Как обновить экран в excel

1014 / 118 / 2

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

Сообщений: 1,113

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

1

06.02.2017, 02:10. Показов 3824. Ответов 3


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

Допустим, я отключил обновление Application.screenupdating = false
Но потом мне нужно в определенный момент просто обновить экран, чтобы посмотреть, — чего там у меня натворилось. И ничего дальше не делать. Вычислений в книге нет.
Есть ли такая команда обновления экрана?



0



RefSol

503 / 246 / 74

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

Сообщений: 742

06.02.2017, 06:11

2

AndreA SN, попробуйте сделать так:

Visual Basic
1
2
3
4
5
Application.screenupdating = true  
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = true 
sleep(100)
Application.screenupdating = false



0



bedvit

1024 / 227 / 21

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

Сообщений: 971

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

06.02.2017, 12:53

3

Имхо должно быть достаточно:

Visual Basic
1
Application.ScreenUpdating = 1: Application.ScreenUpdating = 0



0



Prisioner

6 / 6 / 3

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

Сообщений: 21

06.02.2017, 13:46

4

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

мне нужно в определенный момент просто обновить экран, чтобы посмотреть, — чего там у меня натворилось. И ничего дальше не делать.

Если нужно именно остановить выполнение кода и посмотреть что происходит, а потом решить — продолжать или нет, тогда вот такая конструкция:

Visual Basic
1
2
3
Application.ScreenUpdating = True
Stop
Application.ScreenUpdating = False

При этом выскочит окошко такое же как при ошибке, но будет активны кнопки «Continue», которая продолжит выполнение кода и кнопка «End», которая прервет процедуру.



0



Мой инструмент Excel выполняет длинную задачу, и я стараюсь быть добрым к пользователю, предоставляя отчет о ходе выполнения в строке состояния или в некоторой ячейке на листе, как показано ниже. Но экран не обновляется или не останавливается в какой-либо точке (например, на 33%). Задача в конечном итоге завершается, но индикатор выполнения бесполезен.

Что я могу сделать, чтобы принудительно обновить экран?

For i=1 to imax ' imax is usually 30 or so
    fractionDone=cdbl(i)/cdbl(imax)
    Application.StatusBar = Format(fractionDone, "0%") & "done..."
    ' or, alternatively:
    ' statusRange.value = Format(fractionDone, "0%") & "done..."

    ' Some code.......

Next i

Я использую Excel 2003.

4b9b3361

Ответ 1

Добавьте функцию DoEvents внутри цикла, см. ниже.

Вы также можете убедиться, что строка состояния отображается пользователю и reset, когда ваш код завершен.

Sub ProgressMeter()

Dim booStatusBarState As Boolean
Dim iMax As Integer
Dim i As Integer

iMax = 10000

    Application.ScreenUpdating = False
''//Turn off screen updating

    booStatusBarState = Application.DisplayStatusBar
''//Get the statusbar display setting

    Application.DisplayStatusBar = True
''//Make sure that the statusbar is visible

    For i = 1 To iMax ''// imax is usually 30 or so
        fractionDone = CDbl(i) / CDbl(iMax)
        Application.StatusBar = Format(fractionDone, "0%") & " done..."
        ''// or, alternatively:
        ''// statusRange.value = Format(fractionDone, "0%") & " done..."
        ''// Some code.......

        DoEvents
        ''//Yield Control

    Next i

    Application.DisplayStatusBar = booStatusBarState
''//Reset Status bar display setting

    Application.StatusBar = False
''//Return control of the Status bar to Excel

    Application.ScreenUpdating = True
''//Turn on screen updating

End Sub

Ответ 2

Текстовые поля в листах иногда не обновляются
когда их текст или форматирование изменены, и даже
команда DoEvent не помогает.

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

Следующие команды, похоже, делают трюк:

- ActiveSheet.Calculate    
- ActiveWindow.SmallScroll    
- Application.WindowState = Application.WindowState

Ответ 3

Поместите вызов DoEvents в цикл.

Это повлияет на производительность, поэтому вы можете просто вызвать ее только на каждой, скажем, на 10-й итерации.
Однако, если у вас всего 30, это вряд ли проблема.

Ответ 4

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

Application.ScreenUpdating = False
Application.EnableEvents = False

и положим это как конец

Application.ScreenUpdating = True
Application.EnableEvents = True

Я обнаружил, что это часто ускоряет работу любого кода, с которым я работаю, так что необходимость предупредить пользователя о прогрессе не требуется. Это просто идея для вас попробовать, и ее эффективность в значительной степени зависит от вашего листа и расчетов.

Ответ 5

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

UserForm не будет обновляться в некоторых случаях, потому что DoEvents будет запускать события; однако Repaint обновит UserForm, и пользователь увидит изменения на экране, даже если другое событие сразу же следует за предыдущим событием.

В коде UserForm это просто:

Me.Repaint

Ответ 6

Напишите DoEvents непосредственно перед строкой, в которой вы обновляете пользовательский интерфейс, она должна работать.

 

ran

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

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

Приветствую!  
Помогите разобраться с непонятным  
Private Sub Worksheet_Change(ByVal Target As Range)  
   Application.ScreenUpdating = False  
   If Target.Count > 1 Then Exit Sub  
   If Not Intersect(Target, Range(«A1»)) Is Nothing Then Exit Sub  
End Sub  
Если изменить А1, то все продолжает работать, а если скопировать и вставить 2 ячейки, то требуется принудительное включение обновления экрана.

 

Юрий М

Модератор

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

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

А всё потому, что строка Application.ScreenUpdating = False срабатывает до принудительного выхода из процедуры (Then Exit Sub). А где включение?

 

The_Prist

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

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

Профессиональная разработка приложений для MS Office

А что непонятного? Вы обновление отключаете, а обратно не включаете. Я не раз писал уже, что лучше возвращать занчения изменных параметров и свойств.  

  Private Sub Worksheet_Change(ByVal Target As Range)  
If Target.Count > 1 Then Exit Sub  
If Not Intersect(Target, Range(«A1»)) Is Nothing Then Exit Sub  
Application.ScreenUpdating = False  
‘здесь код  
Application.ScreenUpdating = 1  
End Sub

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ran

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

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

А нигде!  
В том и вопрос — почему в одном случае продолжает работать, а во втором — нет!?

 

Юрий М

Модератор

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

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

А мне ещё вот это непонятно:  
If Not Intersect(Target, Range(«A1»)) Is Nothing Then Exit Sub  
При изменении в ячейке А1 НИЧЕГО не произойдёт. Кроме выхода из процедуры, конечно.

 

Юрий М

