Vba excel пересчет книги

 

Иван Фильченков

Пользователь

Сообщений: 208
Регистрация: 27.12.2012

#1

23.07.2016 10:39:24

Доброго всем времени суток.
Прошу помощи в решение проблемки.
Есть макрос, он подставляет значение и выводит на печать определенные листы, выполняет это в цикличности.
Т.е. вставил значение — отправил на печать, следущее вставил — отправил на печать.
Но файл большой и он не успевает обновить все формулы (пересчитать)
Как прописать в макросе после подстановки значения пересчет формул?
Макрос прилагаю

Код
Sub АОСР()

    Dim c As Range, el
    Application.ScreenUpdating = False
    With Sheets("ФормаСети")
        For Each c In .Range(.Range("F57"), .[F57].End(xlDown)).Cells
            Sheets("ФОРМА").Range("DF123") = c.Value
            Sheets(Array("1ГидИз1", "2Гео", "3ГидИз2", "3ГидИз2", "4Тран", "5РазрТрКол", "6ПеОснКол", "7ПеОснКан", "8МонтТруб", "9БетЗам", "10ОбЗасПеТр", "11БетЛот", "12ШтукКол", "13МонтКол", "14ОбрЗасПеКол", "15МонГол", "16ОбрЗасГрТр", "17ОбрЗасГрКол")).Select
            ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                ThisWorkbook.Path & Application.PathSeparator & c.Value & ".pdf", Quality:=xlQualityStandard, _
                IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
        Next
    End With
    Application.ScreenUpdating = True
End Sub
 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

#2

23.07.2016 10:51:22

Если стоит автомат. пересчёт, то перед печатью добавьте строку:

Код
doevents

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

Извините я полный профан в макросах, это перед какой строчкой?

 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

Попробуйте между 7 и 8 строками.

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 
 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#7

23.07.2016 11:16:27

Если формулы только на листе «ФОРМА»:

Скрытый текст

Если формулы на листе «ФОРМА» и на тех листах, которые Вы выделяете:

Скрытый текст

P.S. Я из цикла убрал выделение листов, чтобы каждый раз листы не выделялись, т.к. достаточно выделить один раз.
Коды не тестировал, поэтому возможны опечатки или ошибки.

 

