Альтернатива application.calculation = xlcalculationmanual для ускорения кода mailmerge vba?

Когда мой код запускается и достигает строки application.calculation = xlcalculationmanual, возникает ошибка компиляции, говорящая о том, что метод или элемент данных не найден


У меня есть макрос vba, который просматривает лист значений excel и извлекает эти данные для заполнения полей слияния почты в документе Word.

Макрос выполняется по нажатию командной кнопки. Мне нужна была помощь, чтобы ускорить код, который выполняется более 15 секунд.

Я добавил несколько строк, чтобы ускорить код (см. ниже), но когда он достигает application.calculation = xlcalculationmanual, возникает ошибка компиляции: метод или элемент данных не найден

Я посмотрел это, и кто-то упомянул об использовании раннего связывания. Поэтому я перешел к справочникам по инструментам и поставил галочку напротив библиотеки MS Excel 16.0. Проблема с calculationmanual осталась.

Как ни странно, запуск кода вручную, а не через командную кнопку, происходит намного быстрее. Есть ли альтернативный метод ускорения моего кода слияния без руководства по расчету или это проблема с командными кнопками?


Private Sub CommandButton1_Click()

'speed up of code    
Application.ScreenUpdating = False    
Application.DisplayStatusBar = False    
Activesheet.DisplayPageBreaks = False    
Application.Calculation = xlCalculationManual    
Application.EnableEvents = False    
'end of speed up of code

  Dim numRecord As Integer
  Dim myDCR As String

myDCR = InputBox("Enter DCR:")    
Set dsMain = ActiveDocument.MailMerge.DataSource

With ActiveDocument.MailMerge
 .DataSource.ActiveRecord = wdFirstRecord
End With

If dsMain.FindRecord(FindText:=myDCR, Field:="DCR") = True Then
    numRecord = dsMain.ActiveRecord
End If

Application.ScreenUpdating = True    
Application.DisplayStatusBar = True    
Activesheet.DisplayPageBreaks = True    
Application.Calculation = xlCalculationAutomatic    
Application.EnableEvents = True

End Sub

Я ожидаю, что код запустится и извлечет данные из Excel и заполнит слово doc менее чем за 3 секунды.