Модератор

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

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

{quote}{login=RAN}{date=03.12.2011 04:01}{thema=}{post}почему в одном случае продолжает работать, а во втором — нет!?{/post}{/quote}Смотрите:    
Вы отключили обновление:  
Application.ScreenUpdating = False  
принудительно вышли, если более одной ячейки:  
If Target.Count > 1 Then Exit Sub  
а обновление не включили.

 

The_Prist

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

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

Профессиональная разработка приложений для MS Office

{quote}{login=RAN}{date=03.12.2011 03:44}{thema=Обновление экрана}{post}а если скопировать и вставить 2 ячейки, то требуется принудительное включение обновления экрана.{/post}{/quote}Вопрос на засыпку: что делает эта строка?  
If Target.Count > 1 Then Exit Sub  

  Для общего понимания: если Вы вышли из процедуры, завершая её логически, т.е. дойдя до End Sub, то VBA сам возвращает значение Application.ScreenUpdating в True. Если же Вы принудительно завершили процедуру — то…короче ничего никуда не возвращается.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ran

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

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

Но ведь здесь в обоих случаях принудительное завершение процедуры!  
Я специально удалил весь код, оставив только строки принудительного выхода.  
Если выходить по строке  
If Not Intersect(Target, Range(«A1»)) Is Nothing Then Exit Sub  
то Application.ScreenUpdating возвращается в True, а если по строке  
If Target.Count > 1 Then Exit Sub  
то нет.  
Вопрос возник в процессе разбирательства с кодом, превая строка которого  
Application.ScreenUpdating = False  
последняя  
Application.ScreenUpdating = True  
а внутри кода — прерывания.

 

nerv

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

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

Всем добрый день)  
Объясните мне, пожалуйста, зачем включать обновление экрана : )  
Запустите два раза.  

  Sub io()  
With Application  
   MsgBox .ScreenUpdating ‘ читаем  
   .ScreenUpdating = False ‘ изменяем  
   MsgBox .ScreenUpdating ‘ читаем  
End With  
End Sub

 

Юрий М

Модератор

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

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

Запустил — и что? Переключается.

 

Юрий М

Модератор

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

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

{quote}{login=RAN}{date=03.12.2011 04:34}{thema=}{post}  
Вопрос возник в процессе разбирательства с кодом, превая строка которого  
Application.ScreenUpdating = False  
последняя  
Application.ScreenUpdating = True  
а внутри кода — прерывания.{/post}{/quote}А где в Вашем примере Application.ScreenUpdating = True?

 

nerv

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

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

>Запустите два раза.  

  Первый запуск (макроса):  
True ‘ проверяем  
‘ отключаем <—  
False ‘ да, отключено  

  Второй  
True ‘ проверяем. Включено. А ведь мы его отключали)  
False

 

Юрий М

Модератор

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

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

{quote}{login=nerv}{date=03.12.2011 04:45}{thema=}{post}А ведь мы его отключали)  
False{/post}{/quote}А теперь читаем Димин пост от 03.12.2011, 16:14

 

ran

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

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

Да нет его!  
Я знаю, что надо вставлять включение.  
Но меня интересует не это, а именно тот вопрос, который я задал!  

  Может конечно это мой локальный глюк, но у меня после выхода по строке  
If Target.Count > 1 Then Exit Sub  
возможность попасть на любой лист Excel появляется только после выполнения  
Application.ScreenUpdating = True

 

Юрий М

Модератор

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

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

{quote}{login=RAN}{date=03.12.2011 04:51}{thema=}{post}возможность попасть на любой лист Excel появляется только после выполнения Application.ScreenUpdating = True{/post}{/quote}Покажите файл ТОЛЬКО с этим фрагментом.

 

Пытливый

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

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

Ну так The_Prist так и написал:  
Если процедура завершается «естественным путем» через End Sub, то обновление включается автоматом.  
Если «неестественным» — через Exit Sub автоматического включения обновления не происходит.

Кому решение нужно — тот пример и рисует.

 

nerv

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

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

{quote}{login=Юрий М}{date=03.12.2011 04:50}{thema=Re: }{post}{quote}{login=nerv}{date=03.12.2011 04:45}{thema=}{post}А ведь мы его отключали)  
False{/post}{/quote}А теперь читаем Димин пост от 03.12.2011, 16:14{/post}{/quote}Как плохо, что я не умею читать!))) Спасибо, понял : )

 

Юрий М

Модератор

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

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

{quote}{login=Пытливый}{date=03.12.2011 04:54}{thema=}{post}Ну так The_Prist так и написал{/post}{/quote}Мало ли что написал, Главное — прочитать :-) А у Саши утро.

 

ran

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

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

 

Юрий М

Модератор

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

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

Что нужно выполнить, чтобы «сломалось»?

 

nerv

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

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

Пытливый, Юрий, а теперь скажите мне почему здесь результат тот же самый)  
Не утро, просто с одного языка на другой пока еще туго переключаюсь) Параллельно на js сижу мастерю : )  

  Sub io()  
With Application  
   Debug.Print .ScreenUpdating  
   .ScreenUpdating = False  
   Exit Sub  
End With  
End Sub

 

ran

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

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

Скопировать и вставить [b5:b6]

 

Юрий М

Модератор

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

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

{quote}{login=RAN}{date=03.12.2011 05:03}{thema=}{post}Скопировать и вставить [b5:b6]{/post}{/quote}Скопировал, вставил — что дальше?

 

ran

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

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

Юрий М  
А что произошло?  
Просто выход? Есть возможность попасть на лист? У меня — нет.

 

The_Prist

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

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

Профессиональная разработка приложений для MS Office

{quote}{login=RAN}{date=03.12.2011 05:03}{thema=}{post}Скопировать и вставить [b5:b6]{/post}{/quote}Здесь ДВЕ ячейки. А у Вас принудительный выход, если изменение более одной ячейки.

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

Юрий М

Модератор

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

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

{quote}{login=RAN}{date=03.12.2011 05:10}{thema=Re: }{post} Есть возможность попасть на лист? У меня — нет.{/post}{/quote}Не очень понимаю вопрос — я ведь и так на листе это делаю. Куда ещё попасть? :-)

 

The_Prist

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

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

Профессиональная разработка приложений для MS Office

{quote}{login=nerv}{date=03.12.2011 05:00}{thema=Re: }{post}Пытливый, Юрий, а теперь скажите мне почему здесь результат тот же самый){/post}{/quote}  
Потому что это не событийная процедура.  
Sub io()  
   With Application  
       MsgBox .ScreenUpdating  
       .ScreenUpdating = False  
       MsgBox .ScreenUpdating  
       Exit Sub  
   End With  