спасибо, сейчас попробую
не не изменяет, не пересчитывает (((

Изменено: Иван Фильченков23.07.2016 11:33:58

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#9

23.07.2016 11:45:45

Пересчет на всех листах активной книги и на всех листах всех других открытых книг:

Код
Sub АОСР()
    Dim c As Range, el
    Application.ScreenUpdating = False
    Sheets(Array("1ГидИз1", "2Гео", "3ГидИз2", "3ГидИз2", "4Тран", "5РазрТрКол", "6ПеОснКол", "7ПеОснКан", "8МонтТруб", "9БетЗам", "10ОбЗасПеТр", "11БетЛот", "12ШтукКол", "13МонтКол", "14ОбрЗасПеКол", "15МонГол", "16ОбрЗасГрТр", "17ОбрЗасГрКол")).Select
    With Sheets("ФормаСети")
        For Each c In .Range(.Range("F57"), .[F57].End(xlDown)).Cells
            Sheets("ФОРМА").Range("DF123") = c.Value
            Application.Calculate
            ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                ThisWorkbook.Path & Application.PathSeparator & c.Value & ".pdf", Quality:=xlQualityStandard, _
                IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
        Next
    End With
    Application.ScreenUpdating = True
End Sub
 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

Попробуйте после пересчёта добавить рекомендуемую мной ранее команду.

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

не пересчитывает, пересчитывает только после первой подстановке (((

 

JayBhagavan

Пользователь

Сообщений: 11833
Регистрация: 17.01.2014

ПОЛ: МУЖСКОЙ | Win10x64, MSO2019x64

Иван Фильченков, сделайте файл-пример и приложите к теме, чтобы не гадать больше. И озвучьте что у Вас за офис (год, разрядность) и ОС.

<#0>
Формула массива (ФМ) вводится Ctrl+Shift+Enter
Memento mori

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#13

23.07.2016 12:11:46

Может быть убрать ScreenUpdating. В этом коде нет обновления формул (то есть это Ваш первоначальный код, только я вынес из цикла выделение листов):

Код
Sub АОСР()
    Dim c As Range, el
    Sheets(Array("1ГидИз1", "2Гео", "3ГидИз2", "3ГидИз2", "4Тран", "5РазрТрКол", "6ПеОснКол", "7ПеОснКан", "8МонтТруб", "9БетЗам", "10ОбЗасПеТр", "11БетЛот", "12ШтукКол", "13МонтКол", "14ОбрЗасПеКол", "15МонГол", "16ОбрЗасГрТр", "17ОбрЗасГрКол")).Select
    With Sheets("ФормаСети")
        For Each c In .Range(.Range("F57"), .[F57].End(xlDown)).Cells
            Sheets("ФОРМА").Range("DF123") = c.Value
            ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
                ThisWorkbook.Path & Application.PathSeparator & c.Value & ".pdf", Quality:=xlQualityStandard, _
                IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
        Next
    End With
End Sub

Изменено: Karataev23.07.2016 12:13:02

 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

Иван Фильченков, Calculate пробовали?

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

Юрий М, да я предлагал Calculate в постах 7 и 9.

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#16

23.07.2016 12:15:16

Цитата
Иван Фильченков написал:
пересчитывает только после первой подстановке (((

а в каком коде пересчитывает? В Вашем исходном или в том, который я предложил? Или при использовании DoEvents?

 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

#17

23.07.2016 12:19:56

Цитата
Karataev написал:
Юрий М, да я предлагал Calculate в постах 7 и 9

Я вижу, но мой вопрос автору темы )

 

Раньше был мой исходный код и он пересчитывался. Сейчас файл большой 20 метров и много связей как и листов и он перестал все пересчитывать.
Офис 13

 

Да делал, пересчета после подстановки нет (

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

Иван Фильченков, а код из поста 13 пробовали? Только у Вас должен быть включен автоматический пересчет формул: вкладка «Формулы» — Параметры вычислений — Автоматически.

 

Юрий М

Модератор

Сообщений: 60575
Регистрация: 14.09.2012

Контакты см. в профиле

#21

23.07.2016 12:35:21

Цитата
Karataev написал: у Вас должен быть включен автоматический пересчет формул

Думаю, что автор проверил это первым делом.

 

Я конечно чайник, но действительно сразу проверил

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

Иван Фильченков, ну так что, Вы тестировали код из поста 13?

 

Попробовал, результат тот же, не пересчитывает ((

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#25

23.07.2016 14:30:42

Может быть какие-нибудь косвенные действия делать, чтобы обновились формулы. Попробуйте такой способ:

Скрытый текст

 

Попробовал, не обновляет.
Странно то что мой исходный файл раньше работал и все обновлялось. Что же может быть такое?? ((

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#27

23.07.2016 14:49:57

А так? Макрос сохраняет файл после каждого изменения ячейки «DF123»:

Скрытый текст

 

Извини за дурацкий вопрос, я в макросах совсем ни как, но он где должен быть записан, сейчас он у меня торчит в Module4. Это может как то сказаться на его работоспособности?
Последний тоже код не обновляет ((

Изменено: Иван Фильченков23.07.2016 15:20:04

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

Вставьте его туда, где у Вас был Ваш код.

 

Karataev

Пользователь

Сообщений: 2306
Регистрация: 23.10.2014

#30

23.07.2016 15:01:14

А вручную, когда Вы изменяете ячейку «DF123», формулы обновляются сейчас?

1068 / 106 / 4

Регистрация: 19.12.2012

Сообщений: 449

1

30.04.2015, 12:16. Показов 14355. Ответов 8


Студворк — интернет-сервис помощи студентам

Тема пока не исследована.
Пока заметил лишь разницу в работе Calculate.

Calculate вызванный с функции прописанной на листе — лист пересчитывает.
Calculate, вызванный с функции какого-нибудь модуля (как например ThisWorkbook.Worksheets(Name).Calculate) — зачастую лист не пересчитывает.

Кто-то с таким сталкивался. Можете объяснить разницу?

Добавлено через 2 часа 41 минуту
Примечание:
не ThisWorkbook.Worksheets(Name).Calculate
а ThisWorkbook.Worksheets(dName).Calculate

потому как может показаться, что пересчет может не идти в связи с другим листов (не тем, который требуется, а тем, что активен).
и все-же такая аномальность есть … где и как — пока не понимаю (не вижу закономерности) … и возникает такая штука только при отработке события открытия книги (и то- не всегда и не везде) …

может кто сталкивался …



0



1068 / 106 / 4

Регистрация: 19.12.2012

Сообщений: 449

30.04.2015, 12:33

 [ТС]

3

Не понял смысла вашего сообщения. Может вы что-то хотели сказать не по теме?



0



5561 / 1367 / 150

Регистрация: 08.02.2009

Сообщений: 4,107

Записей в блоге: 30

30.04.2015, 12:43

4

Да стараюсь по теме. У нас в коммерческом листы пересчитывают по 10 раз на дню.

Просто хочу представить, как в рабочей обстановке разглядеть такие тонкости.



0



1068 / 106 / 4

Регистрация: 19.12.2012

Сообщений: 449

30.04.2015, 13:09

 [ТС]

5

Задача: При загрузке файла необходимо пересчитать все формулы книги (в книге от 2 до 10 листов).
Ограничение: Перехватывать управление книгой при загрузке до момента полного пересчета — нельзя т.к. процесс отнимет много времени и пользователь останется недоволен …
P.S. Замечено, что пользователь зачастую переходит на какой-то лист и потом подолгу там сидит изучая данные этого листа.
Вывод: как только открылась книга — начать перманентно/прозрачно пересчитывать все формулы книги на всех ее листах — параллельно работе пользователя (DoEvents), а при переходе пользователя на какой-то лист — лочить книгу и принудительно пересчитывать именно этот лист (если он пока не был полностью пересчитан прежним переходом или функцией «параллельго» пересчета) … и после пересчета этого активного листа — продолжать работу по перманентному/прозрачному пересчету всех других листов …

Проблема: Если на событие активации листа вешать принудительный пересчет, то:
— если вызывается функция модуля, которой передается имя этого листа и пересчет вызывается как ThisWorkbook.Worksheets(dName$).Calculate — лист иногда! не пересчитывается (и формулы листа остаются нулями и НД)
— если вызывать ту же самую функцию, только не из модуля, а из листа (который пересчитывается), только в которой будет написано Calculate (как cacl текущего листа) — все всегда четко пересчитывается

пока не могу понять зависимости такого поведения. просто интересно почему так?! (если разберусь — отпишусь конечно)



0



Night Ranger

Заблокирован

30.04.2015, 18:39

6

Цитата
Сообщение от StepInLik
Посмотреть сообщение

Не понял смысла вашего сообщения. Может вы что-то хотели сказать не по теме?

Наверное у вас нет настроения, относитесь ко всему проще, попробуйте удалить то что вам мешает, перейти на другой офис (2003) сменить комп на более быстрый



0



5561 / 1367 / 150

Регистрация: 08.02.2009

Сообщений: 4,107

Записей в блоге: 30

30.04.2015, 23:23

7

Night Ranger, и вы туда же — забалтывать!

Я по сути сказать что-то ценное не могу, но просто любопытна сама организация труда и такая забота о работниках!

У нас так всё это на уровне самодеятельности.



1



The_Prist

1337 / 308 / 74

Регистрация: 13.11.2008

Сообщений: 635

05.05.2015, 12:56

8

Я, если честно, не совсем понял необходимую последовательность пересчета. То ли Вы хотите в момент общего пересчета книги пересчитывать активный лист, то ли еще что.
Но по собственным наблюдениям — у листа метод Calculate как-то глючит. Не встречал Вашей ситуации, но при создании надстройки из С — этот метод не обнаруживается как рабочий. А через Invoke его вообще нет. Возможно, связано с несколько кривой реализацией самого Invoke, но утверждать не могу. Не было пока времени все это расковыривать. MSDN утверждает, что метод такой у листа есть и работает. И у меня из Excel он реально работает без ошибок. Но в Вашем случае я бы рекомендовал использовать нечто вроде:

Visual Basic
1
Worksheets(1).UsedRange.Calculate



0



1068 / 106 / 4

Регистрация: 19.12.2012

Сообщений: 449

06.05.2015, 11:20

 [ТС]

9

Ответа на проблему пока нет (не занимался).
Но если кому интересно (для полного понимания реализации задачи) — перманентный/прозрачный пересчет производится обходом всех UsedRange — т.е. пока пользователь сидит на каком-то листе, код в параллель ему перебирает все ячейки других листов и по каждой из них делает пересчет (.Cells([каждая]).Calculate) при том, что проверяется флаг листа на его пересчитанность (он меняется на «лист сосчитан = True» при условии принудительного пересчета при активации листа и вызовом Calculate уже листа целиком)

… подумал тут … а можно ли и как узнать — требуется ли пересчет какой-то конкретной ячейки (на уровне Excel’я — он же перестраивает зависимости и помечает, что требуется пересчитать, а что нет)? и как установить такой признак принудительно?



0



Home / VBA / VBA Calculate (Cell, Range, Row, & Workbook)

By default, in Excel, whenever you change a cell value Excel recalculates all the cells that have a calculation dependency on that cell. But when you are using VBA, you have an option to change it to the manual, just like we do in Excel.

calculate-cell-value-using-vba

Using VBA Calculate Method

You can change the calculation to the manual before you start a code, just like the following.

Application.Calculation = xlManual

When you run this code, it changes the calculation to manual.

using-vba-calculate-method

And at the end of the code, you can use the following line of code to switch to the automatic.

Application.Calculation = xlAutomatic
switch-to-automatic-using-vba

You can use calculation in the following way.

calculation-method-vba-code
Sub myMacro()
    Application.Calculation = xlManual   
        'your code goes here   
    Application.Calculation = xlAutomatic
End Sub

Calculate Now (All the Open Workbooks)

If you simply want to re-calculate all the open workbooks, you can use the “Calculate” method just like below.

Calculate

Use Calculate Method for a Sheet

Using the following way, you can re-calculate all the calculations for all the

ActiveSheet.Calculate
Sheets("Sheet1").Calculate

The first line of code re-calculates for the active sheet and the second line does it for the “Sheet1” but you can change the sheet if you want.

Calculate for a Range or a Single Cell

In the same way, you can re-calculate all the calculations for a particular range or a single cell, just like the following.

Sheets("Sheet1").Range("A1:A10").Calculate
Sheets("Sheet1").Range("A1").Calculate

Пересчет отдельных формул в рабочей книге

Подробности
Создано 04 Февраль 2018
Содержание
Решение задачи
Константы:
Процедура пересчета диапазонов:

Типичная проблема при работе с большими или очень большими файлами Excel — это слишком сильное замедление при выполнении любых расчетов. Стандартной рекомендацией при этом является переключение Excel на ручной режим пересчета (ленат Формулы Параметры вычислений). Но зачастую рабочая книга построена таким образом, что хотелось бы видеть автоматическое обновление каких-то оперативных данных и сумм непосредственно при вводе. Нажимать все время F9, во-первых, неудобно, во-вторых, расчет каких-то итоговых таблиц вообще можно отложить на неопределенный срок — занимать время на их пересчет совсем не требуется. Иногда помогает пересчет не всей рабочей книги, а только активного листа — Shift+F9. Но и это не всегда удобно, и зависит от степени сложности связей между листами.

Кардинальным способом решения проблемы является пересчет итоговых таблиц по определенному событию, все остальное время там будут храниться только значения. Шаблон расчетных формул можно хранить в скрытом диапазоне. Т.е. рабочий файл можно оставить в автоматическом режиме расчетов для ввода каких-то данных. А для расчета итоговых таблиц необходимо будет вызывать макрос VBA. Очевидно, что для эффективности данного пересчитываемые таблицы должны иметь большое количество однотипных формул.

Решение задачи

Макрос делает следуеющее:

  1. Проходит по всем ячейкам столбца «Признак»
  2. Если «Признак»=1, то во все «Столбцы» таблицы вставлются формулы из строки «Формула»
  3. После заполнения всех формул пересчитывается рабочий лист
  4. После завершения расчета все вставленные формулы заменяются на значения
  5. Во вложении пример решения подобной задачи.

Пример реализации макроса на VBA во вложении к статье.

Константы:

Для простоты в примере все ссылки на столбцы и строки заданы через константы — см.проект VBA. В реальном проекте лучше заменить константы на переменные, ссылающиеся на именованные диапазоны рабочей книги.

Const colBegFormula As Long = 2
Const colEndFormula As Long = 9
Const colFlag As Long = 11
Const rowBegData As Long = 5
Const rowEndData As Long = 18
Const rowFormulas As Long = 19

Процедура пересчета диапазонов:

Private Sub RecalcFormulas(rngData As Excel.Range, rngFlags As Excel.Range, rngFormulas As Excel.Range)
    Dim calcMode As Excel.XlCalculation
    Dim wsh As Excel.Worksheet
    Dim rngRowData As Excel.Range
    Dim idx As Long, curRow As Long
    
On Error GoTo Err_
    calcMode = SaveCalcMode()
    Set wsh = rngData.Worksheet
    
    ' fill formulas
    For idx = 1 To rngData.Rows.Count
        curRow = rngData.Rows(idx).Row
        If (rngFlags.Cells(idx) = 1) Then
            Set rngRowData = wsh.Range(wsh.Cells(curRow, rngFormulas.Columns(1).Column), _
                        wsh.Cells(curRow, rngFormulas.Columns(rngFormulas.Columns.Count).Column))
            rngFormulas.Copy
            rngRowData.PasteSpecial xlPasteFormulas
        End If
    Next
    
    wsh.Calculate 'Application.Calculate
    
    ' fill values
    For idx = 1 To rngData.Rows.Count
        curRow = rngData.Rows(idx).Row
        If (rngFlags.Cells(idx) = 1) Then
            Set rngRowData = wsh.Range(wsh.Cells(curRow, rngFormulas.Columns(1).Column), _
                        wsh.Cells(curRow, rngFormulas.Columns(rngFormulas.Columns.Count).Column))
            rngRowData.Copy
            rngRowData.PasteSpecial xlPasteValues
        End If
    Next
    
    RestoreCalcMode calcMode
    Exit Sub
Err_:
    MsgBox Err.Description
    RestoreCalcMode calcMode
End Sub

Для сложных файлов лучше пересчитывать не только активный лист (см.строку wsh.Calculate), а все открытые рабочие книги — замените строку на Application.Calculate

Процедуры SaveCalcMode и RestoreCalcMode необходимы для корректного возврата текущего режима расчета Excel (автоматический или ручной). Туда же можно добавить скрытие визуализации выполнения макроса через задание параметра Application.ScreenUpdating = False (скрывает обновление экрана) и Application.ScreenUpdating = True (восстанавливает обновление экрана).

Смотри также

» Класс сохранения настроек Excel

В данной статье описывается небольшой, но очень удобный класс для сохранения и автоматического восстановления таких параметров…

» Основные принципы оптимизации работы в электронных таблицах

Знание специальных приемов работы в электронных таблицах Excel позволяет в разы сократить время разработки моделей, повысить…

» Надстройки Excel

Те, кто программирует на VBA для Excel, в определенный момент задумываются над распространением своих приложений в качестве независимых…

» Автоматизация в Excel

Создание программного кода для автоматизации определенных процедур открывает практически безграничные возможности по развитию и…

» Доступ к данным Excel через ADO

Данный пример демонстрирует работу с файлами Excel через интерфейс доступа к данным ADO (ActiveX Data Objects). Объекты ADO входят в состав Windows,…


Re[9]: Пересчет формул в Excel

От:

PA

 
Дата:  05.06.07 13:13
Оценка:

23 (2)

Как вариант — пересчитывать только ячейки с определённой формулой:

Dim r As Range
    
For Each r In Application.Cells.SpecialCells(xlCellTypeFormulas, xlTextValues)
    If InStr(1, r.Formula, "=НужнаяФормула()", vbTextCompare) > 0 Then
        r.Dirty
    End If
Next
If Application.Calculation = xlCalculationManual Then Application.Calculate


Re[3]: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  04.06.07 12:56
Оценка:

14 (2)

Здравствуйте, Аноним, Вы писали:

А>так я тоже пробовал, у меня 10 страничек и на каждой по 10 000 формул и когда начинается любые изменения на страничке всё невероятно медленно перерисовываются. Есть ещё предложения?

1) Если речь именно о данных из базы, возможно, имеет смысл использовать QueryTable — такая разновидность связанных таблиц — лист привязывается к данным, может обновляться автоматически или по запросу.

2) Если формулы, то использовать формулы массива, поскольку по каждой формулы идет вызов, лучше если сразу для нескольких ячеек делается. Обычно, если много формул, они именно относятся к однородным данным, которые можно передать в виде массива, и в виде массива вернуть результат.

3) Я в таких случаях предлагаю довольно нудную конструкцию, предполагающую переход на ручной пересчет и пересчет только конкретных формул. Имеет смысл, если функции в одной книге собраны функции из базы, например, а других нет. Примерно это выглядит так:

При открытии книги для всех листов свойство EnableCalculation устанавливается в False, а пересчет в Автоматический
Перед сохранением книги пересчет устанавливается в ручной, а после сохранения восстанавливается автоматический, чтобы не влиять на другие книги.

Таким образом, мы добиваемся того, что автоматически вообще ничего не пересчитывается.

А потом, для расчета конкретного диапазона используется конструкция следующего типа, то есть в любой момент автоматический расчет отключен, поэтому ничего лишнего не происходит. Такой «шлюз» образуется.

    Application.Calculation = xlCalculationManual
    wks.EnableCalculation = True
    wks.Range("D2:D500").Calculate
    wks.EnableCalculation = False
    Application.Calculation = xlCalculationAutomatic

Но это вариант на крайний случай. По 10 000 формул — первое — это попробовать свести их к формулам массива.

Пользователь — друг программиста!

От: Аноним

 
Дата:  04.06.07 10:33
Оценка:

Я создал пару формул в Excel ( UDF ). Эти формулы подгружают данные с сервера и не зависят от других ячеек. Какой код VBA в Excel может пересчитать значения этих формул для активной книги с сервера принудительно ( данные поменялись только на сервере и Excel об этом «не знает» ).
Обычный Calculate не помогает ( он пересчитывает только если формула зависит от других ячеек, которые поменялись), CalculateAll помогает, но он пересчитывает во всех книгах Excel — так не подходит.


Re: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  04.06.07 10:40
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Я создал пару формул в Excel ( UDF ). Эти формулы подгружают данные с сервера и не зависят от других ячеек. Какой код VBA в Excel может пересчитать значения этих формул для активной книги с сервера принудительно ( данные поменялись только на сервере и Excel об этом «не знает» ).

А>Обычный Calculate не помогает ( он пересчитывает только если формула зависит от других ячеек, которые поменялись), CalculateAll помогает, но он пересчитывает во всех книгах Excel — так не подходит.

см. Application.Volatile в начале функции, тогда будут пересчитываться по Calculate

Пользователь — друг программиста!


Re[2]: Пересчет формул в Excel

От: Аноним

 
Дата:  04.06.07 11:40
Оценка:

так я тоже пробовал, у меня 10 страничек и на каждой по 10 000 формул и когда начинается любые изменения на страничке всё невероятно медленно перерисовываются. Есть ещё предложения?

Здравствуйте, Elena_, Вы писали:

E_>Здравствуйте, Аноним, Вы писали:


А>>Я создал пару формул в Excel ( UDF ). Эти формулы подгружают данные с сервера и не зависят от других ячеек. Какой код VBA в Excel может пересчитать значения этих формул для активной книги с сервера принудительно ( данные поменялись только на сервере и Excel об этом «не знает» ).

А>>Обычный Calculate не помогает ( он пересчитывает только если формула зависит от других ячеек, которые поменялись), CalculateAll помогает, но он пересчитывает во всех книгах Excel — так не подходит.

E_>см. Application.Volatile в начале функции, тогда будут пересчитываться по Calculate


Re[4]: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  04.06.07 13:21
Оценка:

Здравствуйте, Elena_, Вы писали:

И совсем забыла, вариант 4) часто совсем это не должны быть собственно формулы, а структура листа известна заранее. Тогда можно просто сделать выборку, подключаясь из программы, например при помощи ADO, получить курсор, выложить данные на лист функцией CopyFromRecordset — очень быстрая операция, просто данные как массив копируются во внутреннюю память листа. Это очень быстрый вариант, формулы для получения данных из базы нужны только тогда, когда пользователь хочет лист по-своему макетировать каждый раз и по-разному, это довольно редко бывает. Это, на мой взгляд, предпочтительнее QueryTable, так как гибче, хотя qt позволяют настроить автоматическое обновление.

Пользователь — друг программиста!


Re[4]: Пересчет формул в Excel

От: Аноним

 
Дата:  04.06.07 15:30
Оценка:

большое спасибо за большой ответ, но он не подходит
Здравствуйте, Elena_, Вы писали:

E_>Здравствуйте, Аноним, Вы писали:


А>>так я тоже пробовал, у меня 10 страничек и на каждой по 10 000 формул и когда начинается любые изменения на страничке всё невероятно медленно перерисовываются. Есть ещё предложения?


E_>1) Если речь именно о данных из базы, возможно, имеет смысл использовать QueryTable — такая разновидность связанных таблиц — лист привязывается к данным, может обновляться автоматически или по запросу.

знаю есть такое, но у меня пользователи выстраивают данные как им угодно и привязки не подойдут, потому что тогда будет прямая связь Excel — БД, что не приемлимо, у меня идет связь через IIS сервер который отдает xml по запросам из Excel.

E_>2) Если формулы, то использовать формулы массива, поскольку по каждой формулы идет вызов, лучше если сразу для нескольких ячеек делается. Обычно, если много формул, они именно относятся к однородным данным, которые можно передать в виде массива, и в виде массива вернуть результат.

Вместо массива я пользую xml, почти то же самое но проще в связи со спецификой данных. И вот как раз то что xml изменился Excel не знает и когда я жму кнопку «перегрузить», этот внутренний xml перегружается с сервера а данные в формулах не меняются.

E_>3) Я в таких случаях предлагаю довольно нудную конструкцию, предполагающую переход на ручной пересчет и пересчет только конкретных формул. Имеет смысл, если функции в одной книге собраны функции из базы, например, а других нет. Примерно это выглядит так:


E_>При открытии книги для всех листов свойство EnableCalculation устанавливается в False, а пересчет в Автоматический

E_>Перед сохранением книги пересчет устанавливается в ручной, а после сохранения восстанавливается автоматический, чтобы не влиять на другие книги.

E_>Таким образом, мы добиваемся того, что автоматически вообще ничего не пересчитывается.


E_>А потом, для расчета конкретного диапазона используется конструкция следующего типа, то есть в любой момент автоматический расчет отключен, поэтому ничего лишнего не происходит. Такой «шлюз» образуется.

E_>

E_>    Application.Calculation = xlCalculationManual
E_>    wks.EnableCalculation = True
E_>    wks.Range("D2:D500").Calculate
E_>    wks.EnableCalculation = False
E_>    Application.Calculation = xlCalculationAutomatic
E_>


E_>Но это вариант на крайний случай. По 10 000 формул — первое — это попробовать свести их к формулам массива.

этот вариант тоже не подходит, потому что он не пересчитает формулы строчкой worksheet.calculate которые зависят от глобального xml, Excel просто не видит что их надо пересчитывать.


Re[5]: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  04.06.07 17:27
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Вместо массива я пользую xml, почти то же самое но проще в связи со спецификой данных. И вот как раз то что xml изменился Excel не знает и когда я жму кнопку «перегрузить», этот внутренний xml перегружается с сервера а данные в формулах не меняются.

Формулы массива — это разновидность формул Excel, которые получают в качестве входных параметров диапазоны (что иногда и обычные формулы получают) и возвращают массивы, которые размещаются в диапазонах Excel. Главная экономия идет за счет того, что один вызов заполняет сразу много ячеек. К xml не имеет вроде бы никакого отношения.

Если xml возвращается по запросам из Excel, можно сразу данные из него просто загрузить на скрытый лист, а формулы привязать к этому листу. Или это так и делается — тогда торможение связано исключительно с количеством пользовательских формул и к базе вообще не имеет отношения? Тогда вопрос в том, как ускорить работу пользовательских формул в книге, а есть база или нет — вообще не при чем? Можно оптимизировать пользовательские формулы различным кэшированием, например. Это кроме формул массива.

Пользователь — друг программиста!


Re[6]: Пересчет формул в Excel

От: Аноним

 
Дата:  05.06.07 06:36
Оценка:

Здравствуйте, Elena_, Вы писали:

E_>Здравствуйте, Аноним, Вы писали:

Уважаемый эксперт, мы совсем отошли от темы. Ведь вопрос был вообще простой — «как принудительно заставить Excel пересчитать формулы».
Application.CalculateAll — не подходит, он пересчитает все книги, этого делать не надо,
*.Calculate — не подходит, он пересчитает только если исходные данные поменялись
Application.Volatile — не подходит, он тормозит
Менять идиалогию и объяснять пользователю что для того чтобы работали данные ему прийдется брать определенный Excel файл с кодом или научить его пользоваться мапингом xml-ячейка, вообще не надо.
Необходимо простое решение задачи: «как принудительно заставить Excel пересчитать формулы»

А>>Вместо массива я пользую xml, почти то же самое но проще в связи со спецификой данных. И вот как раз то что xml изменился Excel не знает и когда я жму кнопку «перегрузить», этот внутренний xml перегружается с сервера а данные в формулах не меняются.


E_>Формулы массива — это разновидность формул Excel, которые получают в качестве входных параметров диапазоны (что иногда и обычные формулы получают) и возвращают массивы, которые размещаются в диапазонах Excel. Главная экономия идет за счет того, что один вызов заполняет сразу много ячеек. К xml не имеет вроде бы никакого отношения.


E_>Если xml возвращается по запросам из Excel, можно сразу данные из него просто загрузить на скрытый лист, а формулы привязать к этому листу. Или это так и делается — тогда торможение связано исключительно с количеством пользовательских формул и к базе вообще не имеет отношения? Тогда вопрос в том, как ускорить работу пользовательских формул в книге, а есть база или нет — вообще не при чем? Можно оптимизировать пользовательские формулы различным кэшированием, например. Это кроме формул массива.


Re[7]: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  05.06.07 09:44
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Уважаемый эксперт, мы совсем отошли от темы. Ведь вопрос был вообще простой — «как принудительно заставить Excel пересчитать формулы».

А>Application.CalculateAll — не подходит, он пересчитает все книги, этого делать не надо,
А>*.Calculate — не подходит, он пересчитает только если исходные данные поменялись
А>Application.Volatile — не подходит, он тормозит
А>Менять идиалогию и объяснять пользователю что для того чтобы работали данные ему прийдется брать определенный Excel файл с кодом или научить его пользоваться мапингом xml-ячейка, вообще не надо.
А>Необходимо простое решение задачи: «как принудительно заставить Excel пересчитать формулы»

Дело в том, что Application.Volatile и есть ответ, и довольно простой («Необходимо простое решение задачи»), но Вы говорите, что он тормозит, поэтому я и предложила другие решения. Тормозит не сам Application.Volatile, это просто указание Excel, что надо пересчитывать эту формулу.

Пользователь — друг программиста!


Re[8]: Пересчет формул в Excel

От: Аноним

 
Дата:  05.06.07 12:08
Оценка:

Здравствуйте, Elena_, Вы писали:

E_>Здравствуйте, Аноним, Вы писали:


А>>Уважаемый эксперт, мы совсем отошли от темы. Ведь вопрос был вообще простой — «как принудительно заставить Excel пересчитать формулы».

А>>Application.CalculateAll — не подходит, он пересчитает все книги, этого делать не надо,
А>>*.Calculate — не подходит, он пересчитает только если исходные данные поменялись
А>>Application.Volatile — не подходит, он тормозит
А>>Менять идиалогию и объяснять пользователю что для того чтобы работали данные ему прийдется брать определенный Excel файл с кодом или научить его пользоваться мапингом xml-ячейка, вообще не надо.
А>>Необходимо простое решение задачи: «как принудительно заставить Excel пересчитать формулы»

E_>Дело в том, что Application.Volatile и есть ответ, и довольно простой («Необходимо простое решение задачи»), но Вы говорите, что он тормозит, поэтому я и предложила другие решения. Тормозит не сам Application.Volatile, это просто указание Excel, что надо пересчитывать эту формулу.

Да решение простое, но Application.Volatile говорит о том что формулу нужно всегда пересчитывать при любых событиях в документе. И тогда например когда у меня в другой книге, связанной с этой начнуться сильные изменения то формулы будут пересчитываться ВСЕ а это больше 100 000 действий которые должно происходить тоько по моей команде.


Re[9]: Пересчет формул в Excel

От:

Elena_

Россия

 
Дата:  05.06.07 13:07
Оценка:

Здравствуйте, Аноним, Вы писали:

А>Да решение простое, но Application.Volatile говорит о том что формулу нужно всегда пересчитывать при любых событиях в документе. И тогда например когда у меня в другой книге, связанной с этой начнуться сильные изменения то формулы будут пересчитываться ВСЕ а это больше 100 000 действий которые должно происходить тоько по моей команде.

Да, так это устроено в Excel. Дело в том, что для задачи получения данных из базы пользовательские функции не слишком подходят, я сама делала подобные решения, и на данный момент уверена в этом. Пользовательские функции по идее должны получать данные, от которых они зависят, в качестве параметров, тогда Excel правильно выстраивает стратегию пересчета. В рамках существующей парадигмы можно только придумывать всякие оптимизирующие трюки.

См. еще ссылку Excel User-Defined Functions и там пункт
UDF not recalculating or always recalculating or calculating in an unexpected sequence. Может быть, что-то оттуда пригодится.

Пользователь — друг программиста!


Re[10]: Пересчет формул в Excel

От: Аноним

 
Дата:  06.06.07 06:36
Оценка:

Здравствуйте, PA, Вы писали:

PA>Как вариант — пересчитывать только ячейки с определённой формулой:

PA>

PA>Dim r As Range
    
PA>For Each r In Application.Cells.SpecialCells(xlCellTypeFormulas, xlTextValues)
PA>    If InStr(1, r.Formula, "=НужнаяФормула()", vbTextCompare) > 0 Then
PA>        r.Dirty
PA>    End If
PA>Next
PA>If Application.Calculation = xlCalculationManual Then Application.Calculate
PA>

Благодарю за ответ, я его немного развил и получил такое элегантное и быстрое решение:
For Each wCurSheet In ActiveWorkbook.Worksheets
wCurSheet.Cells.Dirty
‘ wCurSheet.Calculate — можно убрать если Excel настроен так что идет автоматический пересчет формул
Next

Подождите ...

Wait...

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

Like this post? Please share to your friends:
  • Vba excel перенос ячейки в другую ячейку
  • Vba excel перенос ячеек
  • Vba excel перенос на новую строку
  • Vba excel перенос на другую строку
  • Vba excel перенос данных с одного листа на другой