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, попробуйте сделать так:
0 |
bedvit 1024 / 227 / 21 Регистрация: 20.05.2016 Сообщений: 971 Записей в блоге: 19 |
||||
06.02.2017, 12:53 |
3 |
|||
Имхо должно быть достаточно:
0 |
Prisioner 6 / 6 / 3 Регистрация: 27.01.2017 Сообщений: 21 |
||||
06.02.2017, 13:46 |
4 |
|||
мне нужно в определенный момент просто обновить экран, чтобы посмотреть, — чего там у меня натворилось. И ничего дальше не делать. Если нужно именно остановить выполнение кода и посмотреть что происходит, а потом решить — продолжать или нет, тогда вот такая конструкция:
При этом выскочит окошко такое же как при ошибке, но будет активны кнопки «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.
Ответ 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 |
Приветствую! |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
А всё потому, что строка Application.ScreenUpdating = False срабатывает до принудительного выхода из процедуры (Then Exit Sub). А где включение? |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
А что непонятного? Вы обновление отключаете, а обратно не включаете. Я не раз писал уже, что лучше возвращать занчения изменных параметров и свойств. Private Sub Worksheet_Change(ByVal Target As Range) Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
ran Пользователь Сообщений: 7091 |
А нигде! |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
А мне ещё вот это непонятно: |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=RAN}{date=03.12.2011 04:01}{thema=}{post}почему в одном случае продолжает работать, а во втором — нет!?{/post}{/quote}Смотрите: |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
{quote}{login=RAN}{date=03.12.2011 03:44}{thema=Обновление экрана}{post}а если скопировать и вставить 2 ячейки, то требуется принудительное включение обновления экрана.{/post}{/quote}Вопрос на засыпку: что делает эта строка? Для общего понимания: если Вы вышли из процедуры, завершая её логически, т.е. дойдя до End Sub, то VBA сам возвращает значение Application.ScreenUpdating в True. Если же Вы принудительно завершили процедуру — то…короче ничего никуда не возвращается. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
ran Пользователь Сообщений: 7091 |
Но ведь здесь в обоих случаях принудительное завершение процедуры! |
nerv Пользователь Сообщений: 3071 |
Всем добрый день) Sub io() |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
Запустил — и что? Переключается. |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=RAN}{date=03.12.2011 04:34}{thema=}{post} |
nerv Пользователь Сообщений: 3071 |
>Запустите два раза. Первый запуск (макроса): Второй |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=nerv}{date=03.12.2011 04:45}{thema=}{post}А ведь мы его отключали) |
ran Пользователь Сообщений: 7091 |
Да нет его! Может конечно это мой локальный глюк, но у меня после выхода по строке |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=RAN}{date=03.12.2011 04:51}{thema=}{post}возможность попасть на любой лист Excel появляется только после выполнения Application.ScreenUpdating = True{/post}{/quote}Покажите файл ТОЛЬКО с этим фрагментом. |
Пытливый Пользователь Сообщений: 4587 |
Ну так The_Prist так и написал: Кому решение нужно — тот пример и рисует. |
nerv Пользователь Сообщений: 3071 |
{quote}{login=Юрий М}{date=03.12.2011 04:50}{thema=Re: }{post}{quote}{login=nerv}{date=03.12.2011 04:45}{thema=}{post}А ведь мы его отключали) |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=Пытливый}{date=03.12.2011 04:54}{thema=}{post}Ну так The_Prist так и написал{/post}{/quote}Мало ли что написал, Главное — прочитать |
ran Пользователь Сообщений: 7091 |
|
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
Что нужно выполнить, чтобы «сломалось»? |
nerv Пользователь Сообщений: 3071 |
Пытливый, Юрий, а теперь скажите мне почему здесь результат тот же самый) Sub io() |
ran Пользователь Сообщений: 7091 |
Скопировать и вставить [b5:b6] |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=RAN}{date=03.12.2011 05:03}{thema=}{post}Скопировать и вставить [b5:b6]{/post}{/quote}Скопировал, вставил — что дальше? |
ran Пользователь Сообщений: 7091 |
Юрий М |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
{quote}{login=RAN}{date=03.12.2011 05:03}{thema=}{post}Скопировать и вставить [b5:b6]{/post}{/quote}Здесь ДВЕ ячейки. А у Вас принудительный выход, если изменение более одной ячейки. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
{quote}{login=RAN}{date=03.12.2011 05:10}{thema=Re: }{post} Есть возможность попасть на лист? У меня — нет.{/post}{/quote}Не очень понимаю вопрос — я ведь и так на листе это делаю. Куда ещё попасть? |
The_Prist Пользователь Сообщений: 14182 Профессиональная разработка приложений для MS Office |
{quote}{login=nerv}{date=03.12.2011 05:00}{thema=Re: }{post}Пытливый, Юрий, а теперь скажите мне почему здесь результат тот же самый){/post}{/quote} Выполняя напрямую из редактора VBA вы не отключаете обновление — иначе не смогли бы видеть ход выполнения. А вот с листа — да, отключается. Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы… |
ran Пользователь Сообщений: 7091 |
Давайте попробую еще раз объяснить. |
nerv Пользователь Сообщений: 3071 |
Дмитрий, спасибо за участие) Но если честно, то я не понял : ) Private Sub Worksheet_SelectionChange(ByVal Target As Range) |
Юрий М Модератор Сообщений: 60585 Контакты см. в профиле |
#30 03.12.2011 17:49:54 {quote}{login=RAN}{date=03.12.2011 05:25}{thema=}{post}стоит мне скопировать 2 ячейки — можно мышем по листу щелкать до посинения, ничего не происходит (в ячейку попасть не могу, курсор — стрелка) до того, как в 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?
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.
asked Sep 17, 2010 at 12:42
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
31.8k46 gold badges145 silver badges221 bronze badges
answered Sep 17, 2010 at 16:04
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
54.6k16 gold badges113 silver badges176 bronze badges
answered Dec 19, 2011 at 12:37
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
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
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
This worked for me:
ActiveWindow.SmallScroll down:=0
or more simply:
ActiveWindow.SmallScroll 0
answered Mar 23, 2020 at 17:50
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
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
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
MichaelMichael
1,6362 gold badges16 silver badges21 bronze badges
0
On a UserForm two things worked for me:
- 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
- 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
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
6,4822 gold badges33 silver badges37 bronze badges
answered Aug 4, 2021 at 12:51
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
6,4822 gold badges33 silver badges37 bronze badges
answered Aug 26, 2021 at 3:23
Содержание
- VBA – Turn off Screen Updating
- Disable ScreenUpdating
- Enable ScreenUpdating
- VBA ScreenUpdating Example
- ScreenUpdating Refresh
- VBA Settings – Speed Up Code
- VBA Coding Made Easy
- VBA Coding Made Easy
- VBA Code Examples Add-in
- Заставить обновление экрана в Excel VBA
- ОТВЕТЫ
- Ответ 1
- Ответ 2
- Ответ 3
- Ответ 4
- Ответ 5
- Ответ 6
- VBA Screen Updating Property
- Excel VBA Screen Updating
- When to use Screen Updating Feature?
- How to use the Screen Updating Feature in VBA Code?
- Example #1 – Turn Off Screen Updating
- Example #2 –
- Force a screen update in Excel VBA
- 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:
- 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:
- 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 у меня сработали две вещи:
- Мне нужна полоса прокрутки в моей форме слева. Для этого мне сначала пришлось добавить арабский язык в «Изменить административный язык» в языковых настройках 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
- Я попробовал все, чтобы экран снова перерисовался, чтобы отобразить первое текстовое поле с правильным выравниванием в форме, а не частично под или, по крайней мере, непосредственно рядом с полосой прокрутки, а не на 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 и сходу такие методы оптимизации кому-то могут быть непонятны.
- Если в коде есть много всяких Activate и Select, тем более в циклах — следует немедленно от них избавиться. Как это сделать я писал в статье: Select и Activate — зачем нужны и нужны ли?
- Обязательно на время выполнения кода отключить:
- автоматический пересчет формул. Чтобы формулы не пересчитывались при каждой манипуляции на листе во время выполнения кода — это может дико тормозить код, если формул много:
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
Разрывы печатных страниц можно не возвращать — они тормозят работу в любом случае.
- автоматический пересчет формул. Чтобы формулы не пересчитывались при каждой манипуляции на листе во время выполнения кода — это может дико тормозить код, если формул много:
- Следует избегать циклов, вроде 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
ссылки
статистика