End Sub  

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

Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы…

 

ran

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

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

Давайте попробую еще раз объяснить.  
Добавляю в код первой строкой  
MsgBox Application.ScreenUpdating  
Сколько я бы ни менял значение в [A1], получаю MsgBox True, не смотря на принудительный выход.
Но стоит мне скопировать 2 ячейки — можно мышем по листу щелкать до посинения, ничего не происходит (в ячейку попасть не могу, курсор — стрелка) до того, как в VBA выполню  
Application.ScreenUpdating = True

 

nerv

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

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

Дмитрий, спасибо за участие) Но если честно, то я не понял : )  
Правильно ли я понимаю, что в коде ниже оно должно отключаться и не включаться?  
Если нет, то, пожалуйста, приведите пример когда, когда оно не включается)  

  Private Sub Worksheet_SelectionChange(ByVal Target As Range)  
With Application  
   Debug.Print .ScreenUpdating ‘ всегда True  
   .ScreenUpdating = False  
   Exit Sub  
End With  
End Sub

 

Юрий М

Модератор

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

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

#30

03.12.2011 17:49:54

{quote}{login=RAN}{date=03.12.2011 05:25}{thema=}{post}стоит мне скопировать 2 ячейки — можно мышем по листу щелкать до посинения, ничего не происходит (в ячейку попасть не могу, курсор — стрелка) до того, как в VBA выполню  
Application.ScreenUpdating = True{/post}{/quote}У меня такого не происходит — могу сразу после копирования/вставки активировать любую ячейку.

My Excel tool performs a long task, and I’m trying to be kind to the user by providing a progress report in the status bar, or in some cell in the sheet, as shown below. But the screen doesn’t refresh, or stops refreshing at some point (e.g. 33%). The task eventually completes but the progress bar is useless.

What can I do to force a screen update?

For i=1 to imax ' imax is usually 30 or so
    fractionDone=cdbl(i)/cdbl(imax)
    Application.StatusBar = Format(fractionDone, "0%") & "done..."
    ' or, alternatively:
    ' statusRange.value = Format(fractionDone, "0%") & "done..."

    ' Some code.......

Next i

I’m using Excel 2003.

Community's user avatar

asked Sep 17, 2010 at 12:42

Jean-François Corbett's user avatar

Add a DoEvents function inside the loop, see below.

You may also want to ensure that the Status bar is visible to the user and reset it when your code completes.

Sub ProgressMeter()

Dim booStatusBarState As Boolean
Dim iMax As Integer
Dim i As Integer

iMax = 10000

    Application.ScreenUpdating = False
''//Turn off screen updating

    booStatusBarState = Application.DisplayStatusBar
''//Get the statusbar display setting

    Application.DisplayStatusBar = True
''//Make sure that the statusbar is visible

    For i = 1 To iMax ''// imax is usually 30 or so
        fractionDone = CDbl(i) / CDbl(iMax)
        Application.StatusBar = Format(fractionDone, "0%") & " done..."
        ''// or, alternatively:
        ''// statusRange.value = Format(fractionDone, "0%") & " done..."
        ''// Some code.......

        DoEvents
        ''//Yield Control

    Next i

    Application.DisplayStatusBar = booStatusBarState
''//Reset Status bar display setting

    Application.StatusBar = False
''//Return control of the Status bar to Excel

    Application.ScreenUpdating = True
''//Turn on screen updating

End Sub

Ben McCormack's user avatar

Ben McCormack

31.8k46 gold badges145 silver badges221 bronze badges

answered Sep 17, 2010 at 16:04

Robert Mearns's user avatar

Robert MearnsRobert Mearns

11.8k3 gold badges38 silver badges42 bronze badges

2

Text boxes in worksheets are sometimes not updated
when their text or formatting is changed, and even
the DoEvent command does not help.

As there is no command in Excel to refresh a worksheet
in the way a user form can be refreshed, it is necessary
to use a trick to force Excel to update the screen.

The following commands seem to do the trick:

- ActiveSheet.Calculate    
- ActiveWindow.SmallScroll    
- Application.WindowState = Application.WindowState

brettdj's user avatar

brettdj

54.6k16 gold badges113 silver badges176 bronze badges

answered Dec 19, 2011 at 12:37

Jan Petersen's user avatar

2

Put a call to DoEvents in the loop.

This will affect performance, so you might want to only call it on each, say, 10th iteration.
However, if you only have 30, that’s hardly an issue.

answered Sep 17, 2010 at 13:05

GSerg's user avatar

GSergGSerg

75.3k17 gold badges160 silver badges340 bronze badges

@Hubisans comment worked best for me.

ActiveWindow.SmallScroll down:=1
ActiveWindow.SmallScroll up:=1

answered Nov 27, 2019 at 17:57

FreeSoftwareServers's user avatar

1

Specifically, if you are dealing with a UserForm, then you might try the Repaint method. You might encounter an issue with DoEvents if you are using event triggers in your form. For instance, any keys pressed while a function is running will be sent by DoEvents The keyboard input will be processed before the screen is updated, so if you are changing cells on a spreadsheet by holding down one of the arrow keys on the keyboard, then the cell change event will keep firing before the main function finishes.

A UserForm will not be refreshed in some cases, because DoEvents will fire the events; however, Repaint will update the UserForm and the user will see the changes on the screen even when another event immediately follows the previous event.

In the UserForm code it is as simple as:

Me.Repaint

answered Mar 18, 2013 at 0:29

user2180598's user avatar

This worked for me:

ActiveWindow.SmallScroll down:=0

or more simply:

ActiveWindow.SmallScroll 0

answered Mar 23, 2020 at 17:50

PKanold's user avatar

I couldn’t gain yet the survey of an inherited extensive code. And exact this problem bugged me for months. Many approches with DoEnvents were not helpful.
Above answer helped. Placeing this Sub in meaningful positions in the code worked even in combination with progress bar

Sub ForceScreenUpdate()
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Application.Wait Now + #12:00:01 AM#
    Application.ScreenUpdating = False
    Application.EnableEvents = False
End Sub

answered May 4, 2020 at 20:36

CH Oldie's user avatar

1

In my case: A complex Excel with a graphic simulation using shapes which move. In order to speed up, I wished to update the display only each 10th optimization step. Therefore, every 10th step, I had to switch it back on, followed by a doevents — but I ran into the problems described above. — Now, which is odd: Simply stating the screenupdating=True TWICE, it works. ??!! This is crazy.

        If counteR Mod 10 = 0 Then
            'must state this twice. WHY ??
            Application.ScreenUpdating = True
            Application.ScreenUpdating = True
            DoEvents
            Application.ScreenUpdating = False
        End If