person James Knight    schedule 19.04.2019    source источник
comment
Где твой макрос? Если это в Word, и если вы не установили свои параметры для требования объявления переменной, то это сообщение правильное.   -  person Ron Rosenfeld    schedule 19.04.2019
comment
Спасибо. Я только что поставил галочку, чтобы разрешить объявление переменной, и возникает та же ошибка. Я искренне думаю, что эта команда Application.Calculation = xlCalculationManual может оказаться бесполезной для ускорения моего кода. Могут быть альтернативы, но я понятия не имею, что это такое.   -  person James Knight    schedule 23.04.2019
comment
Если все, что вы делаете, это отмечаете опцию, это влияет только на новые модули. Для существующих модулей вам необходимо поместить Option Explicit вверху модуля и, пожалуйста, ответьте на мой первый вопрос.   -  person Ron Rosenfeld    schedule 23.04.2019
comment
Спасибо за помощь, Рон. Макрос запускается из msword, но источником данных mailmerge является excel. Он извлекает данные из Excel для заполнения полей MS Word. Следуя вашему совету, чтобы включить опцию явно в качестве дополнительной строки над всем моим кодом, все равно дает ту же ошибку компиляции CalculationManual. По вашему опыту, какие команды вы обычно используете для ускорения написания кода?   -  person James Knight    schedule 23.04.2019
comment
Чтобы ускорить макрос, вам нужно оптимизировать алгоритм для среды. Используемый вами метод может помочь ускорить операции в Excel, но он не подходит для Word (а часто даже для Excel есть лучшие способы). Я не так хорошо знаком с Word, но я бы предложил что-то вроде ответа @macropod, где ваш код по-прежнему запрашивает ввод данных пользователем, но использует этот ввод для настройки фильтра слияния (или поля SKIPIF в Word.   -  person Ron Rosenfeld    schedule 23.04.2019


Ответы (3)


Предположительно, поскольку вы выполняете слияние, вашим приложением является Word, для которого не существует такого понятия, как Application.Calculation. Это команда Excel, и вы не используете Excel. Кроме того, если все, что вы пытаетесь сделать, это ограничить слияние определенным набором записей, то нет необходимости в каком-либо VBA. Вы можете использовать фильтры слияния или поле SKIPIF, закодированное следующим образом:

{SKIPIF {MERGEFIELD DCR}<> {FILLIN "Enter DCR:" \o}}

где фигурные скобки поля (например, {}) создаются как пары в основном документе mailmerge с помощью Ctrl-F9.

person macropod    schedule 19.04.2019
comment
Спасибо за Ваш ответ. Цель VBA — предложить пользователю ввести число, чтобы макрос заполнил несколько полей, извлеченных из определенного набора записей. Поэтому поля будут меняться в зависимости от числа, которое ввел пользователь. Поэтому я не мог ограничить поля только DCR в приведенном выше примере; есть 10 других полей, извлеченных из 10 столбцов записей данных на листе Excel. - person James Knight; 23.04.2019
comment
Как указано в моем предыдущем ответе, нет необходимости в VBA. Вы можете хотя бы попробовать поле SKIPIF... Если вы хотите фильтровать по нескольким критериям, у вас могут быть отдельные поля SKIPIF для каждого. - person macropod; 23.04.2019

У вас также нет обработки ошибок в вашем коде. Если ваш код сломается после того, как вы начали вносить все изменения в настройки приложения, нет ничего, что могло бы восстановить эти настройки до того состояния, в котором они должны быть. Это может оставить ваше приложение в ОЧЕНЬ плохом состоянии. Вот что вы должны делать:

 Private Sub CommandButton1_Click()

    'speed up of code    
    On Error GoTo ExitErr
       Application.ScreenUpdating = False    
       Application.DisplayStatusBar = False    
       Activesheet.DisplayPageBreaks = False    
       Application.Calculation = xlCalculationManual    
       Application.EnableEvents = False    
    'end of speed up of code

   Dim numRecord As Integer
   Dim myDCR As String

       myDCR = InputBox("Enter DCR:")    
       Set dsMain = ActiveDocument.MailMerge.DataSource

       With ActiveDocument.MailMerge
        .DataSource.ActiveRecord = wdFirstRecord
       End With

       If dsMain.FindRecord(FindText:=myDCR, Field:="DCR") = True Then
           numRecord = dsMain.ActiveRecord
       End If

    ExitErr:
       Application.ScreenUpdating = True    
       Application.DisplayStatusBar = True    
       Activesheet.DisplayPageBreaks = True    
       Application.Calculation = xlCalculationAutomatic    
       Application.EnableEvents = True

    End Sub
person Frank Ball    schedule 19.04.2019
comment
Спасибо за ответ, но это не решает проблему, указанную в сообщении. Ошибка компиляции для calculatemanual все еще остается. Если бы я пошел дальше и удалил calculate.manual, макрос все равно будет работать медленно, поэтому мне нужен альтернативный способ ускорения моего кода. - person James Knight; 23.04.2019
comment
Как сказал макропод, ошибка компиляции вызвана вызовом явной функции Excel в приложении Word. Вам нужно получить приложение Excel как объект в вашем коде, а затем внести изменения в настройки этого объекта. Я никогда не возился с вызовом другого приложения с помощью VBA, но вы должны быть в состоянии найти что-то там о вызове Excel из макроса в Word. - person Frank Ball; 24.04.2019
comment
Спасибо, Фрэнк, это может быть суть дела. Мне придется прочитать и научиться вызывать excel из слова. Хотя сокращение количества данных для просеивания дало мне результат, который я искал. - person James Knight; 24.04.2019

Спасибо за все ваши ответы, когда вы изучали SKIPIF для реализации ответа макропода. Я придумал очень простое интуитивно понятное решение.

Решение. Архивируйте половину таблицы, чтобы в ней было вдвое меньше строк, чем раньше. Электронная таблица содержала данные за 2016–2019 годы, но не было необходимости иметь под рукой данные до 2019 года.

Причина, по которой я думаю, что это сработало: вместо того, чтобы ускорить мой макрос, добавив больше кода, я вместо этого сократил объем данных, которые Excel должен просеивать.

Тот же результат, но другой способ его обойти. Теперь макрос запускается довольно быстро с командной кнопки.

person James Knight    schedule 24.04.2019