answered Mar 4 at 16:46

Pelton's user avatar

1

This is not directly answering your question at all, but simply providing an alternative. I’ve found in the many long Excel calculations most of the time waiting is having Excel update values on the screen. If this is the case, you could insert the following code at the front of your sub:

Application.ScreenUpdating = False
Application.EnableEvents = False

and put this as the end

Application.ScreenUpdating = True
Application.EnableEvents = True

I’ve found that this often speeds up whatever code I’m working with so much that having to alert the user to the progress is unnecessary. It’s just an idea for you to try, and its effectiveness is pretty dependent on your sheet and calculations.

answered Sep 17, 2010 at 16:05

Michael's user avatar

MichaelMichael

1,6362 gold badges16 silver badges21 bronze badges

0

On a UserForm two things worked for me:

  1. I wanted a scrollbar in my form on the left. To do that, I first had to add an Arabic language to «Change administrative language» in the Language settings of Windows 10 (Settings->Time & Language->Change Administrative Language). The setting is actually for «Change the language of Non-Unicode Programs,» which I changed to Arabic (Algerian). Then in the properties of the form I set the «Right to Left» property to True. From there the form still drew a partial ghost right scrollbar at first, so I also had to add an unusual timed message box:
    Dim AckTime As Integer, InfoBox As Object
    Set InfoBox = CreateObject("WScript.Shell")
    'Set the message box to close after 10 seconds
    AckTime = 1
    Select Case InfoBox.Popup("Please wait.", AckTime, "This is your Message Box", 0)
    Case 1, -1
    End Select
  1. I tried everything to get the screen to redraw again to show the first text box in it’s proper alignment in the form, instead of partially underneath or at least immediately adjacent to the scrollbar instead of 4 pixels to the right where I wanted it. Finally I got this off another Stackoverflow post (which I now can’t find or I would credit it) that worked like a charm:
Me.Frame1.Visible = False
Me.Frame1.Visible = True

answered Apr 7, 2021 at 11:09

socrtwo's user avatar

socrtwosocrtwo

1221 silver badge12 bronze badges

In my case the problem was in trying to make one shape visible and another one invisible on a worksheet.

This is my approach to «inactivating» a button [shape] once the user has clicked it. The two shapes are the same size and in the same place, but the «inactive» version has dimmer colors, which was a good approach, but it didn’t work, because I could never get the screen to update after changing .visible = FALSE to = TRUE and vice versa.

None of the relevant tricks in this thread worked. But today I found a solution that worked for me, at this link on Reddit

Essentially you just call DoEvents twice in immediate succession after the code that makes the changes. Now why? I can’t say, but it did work.

Gass's user avatar

Gass

6,4822 gold badges33 silver badges37 bronze badges

answered Aug 4, 2021 at 12:51

Soproni's user avatar

SoproniSoproni

51 silver badge3 bronze badges

I’ve been trying to solve this Force a screen update on a Worksheet (not a userform) for many years with limited success with
doevents and scrolling etc.. This CH Oldie solutions works best with a slight mod.

I took out the Wait and reset ScreenUpdating and EnableEvents back to true.

This works office excel 2002 through to office 365

Sub Sheet1Mess(Mess1 As String)
    Sheet1.Range("A6").Value = Mess1
    ForceScreenUpdate
End Sub
Sub ForceScreenUpdate()
    Application.ScreenUpdating = True
    Application.EnableEvents = True
   ' Application.Wait Now + #12:00:01 AM#
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub

Gass's user avatar

Gass

6,4822 gold badges33 silver badges37 bronze badges

answered Aug 26, 2021 at 3:23

Rodney Sammut's user avatar

Содержание

  1. VBA – Turn off Screen Updating
  2. Disable ScreenUpdating
  3. Enable ScreenUpdating
  4. VBA ScreenUpdating Example
  5. ScreenUpdating Refresh
  6. VBA Settings – Speed Up Code
  7. VBA Coding Made Easy
  8. VBA Coding Made Easy
  9. VBA Code Examples Add-in
  10. Заставить обновление экрана в Excel VBA
  11. ОТВЕТЫ
  12. Ответ 1
  13. Ответ 2
  14. Ответ 3
  15. Ответ 4
  16. Ответ 5
  17. Ответ 6
  18. VBA Screen Updating Property
  19. Excel VBA Screen Updating
  20. When to use Screen Updating Feature?
  21. How to use the Screen Updating Feature in VBA Code?
  22. Example #1 – Turn Off Screen Updating
  23. Example #2 –
  24. Force a screen update in Excel VBA
  25. 12 Answers 12

VBA – Turn off Screen Updating

In this Article

As cool as it looks watching your VBA macro manipulate the screen, you can help your Macro run faster if you turn off (disable) ScreenUpdating.

Disable ScreenUpdating

1. To disable ScreenUpdating, At the beginning of your code put this line:

Enable ScreenUpdating

2. To re-enable ScreenUpdating, At the end of your code put this line:

VBA ScreenUpdating Example

Your procedure will then look like this:

ScreenUpdating Refresh

Disabling ScreenUpdating will make your VBA code run MUCH faster, but it will also make your work appear more professional. End-users typically don’t want to see the behind the scenes actions of your procedures (especially when the procedure runs slow). Also, you may not want end-users to see the behind the scenes functionality (ex. Hidden Worksheets). I recommend disabling (and re-enabling) ScreenUpdating in virtually all of your procedures.

However, there are some times when you want the screen to refresh. To refresh the screen, you will need to temporarily turn back on ScreenUpdating (there is no screen “refresh” command):

VBA Settings – Speed Up Code

There are several other settings to play with to improve your code speed.

Disabling Automatic Calculations can make a HUGE difference in speed:

Disabling the Status Bar will also make a small difference:

If your workbook contains events you should usually disable events at the beginning of your procedure:

Last, your VBA code can be slowed down when Excel tries to re-calculate page breaks (Note: not all procedures will be impacted). To disable displaying page breaks use this line of code:

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro – A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!

VBA Coding Made Easy

Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!

VBA Code Examples Add-in

Easily access all of the code examples found on our site.

Simply navigate to the menu, click, and the code will be inserted directly into your module. .xlam add-in.

Источник

Заставить обновление экрана в Excel VBA

Мой инструмент Excel выполняет длинную задачу, и я стараюсь быть добрым к пользователю, предоставляя отчет о ходе выполнения в строке состояния или в некоторой ячейке на листе, как показано ниже. Но экран не обновляется или не останавливается в какой-либо точке (например, на 33%). Задача в конечном итоге завершается, но индикатор выполнения бесполезен.

Что я могу сделать, чтобы принудительно обновить экран?

Я использую Excel 2003.

ОТВЕТЫ

Ответ 1

Добавьте функцию DoEvents внутри цикла, см. ниже.

Вы также можете убедиться, что строка состояния отображается пользователю и reset, когда ваш код завершен.

Ответ 2

Текстовые поля в листах иногда не обновляются когда их текст или форматирование изменены, и даже команда DoEvent не помогает.

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

Следующие команды, похоже, делают трюк:

Ответ 3

Поместите вызов DoEvents в цикл.

Это повлияет на производительность, поэтому вы можете просто вызвать ее только на каждой, скажем, на 10-й итерации.
Однако, если у вас всего 30, это вряд ли проблема.

Ответ 4

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

и положим это как конец

Я обнаружил, что это часто ускоряет работу любого кода, с которым я работаю, так что необходимость предупредить пользователя о прогрессе не требуется. Это просто идея для вас попробовать, и ее эффективность в значительной степени зависит от вашего листа и расчетов.

Ответ 5

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

UserForm не будет обновляться в некоторых случаях, потому что DoEvents будет запускать события; однако Repaint обновит UserForm, и пользователь увидит изменения на экране, даже если другое событие сразу же следует за предыдущим событием.

В коде UserForm это просто:

Ответ 6

Напишите DoEvents непосредственно перед строкой, в которой вы обновляете пользовательский интерфейс, она должна работать.

Источник

VBA Screen Updating Property

Excel VBA Screen Updating

VBA Screen Updating is a property used to avoid or prevent distraction flashes while running the code and make it fast by turning off screen updating. We can turn off the screen updating by setting this property as “False.”

We often feel the Excel screen going crazy while the Macro is running. We almost get frustrated by that. But, how do we deal with these situations and make the code run faster than the usual slow thing?

Screen Updating is something we can notice while the excel macro Excel Macro A macro in excel is a series of instructions in the form of code that helps automate manual tasks, thereby saving time. Excel executes those instructions in a step-by-step manner on the given data. For example, it can be used to automate repetitive tasks such as summation, cell formatting, information copying, etc. thereby rapidly replacing repetitious operations with a few clicks. read more is running. When the task is executing, we notice our screen updating the values until the Macro finishes its assigned task. As our screen flickers or refreshes, it leads to the slowdown of the Excel program and takes a longer time than usual to complete the task.

In VBA, we have a property called “ScreenUpdating,” we set this property to FALSE to eliminate the screen updating process while the code runs.

This article will say goodbye to watching on-screen action drama while the code is running. Instead, today you will make your code run faster and quicker than your usual time.

Table of contents

You are free to use this image on your website, templates, etc., Please provide us with an attribution link How to Provide Attribution? Article Link to be Hyperlinked
For eg:
Source: VBA Screen Updating Property (wallstreetmojo.com)

When to use Screen Updating Feature?

Suppose you have any doubt about when to use this technique. Then, look into the below points.

How to use the Screen Updating Feature in VBA Code?

Example #1 – Turn Off Screen Updating

Look at the below code.

Code:

The above has a nested VBA loop VBA Loop A VBA loop in excel is an instruction to run a code or repeat an action multiple times. read more to insert serial numbers from the first column to the 50th column and again to insert serial numbers starting from 51 from the second row to the 50th column.

Like this, it will insert until it reaches the 50th row.

While this code is running, you can notice your screen flickering. You cannot do anything apart from watching this crazy moment.

To avoid all of these, we can add Screen Updating to FALSE.

To access the Screen Updating feature, first, we need to access the Application object.

As we can see with the Application object, we have many properties and methods. So, select “Screen Updating” from the IntelliSense list.

Note: You must apply the Screen Updating feature immediately after declaring the variables.

After selecting the Screen Updating property, put an equal sign (=).

As we can see, there are two Boolean values: FALSE and TRUE.

To stop screen updating, set the status to FALSE.

As the Macro starts running first, it will update the screen, updating the status to FALSE, and proceed to the next line.

Since Macro executed Screen Updating to FALSE, it will not allow the screen to update while the code is executing its task.

Example #2 –

Always Set Screen Updating to TRUE at the End

We have seen many people set the Screen Updating to FALSE but forgot to set it back to TRUE at the end of the Macro.

Always set the Screen Updating back to TRUE at the end of the Macro.

Источник

Force a screen update in Excel VBA

My Excel tool performs a long task, and I’m trying to be kind to the user by providing a progress report in the status bar, or in some cell in the sheet, as shown below. But the screen doesn’t refresh, or stops refreshing at some point (e.g. 33%). The task eventually completes but the progress bar is useless.

What can I do to force a screen update?

I’m using Excel 2003.

12 Answers 12

Add a DoEvents function inside the loop, see below.

You may also want to ensure that the Status bar is visible to the user and reset it when your code completes.

Text boxes in worksheets are sometimes not updated when their text or formatting is changed, and even the DoEvent command does not help.

As there is no command in Excel to refresh a worksheet in the way a user form can be refreshed, it is necessary to use a trick to force Excel to update the screen.

The following commands seem to do the trick:

Put a call to DoEvents in the loop.

This will affect performance, so you might want to only call it on each, say, 10th iteration.
However, if you only have 30, that’s hardly an issue.

@Hubisans comment worked best for me.

Specifically, if you are dealing with a UserForm, then you might try the Repaint method. You might encounter an issue with DoEvents if you are using event triggers in your form. For instance, any keys pressed while a function is running will be sent by DoEvents The keyboard input will be processed before the screen is updated, so if you are changing cells on a spreadsheet by holding down one of the arrow keys on the keyboard, then the cell change event will keep firing before the main function finishes.

A UserForm will not be refreshed in some cases, because DoEvents will fire the events; however, Repaint will update the UserForm and the user will see the changes on the screen even when another event immediately follows the previous event.

In the UserForm code it is as simple as:

This worked for me:

I couldn’t gain yet the survey of an inherited extensive code. And exact this problem bugged me for months. Many approches with DoEnvents were not helpful. Above answer helped. Placeing this Sub in meaningful positions in the code worked even in combination with progress bar

This is not directly answering your question at all, but simply providing an alternative. I’ve found in the many long Excel calculations most of the time waiting is having Excel update values on the screen. If this is the case, you could insert the following code at the front of your sub:

and put this as the end

I’ve found that this often speeds up whatever code I’m working with so much that having to alert the user to the progress is unnecessary. It’s just an idea for you to try, and its effectiveness is pretty dependent on your sheet and calculations.

On a UserForm two things worked for me:

  1. I wanted a scrollbar in my form on the left. To do that, I first had to add an Arabic language to «Change administrative language» in the Language settings of Windows 10 (Settings->Time & Language->Change Administrative Language). The setting is actually for «Change the language of Non-Unicode Programs,» which I changed to Arabic (Algerian). Then in the properties of the form I set the «Right to Left» property to True. From there the form still drew a partial ghost right scrollbar at first, so I also had to add an unusual timed message box:
  1. I tried everything to get the screen to redraw again to show the first text box in it’s proper alignment in the form, instead of partially underneath or at least immediately adjacent to the scrollbar instead of 4 pixels to the right where I wanted it. Finally I got this off another Stackoverflow post (which I now can’t find or I would credit it) that worked like a charm:

In my case the problem was in trying to make one shape visible and another one invisible on a worksheet.

This is my approach to «inactivating» a button [shape] once the user has clicked it. The two shapes are the same size and in the same place, but the «inactive» version has dimmer colors, which was a good approach, but it didn’t work, because I could never get the screen to update after changing .visible = FALSE to = TRUE and vice versa.

None of the relevant tricks in this thread worked. But today I found a solution that worked for me, at this link on Reddit

Essentially you just call DoEvents twice in immediate succession after the code that makes the changes. Now why? I can’t say, but it did work.

Источник

Мой инструмент Excel выполняет длинную задачу, и я стараюсь быть добрым к пользователю, предоставляя отчет о ходе работы в строке состояния или в некоторой ячейке на листе, как показано ниже. Но экран не обновляется или перестает обновляться в какой-то момент (например, 33%). Задача в конечном итоге завершается, но индикатор выполнения бесполезен.

Что я могу сделать, чтобы вызвать обновление экрана?

For i=1 to imax ' imax is usually 30 or so
    fractionDone=cdbl(i)/cdbl(imax)
    Application.StatusBar = Format(fractionDone, "0%") & "done..."
    ' or, alternatively:
    ' statusRange.value = Format(fractionDone, "0%") & "done..."

    ' Some code.......

Next i

Я использую Excel 2003.

2010-09-17 12:42

13

ответов

Решение

Добавьте функцию DoEvents внутри цикла, см. Ниже.

Вы также можете убедиться, что строка состояния видна пользователю, и сбросить ее после завершения кода.

Sub ProgressMeter()

Dim booStatusBarState As Boolean
Dim iMax As Integer
Dim i As Integer

iMax = 10000

    Application.ScreenUpdating = False
''//Turn off screen updating

    booStatusBarState = Application.DisplayStatusBar
''//Get the statusbar display setting

    Application.DisplayStatusBar = True
''//Make sure that the statusbar is visible

    For i = 1 To iMax ''// imax is usually 30 or so
        fractionDone = CDbl(i) / CDbl(iMax)
        Application.StatusBar = Format(fractionDone, "0%") & " done..."
        ''// or, alternatively:
        ''// statusRange.value = Format(fractionDone, "0%") & " done..."
        ''// Some code.......

        DoEvents
        ''//Yield Control

    Next i

    Application.DisplayStatusBar = booStatusBarState
''//Reset Status bar display setting

    Application.StatusBar = False
''//Return control of the Status bar to Excel

    Application.ScreenUpdating = True
''//Turn on screen updating

End Sub

user5050


17 сен ’10 в 16:04
2010-09-17 16:04

2010-09-17 16:04

Текстовые поля на листах иногда не обновляются при изменении их текста или форматирования, и даже команда DoEvent не помогает.

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

Следующие команды, кажется, делают трюк:

- ActiveSheet.Calculate    
- ActiveWindow.SmallScroll    
- Application.WindowState = Application.WindowState

2011-12-19 12:37

Позвоните DoEvents в петле.

Это повлияет на производительность, поэтому вы можете вызывать его только на каждой, скажем, 10-й итерации.
Однако, если у вас есть только 30, это вряд ли проблема.

user11683


17 сен ’10 в 13:05
2010-09-17 13:05

2010-09-17 13:05

Комментарий @Hubisans работал лучше всего для меня.

ActiveWindow.SmallScroll down:=1
ActiveWindow.SmallScroll up:=1

2019-11-27 20:57

Я пока не могу ознакомиться с унаследованным обширным кодом. И эта проблема мучила меня месяцами. Многие попытки использовать DoEnvents не помогли. Выше ответ помог. Размещение этой подпрограммы на значимых позициях в коде работало даже в сочетании с индикатором выполнения.

Sub ForceScreenUpdate()
    Application.ScreenUpdating = True
    Application.EnableEvents = True
    Application.Wait Now + #12:00:01 AM#
    Application.ScreenUpdating = False
    Application.EnableEvents = False
End Sub

2020-05-04 23:36

Это сработало для меня:

ActiveWindow.SmallScroll down:=0

или проще:

ActiveWindow.SmallScroll 0

2020-03-23 20:50

В частности, если вы имеете дело с UserForm, то вы можете попробовать метод Repaint. Вы можете столкнуться с проблемой DoEvents, если вы используете в своей форме триггеры событий. Например, любые нажатия клавиш во время работы функции будут отправлены DoEvents. Ввод с клавиатуры будет обработан до обновления экрана, поэтому, если вы изменяете ячейки в электронной таблице, удерживая одну из клавиш со стрелками на клавиатуре, затем событие смены ячейки будет продолжать срабатывать до завершения основной функции.

UserForm не будет обновляться в некоторых случаях, потому что DoEvents будет запускать события; однако Repaint обновит пользовательскую форму, и пользователь увидит изменения на экране, даже если другое событие сразу же следует за предыдущим.

В коде UserForm это так просто, как:

Me.Repaint

2013-03-18 00:29

Я пытался решить это
Force a screen update on a Worksheet (не пользовательская форма) в течение многих лет с ограниченным успехом с
doevents и прокрутка и т. д. Это решение CH Oldie лучше всего работает с небольшим модом.

Я достал
Wait и сбросить
ScreenUpdating а также
EnableEvents назад к истине.

Это работает с Office Excel 2002 до Office 365.

      Sub Sheet1Mess(Mess1 As String)
    Sheet1.Range("A6").Value = Mess1
    ForceScreenUpdate
End Sub
Sub ForceScreenUpdate()
    Application.ScreenUpdating = True
    Application.EnableEvents = True
   ' Application.Wait Now + #12:00:01 AM#
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.ScreenUpdating = True
    Application.EnableEvents = True
End Sub

2021-08-26 06:23

В моем случае: сложный Excel с графическим моделированием с использованием движущихся фигур. Для ускорения я хотел обновлять отображение только каждый 10-й шаг оптимизации. Поэтому на каждом 10-м шаге мне приходилось включать его снова, а затем делать события — но я столкнулся с проблемами, описанными выше. — Теперь, что странно: просто заявить screenupdating=True ДВАЖДЫ, это работает. ??!! Это безумие.

              If counteR Mod 10 = 0 Then
            'must state this twice. WHY ??
            Application.ScreenUpdating = True
            Application.ScreenUpdating = True
            DoEvents
            Application.ScreenUpdating = False
        End If

Pelton


04 мар ’23 в 16:46
2023-03-04 16:46

2023-03-04 16:46

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

Application.ScreenUpdating = False
Application.EnableEvents = False

и положить это как конец

Application.ScreenUpdating = True
Application.EnableEvents = True

Я обнаружил, что это часто ускоряет любой код, с которым я работаю, настолько, что нет необходимости предупреждать пользователя о прогрессе. Это просто идея для вас, и ее эффективность в значительной степени зависит от вашего листа и расчетов.

2010-09-17 16:05

В UserForm у меня сработали две вещи:

  1. Мне нужна полоса прокрутки в моей форме слева. Для этого мне сначала пришлось добавить арабский язык в «Изменить административный язык» в языковых настройках Windows 10 (Настройки-> Время и язык-> Изменить административный язык). На самом деле настройка предназначена для «Изменить язык программ, не поддерживающих Юникод», который я изменил на арабский (алжирский). Затем в свойствах формы устанавливаю для свойства «Справа налево» значение True. Оттуда форма сначала рисовала частичную призрачную правую полосу прокрутки, поэтому мне также пришлось добавить необычное временное окно сообщения:
          Dim AckTime As Integer, InfoBox As Object
    Set InfoBox = CreateObject("WScript.Shell")
    'Set the message box to close after 10 seconds
    AckTime = 1
    Select Case InfoBox.Popup("Please wait.", AckTime, "This is your Message Box", 0)
    Case 1, -1
    End Select
  1. Я попробовал все, чтобы экран снова перерисовался, чтобы отобразить первое текстовое поле с правильным выравниванием в форме, а не частично под или, по крайней мере, непосредственно рядом с полосой прокрутки, а не на 4 пикселя вправо, где я хотел. Наконец, я получил это из другого поста Stackoverflow (который я сейчас не могу найти, или я бы поверил в это), который работал как шарм:
      Me.Frame1.Visible = False
Me.Frame1.Visible = True

2021-04-07 14:09

В моем случае проблема заключалась в попытке сделать одну фигуру видимой, а другую — невидимой на листе. Это мой подход к «деактивации» кнопки [формы] после того, как пользователь нажал на нее. Две формы имеют одинаковый размер и находятся в одном месте, но «неактивная» версия имеет более тусклые цвета. Хороший подход, но он не сработал, потому что я никогда не мог обновить экран после изменения .visible = FALSE на = TRUE и наоборот. Ни один из подходящих трюков в этой ветке не сработал. Но сегодня я нашел решение, которое сработало для меня, по этой ссылке на Reddit: https://www.reddit.com/r/vba/comments/fjsrd7/force_screen_refresh/ . По сути, вы просто дважды вызываете DoEvents сразу после кода, который вносит изменения. А почему? Не могу сказать, но это сработало.

2021-08-04 15:51

Написать DoEvents как раз перед строкой, где вы обновляете пользовательский интерфейс, он должен работать.

2015-12-20 13:00

Хитрости »

20 Январь 2016              61482 просмотров


Рано или поздно у пишущих на Visual Basic for Applications возникает проблема — код хоть и облегчает жизнь и делает все автоматически, но очень долго. В этой статье я решил собрать несколько простых рекомендаций, которые помогут ускорить работу кода VBA, при этом в некоторых случаях весьма внушительно — в десятки, а то и больше, раз. Основной упор в статье сделан на начинающих, поэтому в начале статьи приводятся самые простые методы оптимизации. Более «глубокие» решения по оптимизации кода приведены в конце статьи, т.к. для применения данных решений необходим достаточный опыт работы в VB и сходу такие методы оптимизации кому-то могут быть непонятны.

  1. Если в коде есть много всяких Activate и Select, тем более в циклах — следует немедленно от них избавиться. Как это сделать я писал в статье: Select и Activate — зачем нужны и нужны ли?
  2. Обязательно на время выполнения кода отключить:
    • автоматический пересчет формул. Чтобы формулы не пересчитывались при каждой манипуляции на листе во время выполнения кода — это может дико тормозить код, если формул много:
      Application.Calculation = xlCalculationManual

      Если во время кода все же нужно пересчитывать какие-то диапазоны, то можно пересчитывать только их:

      Range("A1:C60").Calculate
    • обновление экрана, чтобы действия по изменению значений ячеек и пр. не мелькали. Зачем это надо? Т.к. все эти действия обращаются к графическому процессору и заставляют его трудиться для перерисовки экрана — это может значительно тормозить код:
      Application.ScreenUpdating = False
    • На всякий случай отключаем отслеживание событий. Нужно для того, чтобы Excel не выполнял никаких событийных процедур, которые могут быть в листе, в котором производятся изменения. Как правило это события изменения ячеек, активации листов и пр.:
      Application.EnableEvents = False
    • Если книга выводилась на печать или выводится на печать в процессе выполнения кода, то лучше убрать разбиение на печатные страницы.
      ActiveWorkbook.ActiveSheet.DisplayPageBreaks = False

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

    • На всякий случай можно отключить отображение информации в строке статуса Excel(в каких случаях там вообще отображается информация и зачем можно узнать в статье: Отобразить процесс выполнения). Хоть это и не сильно поедает ресурсы — иногда может все же ускорить работу кода:
      Application.StatusBar = False

    Главное, что следует помнить — все эти свойства необходимо включить обратно после работы кода. Иначе могут быть проблемы с работой внутри Excel. Например, если забыть включить автопересчет формул — большинство формул будут пересчитывать исключительно принудительным методом — после нажатия сочетания клавиш Shift+F9. А если забыть отключить обновление экрана — то есть шанс заблокировать себе возможность работы на листах и книгах. Хотя по умолчанию свойство ScreenUpdating и должно возвращаться в True, если было отключено внутри процедуры — лучше не надеяться на это и привыкать возвращать все свойства на свои места принудительно. По сути все это сведется к нескольким строкам:

    'Возвращаем обновление экрана
    Application.ScreenUpdating = True
    'Возвращаем автопересчет формул
    Application.Calculation = xlCalculationAutomatic
    'Включаем отслеживание событий
    Application.EnableEvents = True

    Как такой код выглядит на практике. Предположим, надо записать в цикле в 10 000 строк значения:

    Sub TestOptimize()
    'отключаем обновление экрана
    Application.ScreenUpdating = False
    'Отключаем автопересчет формул
    Application.Calculation = xlCalculationManual
    'Отключаем отслеживание событий
    Application.EnableEvents = False
    'Отключаем разбиение на печатные страницы
    ActiveWorkbook.ActiveSheet.DisplayPageBreaks = False
     
    'Непосредственно код заполнения ячеек
    Dim lr As Long
    For lr = 1 To 10000
        Cells(lr, 1).Value = lr 'для примера просто пронумеруем строки
    Next
     
    'Возвращаем обновление экрана
    Application.ScreenUpdating = True
    'Возвращаем автопересчет формул
    Application.Calculation = xlCalculationAutomatic
    'Включаем отслеживание событий
    Application.EnableEvents = True
    End Sub

    Разрывы печатных страниц можно не возвращать — они тормозят работу в любом случае.

  3. Следует избегать циклов, вроде Do While для поиска последней ячейки. Часто такую ошибку совершают начинающие. Куда эффективнее и быстрее вычислять последнюю ячейку на всем листе или в конкретном столбце без этого тормозного цикла Do While. Я обычно использую
    lLastRow = Cells(Rows.Count,1).End(xlUp).Row

    другие варианты определения последней ячейки я детально описывал в статье: Как определить последнюю ячейку на листе через VBA?

Для более опытных пользователей VBA я приведу несколько решений по оптимизации кодов в различных ситуациях:

  • Самая хорошая оптимизация кода, если приходится работать с ячейками листа напрямую, обрабатывать их и, возможно, изменять значения, то быстрее все обработки делать в массиве и разом выгружать на листе. Например, код выше по заполнению ячеек номерами будет в этом случае выглядеть так:
    Sub TestOptimize_Array()
    'Непосредственно код заполнения ячеек
    Dim arr, lr As Long
    'запоминаем в массив одним махом все значения 10000 строк первого столбца
    arr = Cells(1, 1).Resize(10000).Value
    'если нужно заполнение для двух и более столбцов
    'arr = Cells(1, 1).Resize(10000, 2).Value
    'или 
    'arr = Range(Cells(1, 1),Cells(10000, 2)).Value
    'или автоматически вычисляем последнюю ячейку и заносим в массив данные, начиная с ячейки А3
    'llastr = Cells(Rows.Count, 1).End(xlUp).Row 'последняя ячейка столбца А
    'arr = Range(Cells(3, 1),Cells(llastr, 2)).Value
    For lr = 1 To 10000
        arr(lr,1) = lr 'заполняем массив порядковыми номерами
    Next
    'Выгружаем обработанный массив обратно на лист в те же ячейки
    Cells(1, 1).Resize(10000).Value = arr
    End Sub

    Но здесь следует учитывать и тот момент, что большие массивы могут просто вызвать переполнение памяти. Наиболее актуально это для 32-битных систем, где на VBA и Excel выделяется памяти меньше, чем в 64-битных системах

  • Если используете быстрый ЕСЛИ — IIF, то замените его на IF … Then … Else
  • Так же лучше вместо Switch() и Choose() применить тот же IF … Then … Else
  • В большинстве случаев проверять строку на «не пусто» лучше через Len(), чем прямое сравнение с пустотой: Len(s)=0 вместо s = «». Связано с тем, что работа со строками значительно медленнее, чем с числовыми данными и Len по сути не подсчитывает длину переменной, а берет это число непосредственно уже готовое из памяти. При сравнении же текста с пустой строкой(«»), VBA сначала создает в памяти переменную нулевой длинны, а уже потом сравнивает с ней наш текст. Поэтому в некоторых случаях так же ускоряет сравнение и в таком виде: s = vbNullString
  • Не применять объединение строк без необходимости. Например, s = «АВ», будет быстрее, чем: s =»А» & «В»
  • Не применять сравнение текстовых величин напрямую. Лучше применить встроенную функцию StrComp:
    If s <> s1 Then будет медленнее, чем
    If StrComp(s, s1, vbBinaryCompare) <> 0
    и тем более, если при сравнении необходимо не учитывать регистр:
    If LCase(s) <> LCase(s1) Then будет медленнее, чем
    If StrComp(s, s1, vbTextCompare) <> 0
  • Циклы For … Next в большинстве случаев работает быстрее, чем цикл Do … Lоор
  • Избегать присвоения переменным типа Variant. Хоть соблазн и велик — этот тип забирает много памяти и в дальнейшем замедляет работу кода. Так же для объектных переменных следует избегать по возможности безликого глобального типа Object и применять конкретный тип:
    Dim rRange as Object, wsSh as Object

    будет медленнее работать, чем:

    Dim rRange as Range, wsSh as Worksheet

    Причина в том, что при объявлении As Object мы не даем VBA практически никакой информации о типе данных, кроме того, что это какой-то объект. И VBA приходится «на лету» внутри кода при каждом обращении к такой переменной определять её конкретный тип(Range, Worksheet, Workbook, Chart и т.д.). Что опять же занимает время.

  • Если работаете с массивами, то можно при объявлении указать это явно:

    вместо

    Такая инициализация происходит быстрее.
    А еще лучше будет при этом еще и тип данных сразу присвоить:

    Dim arr() as string, arr2() as long

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

Конечно, это не все приемы и решения для оптимизации. Но на первых парах должно хватить. Плюс, всегда следует исходить из здравого смысла. Например, если код выполняется за 2 секунды, то вероятно нет смысла его дальше оптимизировать. Конечно, если этот код не из тех, которые просто изменяют значение одной-двух ячеек.


Статья помогла? Поделись ссылкой с друзьями!

  Плейлист   Видеоуроки


Поиск по меткам



Access
apple watch
Multex
Power Query и Power BI
VBA управление кодами
Бесплатные надстройки
Дата и время
Записки
ИП
Надстройки
Печать
Политика Конфиденциальности
Почта
Программы
Работа с приложениями
Разработка приложений
Росстат
Тренинги и вебинары
Финансовые
Форматирование
Функции Excel
акции MulTEx
ссылки
статистика

Понравилась статья? Поделить с друзьями:

А вот еще интересные статьи:

  • Как обобщить ячейки в excel
  • Как обновить шрифты в word
  • Как обновить документ microsoft word
  • Как обнулить формулы в excel
  • Как обновить шаблоны в excel

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии