Excel vba отображение прогресса
If you have a Microsoft Visual Basic for Applications macro that takes a long time to finish, you may want to give the user an indication that the macro is progressing correctly. This article describes how to create a progress bar with a user form in Microsoft Excel.
More Information
Microsoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure. However, they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.
Create the User Form
In the following example, a Visual Basic subroutine populates a large range of cells with a random number. The indicator shows you that the macro is running correctly.
Open a new workbook in Excel.
In Microsoft Office Excel 2003 and in earlier versions of Excel, click Tools, point to Macro, and then click Visual Basic Editor.
In Microsoft Office Excel 2007, click Visual Basic in the Code group on the Developer tab.
Note To display the Developer tab in the Ribbon, follow these steps:
- Start Excel 2007, click the Microsoft Office Button, and then click Excel Options.
- In the Excel Options dialog box, click Popular, and then click to select the Show Developer tab in the Ribbon check box.
On the Insert menu, click UserForm.
Draw a Label control on the user form.
Change the following properties of the Label control to the following values: |Property| Value| |---------------|-----------------------------| |Caption| Now updating. Please wait. | Note If the Properties window is not visible, click Properties Window on the View menu.
Draw a Frame control on the user form.
Change the following properties of the Frame control to the following values: |Property |Value| |---------|--------------------| |Name FrameProgress|
Draw a Label control on the Frame control.
Change the following properties of the Label control to the following values: |Property| Value| |----------|---------------------------| |Name |LabelProgress| |BackColor |&H000000FF&| |SpecialEffect |fmSpecialEffectRaised|
Type the Macro Code
Double-click the user form to open the Code window for the user form.
In the module, type the following code for the UserForm_Activate event:
On the Insert menu, click Module.
In the Code window for the module, type the following code:
Return to Excel.
In Excel 2003 and in earlier versions of Excel, point to Macro on the Tools menu, and then click Macros.
In Excel 2007, click Macros in the Code group on the Developer tab.
In the Macro dialog box, click to select ShowUserForm, and then click Run.
A dialog box that has a red progress bar appears. The progress bar increases as the Main subroutine populates the cells on the worksheet.
The ShowUserForm subroutine shows the user form. The procedure that is attached to the Activate event of the user form calls the Main subroutine. The Main subroutine populates cells with random numbers. Additionally, the subroutine calls the UpdateProgressBar subroutine that updates the Label control on the user form.
Note When you use this technique, your macro takes just a bit longer to finish its intended tasks.
Часто при создании кодов в VBA используется обращение к ячейкам, листам, книгам и т.д. и их обработка в циклах. Пара примеров подобных циклов:
Если операция в цикле выполняется за пару секунд - это вполне приемлемо и отражать графически подобные действия нет нужды. Но, если циклы "крутятся" по полчаса - вполне неплохо иметь возможность видеть на какой стадии цикл. Здесь есть один нюанс: циклы могут быть как с заранее известным кол-вом итераций, так и без этого понимания.
Цикл Do While из первого кода статьи Просмотреть все файлы в папке является циклом условия. Т.е. заранее неизвестно сколько файлов будет обработано и следовательно невозможно отразить прогресс выполнения задачи в процентах.
Циклы вроде For Each и For . Next как правило дают возможность определить общее кол-во элементов к обработке, т.к. применяются как правило к коллекциям и объектам, у которых есть свойство .Count. Углубляться в этой статье не стану - это лишь предисловие, чтобы было ясно, почему и зачем далее в статье продемонстрированы разные подходы отображения процесса выполнения.
Отобразить же процесс можно двумя способами:
Использование Application.StatusBar
Самый простой вариант отображения процесса выполнения кода. Он может быть без проблем использован на любом ПК.
Application.StatusBar - это специальный элемент интерфейса, расположенный в левой нижней части окна Excel и который может показывать дополнительную информацию в зависимости от действий пользователя. Все не раз видели его в работе. Например, после того как мы скопировали ячейки StatusBar покажет нам доп.информацию:
И из VBA есть доступ к этому элементу. Чтобы написать слово привет в StatusBar надо выполнить всего одну строку кода:
Чтобы сбросить значения StatusBar и передать управление им обратно самому Excel необходимо выполнить строку:
Sub Get_All_File_from_Folder() Dim sFolder As String, sFiles As String 'диалог запроса выбора папки с файлами With Application.FileDialog(msoFileDialogFolderPicker) If .Show = False Then Exit Sub sFolder = .SelectedItems(1) End With sFolder = sFolder & IIf(Right(sFolder, 1) = Application.PathSeparator, "", Application.PathSeparator) 'отключаем обновление экрана, чтобы наши действия не мелькали Application.ScreenUpdating = False sFiles = Dir(sFolder & "*.xls*") Do While sFiles <> "" 'показываем этап выполнения Application.StatusBar = "Обрабатывается файл '" & sFiles & "'" 'открываем книгу Workbooks.Open sFolder & sFiles 'действия с файлом 'Запишем на первый лист книги в ячейку А1 - www.excel-vba.ru ActiveWorkbook.Sheets(1).Range("A1").Value = "www.excel-vba.ru" 'Закрываем книгу с сохранением изменений ActiveWorkbook.Close True 'если поставить False - книга будет закрыта без сохранения sFiles = Dir Loop 'возвращаем ранее отключенное обновление экрана Application.ScreenUpdating = True 'сбрасываем значение статусной строки Application.StatusBar = False End Sub
Если запустить код, то перед открытием каждой книги в строке StatusBar будет показано какой именно файл отрывается и обрабатывается. И так с каждым файлом:
В случае же с циклами, количество итераций которых есть возможность определить, можно показывать этап выполнения в процентах. Например, цикл по всем выделенным ячейкам:
Sub ShowProgressBar() Dim lAllCnt As Long, lr as Long Dim rc As Range 'кол-во ячеек в выделенной области lAllCnt = Selection.Count 'цикл по всем ячейкам в выделенной области For Each rc In Selection 'прибавляем 1 при каждом шаге lr = lr + 1 Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%" DoEvents 'чтобы форма перерисовывалась Next 'сбрасываем значение статусной строки Application.StatusBar = False End Sub
В строке статуса это будет выглядеть так:
Но можно показывать информацию и в чуть более изощренных формах:
Вариант отображения % и блоками-цифрами от 1 до 10 (1 = 10% выполнения)
Sub StatusBar1() Dim lr As Long, lrr As Long, lp As Double Dim lAllCnt As Long 'кол-во итераций Dim s As String lAllCnt = 10000 'основной цикл For lr = 1 To lAllCnt lp = lr \ 100 'десятая часть всего массива s = "" 'формируем строку символов(от 1 до 10) For lrr = 10102 To 10102 + lp \ 10 s = s & ChrW(lrr) Next 'выводим текущее состояние выполнения Application.StatusBar = "Выполнено: " & lp & "% " & s: DoEvents DoEvents Next 'очищаем статус-бар от значений после выполнения Application.StatusBar = False End Sub
Вариант отображения % и стрелками -> (1 стрелка = 10% выполнения)
Sub StatusBar2() Dim lr As Long, lp As Double Dim lAllCnt As Long 'кол-во итераций Dim s As String lAllCnt = 10000 For lr = 1 To lAllCnt lp = lr \ 100 'десятая часть всего массива 'формируем строку символов(от 1 до 10) s = String(lp \ 10, ChrW(10152)) & String(11 - lp \ 10, ChrW(8700)) Application.StatusBar = "Выполнено: " & lp & "% " & s: DoEvents DoEvents Next 'очищаем статус-бар от значений после выполнения Application.StatusBar = False End Sub
Вариант отображения % и квадратами (кол-во квадратов можно изменять. Если lMaxQuad=20 - каждый квадрат одна 20-я часть всего массива)
Sub StatusBar3() Dim lr As Long Dim lAllCnt As Long 'кол-во итераций Const lMaxQuad As Long = 20 'сколько квадратов выводить lAllCnt = 10000 For lr = 1 To lAllCnt Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%" & String(CLng(lMaxQuad * lr / lAllCnt), ChrW(9632)) & String(lMaxQuad - CLng(lMaxQuad * lr / lAllCnt), ChrW(9633)) DoEvents Next 'очищаем статус-бар от значений после выполнения Application.StatusBar = False End Sub
Этот вариант мне нравится больше всего.
При желании можно сделать и иные варианты - главное найти символы, которые будут показываться и определить их числовой код.
Использование UserForm
Использование стандартного элемента ProgressBar
Для Userform можно использовать стандартный контрол ProgressBar, но я лично не люблю добавлять на формы элементы, которые надо подключать отдельно. Потому как впоследствии контрол может отказаться работать, т.к. нужной версии не окажется на конечном ПК пользователя. Например в моем офисе 2010 для 64-битных систем его нет.
Поэтому про него кратко и в файле примере его нет. Как его создать:
- создаем UserForm (в меню VBE -Insert -UserForm. Подробнее про вставку модулей и форм - Что такое модуль? Какие бывают модули?)
- отображаем окно конструктора(если не отображено): View -Toolbox
- далее в меню Tools -Additional Controls
- там ищем что-то имеющее в названии ProgressBar и отмечаем его. Жмем Ок.
Теперь в окне Toolbox появится элемент ProgressBar. Просто перетаскиваем его на форму. В свойствах можно задать цвет и стиль отображения полосы прогресса. Останется лишь при необходимости программно показывать форму и задавать для элемента ProgressBar значения минимума и максимума. Примерно это выглядеть будет так:
Практический код
Например, надо обработать все выделенные ячейки. Если форма называется UserForm1, а ProgressBar - ProgressBar1, то код будет примерно такой:
Sub ShowProgressBar() Dim lAllCnt As Long Dim rc As Range 'кол-во ячеек в выделенной области lAllCnt = Selection.Count 'показываем форму прогресс-бара UserForm1.Show UserForm1.ProgressBar1.Min = 1 UserForm1.ProgressBar1.Max = lAllCnt 'цикл по всем ячейкам в выделенной области For Each rc In Selection 'прибавляем 1 при каждом шаге UserForm1.ProgressBar1.Value = UserForm1.ProgressBar1.Value + 1 DoEvents 'чтобы форма перерисовывалась Next 'закрываем форму Unload UserForm1 End Sub
Использование своего собственного прогресс-бара
Я использую в своих приложениях свой прогресс-бар с процентами. Для этого я использую стандартную UserForm, на которой располагаю два элемента Caption. Первый отвечает за визуальную составляющую в виде синей полосы заполнения, а так же за отображение процентов белыми цифрами на синем фоне. Второй Caption прозрачный и на нем в том же месте, что и у первого, отображаются проценты цифрами, но уже черным шрифтом. В результате в работе это выглядит так:
Как использовать эту форму и коды
Первоначально надо скачать файл, приложенный к статье, и в свой проект перенести форму frmStatusBar и модуль mCustomProgressBarModule.
Далее просто внедряем нужные строки в свои коды с циклами:
- До начала цикла необходимо вызывать процедуру инициализации формы:
Call Show_PrBar_Or_No(lAllCnt, "Обрабатываю данные. ")
первым аргументом задается общее кол-во обрабатываемых элементов, а вторым заголовок формы. Если второй аргумент не указан, то по умолчанию будет показан заголовок "Выполнение. ". Так же внутри кодов есть кусок кода, отвечающий за минимальное кол-во элементов к обработке. По умолчанию задано 10. Это значит, что если обрабатывается менее 10 ячеек, то форма прогресс-бара показана не будет. Нужно для случаев, когда производятся разные действия над ячейками, но неизвестно сколько их будет. Но зато известно, что с ними будет делать код. Часто для кол-ва ячеек менее 100 нет смысла отображать прогресс выполнения, т.к. это и так секундное дело.
Чтобы изменить минимальное кол-во достаточно в строке bShowBar = (lCnt > 10) заменить 10 на нужное число. - Далее в каждом проходе цикла вызвать перерисовку формы под новое значение цикла:
If bShowBar Then Call MyProgresBar - и в конце не забыть закрыть форму, чтобы не висела:
If bShowBar Then Unload frmStatusBar
Пример применения формы:
Sub Test_ProgressForm() Dim lr As Long Dim lAllCnt As Long 'кол-во итераций lAllCnt = 10000 'инициализируем форму прогресс-бара Call Show_PrBar_Or_No(lAllCnt, "Обрабатываю данные. ") 'сам цикл For lr = 1 To lAllCnt If bShowBar Then Call MyProgresBar Next 'закрываем форму, если она была показана If bShowBar Then Unload frmStatusBar End Sub
Во время выполнения кода программ в Excel, в случае длительного исполнения какого-либо процесса, возникает необходимость сообщить пользователю, что приложение стабильно работает, а вовсе не зависло, как это может показаться на первый взгляд.
Во многих случаях, этого вполне достаточно, чтобы успокоить пользователей Ваших программ. Если Вы хотите сообщать больше информации, сообщить оставшееся время обработки, процент выполнения, позволить остановить процедуру, то одним статус баром не обойтись.
В данной статье описано, как создать окно загрузки (или по-другому прогресс бар) для Ваших процедур без загромождения их кодом.
Состав прогресс бара
Строится окно загрузки на основе простой пользовательской формы UserForm, которая содержит следующие элементы:
Если вывести все элементы на форму, то она будет иметь такой вид:
В случае ненадобности тех или иных элементов, их можно не выводить. Контроль за выводом элементов осуществляет класс «ProgressBar», экземпляр которого для начала необходимо создать (Set var = New ProgressBar). Затем, используя созданный класс, можно программным образом заполнить форму элементами и задавать им конкретные значения.
Описание класса и способов создания окна загрузки
Для начала рассмотрим доступные методы данного класса, не концентрируясь на коде, а только на его функциональности:
- Метод createLoadingBar – создает полосу загрузки на форме;
- createString – создает сроку «Обработано: … %»;
- createtimeDuration – создает сроку «Продолжительность обработки: …»;
- createtimeFinish – создает строку «Оставшееся время обработки: …»;
- createTextBox – создает элемент TextBox;
- setParameters – задает параметры окна загрузки для предстоящего процесса. Принимает 3 аргумента:
- expProcess_INT – обязательный аргумент. Принимает целое число, сообщающее, из какого количества этапов состоит последующий процесс;
- UpdateInterval_INT – необязательный аргумент. С его помощью можно задать интервал обновления формы, т.е. через какое количество этапов все элементы окна загрузки необходимо обновить;
- UpdTimeInterval_INT_SEC – необязательный аргумент. Задает интервал обновления формы в секундах. Аргумент имеет смысл только в том случае, если не задан аргумент UpdateInterval_INT.
- curProcess – целое число. Номер текущего этапа процесса;
- stringTextBox – строка для элемента TextBox.
Это сделано по двум причинам.
Первая причина. При выводе в форму оставшегося времени обработки, его расчет производится, исходя из среднего времени, затраченного на один этап процесса, а затем умноженного на число оставшихся процессов. Данный способ является достаточно простым и понятным, но так как этапы выполняются не всегда с одной и той же скоростью, то время постоянно перепрыгивает с одного показателя на другой, что не позволяет адекватно его оценивать. Особенно данный эффект заметен в начале, когда прошедших этапов для оценки не так много. Установив интервал, Вы можете смягчить данный эффект. Рекомендуемого интервала в данном случае нет, так как все зависит от конкретного процесса.
Второй причиной является производительность. Не смотря на то, что идея вывода информации по загрузке является вполне обоснованной, само ее использование сильно замедляет процесс. Например, с использованием ProgressBar время обработки нижеприведенного примера составляет 1 минута 17 секунд при установленном интервале обновления в секунду. При обновлении формы на каждом этапе, за 2 минуты обработалось чуть больше 2 сотых процента. Без использования на все ушло 8 секунд. Поэтому старайтесь использовать прогресс бар только в случаях, когда это действительно важно и применяйте к нему оптимальный интервал – секунды достаточно, свыше данного значения особых изменений в производительности не наблюдается.
Также предусмотрена возможность остановить выполнение всех процессов, закрыв окно загрузки. Предварительно пользователю будет выведено окно с подтверждением.
Пример подключения прогресс бара к макросу
Далее приводиться простой пример перебора символов строки. Процедура сама по себе смысла не имеет, но хорошо демонстрирует возможности окна загрузки.
Многоуровневая полоса загрузки
Применение описанного в статье класса позволяет создавать независимые друг от друга окна загрузки для многоуровневых процессов.
Никаких дополнительных действий не требуется, достаточно создать новый экземпляр класса (New ProgressBar) и работать с ним независимо от родительского процесса.
Рекомендация: Для дочерних процессов добавляйте к формам загрузок уникальные заголовки (ProgressBar.Start Заголовок). Это уведомит пользователя программы о том, что сейчас выполняется подпроцесс.
Специальный элемент Microsoft ProgressBar Control
Выше было сказано о том, что саму полосу загрузки можно заменить дополнительным элементом управления формы, который специально предназначен для этого и называется Microsoft ProgressBar Control, version 6.0. Чтобы применить его, достаточно нажать правой кнопкой мыши на панели Tollbox и выбрать пункт "Additional Control. ".
Для ее устранения сначала проверьте наличие на Вашем компьютере файла MSCOMTCL.ocx. Это библиотека содержащая общие элементы управления Windows 6.0. Он должен располагаться в папке \Windows\SysWOW64 для 64-разрядных ОС либо \Windows\Sistem32 для 32-разрядных. В случае необходимости скачайте его и разместите в требуемую папку.
После того, как Вы убедились в наличии библиотеки, следует ее зарегистрировать. Запустите командную строку от имени администратора (Пуск -> Все программы -> Стандартные -> Командная строка) и выполните команду regsvr32 MSCOMTCL.ocx.
Комментарии
Подскажите, а зачем сделана проверка были ли созданы элементы формы? Это сильно тормозит процесс создания окна прогресс бара.
P.S. В любом случае, спасибо за готовое решение! )Насколько сильно тормозится процесс? На моей машине создание 2-х прогресс баров занимает доли секунды.
Если для Вашей задачи это критично, то лучше вообще отказаться от использования полосы загрузки.К тому же, проверка осуществляется единожды - при добавлении нового элемента на форму.
Мне понравилась Ваша идея. Внес изменения в код. Спасибо.
Еще было бы не плохо добавить двойной прогресс бар для многоуровневых процессов.
ну это так. Имхо.PS: просто мне очень понравился ваш прогресс бар) простой и лаконичный.
у меня процедура "поиск решения" выполняется через код VBA, вот там и не знаю к чему "прикрутить" barUpdate.
А как прикрутить ваш прогресс бар на выполнение "поиска решения"? Какой параметр прописывать в barUpdate?
Подключить прогресс бар можно только в коде процедуры VBA.
Каким образом Вы хотите совместить надстройку Excel со своей процедурой?Данный прогресс-бар позволяет отображать ход выполнения любого макроса.
Для использования этого индикатора перетащите из файла-примера в свой файл модуль класса ProgressIndicator и форму F_Progress
Использовать прогресс бар сравнительно просто - достаточно добавить в макрос несколько строк кода:
Давайте рассмотрим подробнее работу с индикатором.
Прогресс-бар выполнен в виде модуля класса, поэтому, для начала работы с ним,
надо прежде всего создать экземпляр этого класса:Итак, прогресс-бар создан, и теперь надо его отобразить.
Для этого мы используем метод Show объекта типа ProgressIndicator:
При использовании метода Show мы сразу задаём заголовок индикатора (можно здесь указать название вашего макроса)
Индикатор появился на экране - но полоса не отображается, ибо процент выполнения по-умолчанию равен нулю.
Для каждого действия мы будем задавать начальный и конечный процент выполнения задачи
К примеру, если первое действие вашего макроса занимает по времени примерно пятую часть от времени выполнения всего макроса,
то мы укажем интервал для индикатора от 0% до 20%:Как вы заметили, для запуска очередного действия используется метод StartNewAction объекта ProgressIndicator.
При вызове этого метода можно сразу задать текст для каждой из 3 текстовых строк индикатора:
Если действие состоит из нескольких отдельных "поддействий", то можно также сразу задать и количество этих "поддействий"
(например, основное действие - это форматирование ячеек (от 0% до 20% индикатора), а поддействия - это окраска отдельных ячеек (первая строка - от 0% до 1% индикатора, вторая строка - от 1% до 2%, и т.д.))
Чтобы нам не мучиться с расчётами этих процентов, мы просто задаём количество действий (например, количество форматируемых ячеек, равное 3000),
и индикатор сам разделит диапазон от 0% до 20% на 3000 равных частей, плавно увеличивая длину полосы индикатора по мере форматирования отдельных ячеек.Чтобы уведомить индикатор об очередном "поддействии" внутри цикла, мы используем метод SubAction объекта ProgressIndicator
Как вы могли заметить, мы задали только значение второй и третьей строки индикатора, не указав никакого текста для первой строки.
В этом случае (если значения некоторых из 3 строк индикатора не заданы), эти строки не изменяются
(в первой строке индикатора останется текст, заданный ранее при использовании метода StartNewAction)Кроме того, в тексте для строк индикатора можно использовать следующие ключевые слова:
- $index и $count - для вывода строк типа "Обрабатывается ячейка 515 из 3000",
- $time - для вывода ожидаемого времени до окончания макроса
(макрос анализирует текущий процент выполнения и затраченное время, и предсказывает, сколько времени осталось до окончания всех действий)
Если же необходимо просто увеличить длину полоски индикатора - можете использовать метод SubAction без параметров:
Вы можете выводить сколько угодно действий в индикаторе, причем совсем не обязательно, чтобы начальный процент очередного действия был равен конечному проценту предыдущего.
Вполне допустим следующий код:
По окончании макроса желательно закрыть прогресс бар:
У объекта ProgressIndicator имеется много различных свойств и методов.
Вкратце расскажу о некоторых свойствах:
- свойство Caption позволяет задать новый заголовок индикатора
- свойство FP позволяет получить доступ к отображаемой форме (и всем её элементам управления)
(например, код pi.FP.PrintForm выведет индикатор на печать) - свойства Line1, Line2 и Line3 позволяют в любом месте кода задать текст конкретной строки индикатора
- свойства ShowPercents и ShowTime включают или выключают отображение процента выполнения и времени в заголовке индикатора
(по умолчанию оба свойства имеют значение TRUE, т.е. в заголовке отображается и время, и процент выполнения макроса)
Из функций объекта мы рассмотрим только одну: AddChildIndicator
Эта функция создаёт дочерний прогресс бар, и отображает его выше или ниже родительского:
При изменении процента выполнения в дочернем индикаторе пропорционально меняется и процент выполнения главного (родительского) прогресс-бара.
В прикреплённом файле, помимо модуля класса и формы индикатора,
присутствует также стандартный модуль с несколькими примерами использования прогресс-бара.На индикаторе присутствует кнопка «Отмена» - её нажатие вызывает останов всех запущенных макросов
(выполняется команда End, останавливающая все макросы, и обнуляющая все переменные)Поскольку у этой кнопки свойство Cancel установлено в TRUE, нажатие на клавиатуре клавиши ESC равносильно нажатию кнопки «Отмена»
(при нажатии Esc макрос останавливается)Новая версия прогресс-бара - с поддержкой отображения лога на индикаторе, и возможностью отображения лога в виде текстового файла.
Высоту текстового поля с логом можно изменять:
Новая версия индикатора, и примеры его использования - во втором прикреплённом файле.
Комментарии
Огромное спасибо разработчику.
Несколько лет применял ваш ProgressIndicator (выдрал из какого-то примера), просто, эффектно. И вот наконец обнаружил автора.Большое спасибо Автору! Великолепный макрос! Думал что не нужный, пока не пришлось обрабатывать однотипные файлы тысячами! А так сразу понятно, на сколько можно идти пить чай!
Еще раз добрый день!
Заменил строку LogString = LogString & vbNewLine & currtime$ & txt на LogString = LogString & vbLf & currtime$ & txt в вашей процедуре Log, все стало нормально.
Спасибо
С уважением АлександрДоброго дня!
Попробовал Ваш код с поддержкой отображения лога на индикаторе
Очередная строка лога лепится к предыдущей, а не пишется на индикаторе с новой строки
Что посоветуете посмотреть?
Спасибо
С уважением АлександрНадо внутрь кода вычислений добавить строку DoEvents
чтобы комп не подвисал на выполнении вычислений.
Тогда прогрессбар будет отрисовываться постоянно, и ничего пропадать не будет
PS: все ваши 6 строк кода, к этой проблеме никакого отношения не имеют.Добрый день!
Использую прогресс бар для индикации во время объемных вычислений (парсинг большого объема JSON, общее время около 8 - 10 минут). Когда тестировал на меньших объемах (1-2 минуты) все работало отлично, но когда загрузил реальные данные, то прогресс бар стал периодически пропадать на несколько секунд, а потом снова появляться уже с обновленными данными. Причем количество таких появлений и пропаданий прогресс бара плавающее. Подскажите, может кто-то сталкивался с такой же проблемой?Все параметры обновления перед запуском сбрасываю:
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
Application.DisplayStatusBar = False
Application.DisplayAlerts = FalseПодскажите, если при использовании дочернего индикатора обращаться к нему напрямую (например, если брать Ваш пример, так: pi.AddChildIndicator("ИМЯ_ИНДИКАТОРА").SubAction "Действие $index из $count"), без конструкции With, то на стадии обновления дочернего индикатора (добавления действия) возникает ошибка деления на ноль: почему так происходит?
Константин, могу помочь, но только если платно (не готов бесплатно внедрять свои макросы в ваши файлы)
Инструкцию я написал, файл-пример приложил, - можете сами разобраться и сделать по аналогии, если хотите бесплатно.Добрый день,
я не понял как и где вставлять сам код между моим макросом. Форму и модуль я скопировал.
У меня следующий процесс.
1. Отключаю экранчик.
2. Открываю файл 1 и проверяю его на наличие в указанной папке.
3. Если файл1 есть то в самом файле я снимаю объединения ячеек.
4. Открываю файл2 повторяю пункт 2-3.
5. В файле1 делаю автофильтр и удаляю все не нужное и копирую данные в свой "материнский" файл через который запустил макрос. Закрываю файл 1 без сохранения(поскольку не знаю как макросом вернуть удаленное).
6. опять открываю файл1 п.2-3
7. Тяну ВПР с файла 2, фильтрую не нужные данные в файле1 и удаляю их, копирую в другую таблицу "материнского" файла.
8. закрываю файл 1,2 не сохраняя, и включаю экран.Прогрес бар тут нужен, поскольку долго обрабатывается, и файлы большие, но это намного быстрей чем все делать ручками. Хотелось бы увидеть общий прогресс бар просто с полосой и время.
Игорь, в настройках парсера: дополнительно-разное, есть галочка "отображать второй прогресс-бар" уже не актуальна) , т.к. первый после апа проги вмещает 6 строк. Было бы очень здорово если бы на следующий ап галочку изменили на "отображать прогресс-бар"))) Спасибо!
Здравствуйте, Юрий
В парсере отключение прогресс-бара не предусмотрено
От версии Excel зависит (у меня в Excel 2010 прогресс-бар отображается только в Excel, если в этот момент работать в других программах, то прогресс-бар не мешает. Но на некоторых компах проблема проявляется, и индикатор отображается поверх всех приложений)Здравствуйте, вопрос в следующем. Как отключить прогресс-бар в парсере? Очень не удобно когда парсер запускается каждую минуту и всплывает поверх окон. Спасибо!
Александр, надо задать количество действий - selection.cells.count
и при обработке каждой ячейки вызывать медом .SubAction прогрессбара
Тогда время и проценты будут считатьсяPS: а можно просто макрос немного переписать, чтобы вся обработка выполнялась за десятую долю секунду. - тогда и прогрессбар не понадобится
Поищите в инете советы, как в макросе уйти от использования Selection, обрабатывая массив ячеек целикомПодскажите пожалуйста. я обрабатываю ячейки по selection, как мне создать такой прогрессбар которые будет высчитывать проценты и время
Нажатие на красный крестик не останавливает макрос, а просто скрывает форму прогресс-бара.
Чтобы крестиком форма не закрывалась, добавьте код в ФОРМУ F_Progress
Подскажите пожалуйста! Как исключить возможность закрытия прогресс бара, до полного завершения процесса формирования документов? т.е. исключить принудительную остановку процесса формирования документов, путем нажатия на красный крестик.
Вышел из положения так. Сначала запускается маленький легкий макрос, он показывает юзеру чистый лист с предупреждающей надписью и стоящим на 20% прогресс-баром, пока что фальшивым, статичным.
Ведь главное, чтобы юзер спокойно ждал и не дергался!
Далее из этого макроса запускается основной большой макрос и прогресс-бар начинает ехать обычным порядком.
Прогресс-бар использовал свой, простейший, см. ранее, повтором буквы g шрифта Webdings.У меня сложный макрос долго работал.
Но пока налаживал этот прогресс-бар, выяснилась интересная штука.
Собственно, и необходимость в нем отпала.
Выяснилось, что основное замедление (до 15-20 секунд) происходит еще ДО НАЧАЛА выполнения операций!
Получается, что на этапе выделения памяти под переменные! Больше быть нечему.
У меня там реально много: по 20 переменных типа Long и Single, 8 String, 4 динамических массива Range, 8 массивов String тоже динамических и т.д. Сократить бы можно, но - за счет понятности кода.
За эту гипотезу говорит то, что замедление на компе с 8G памяти практически не чувствуется, а с 2G достигает 15 сек. Та же Win-7 и тот же Office-2010.Это правда может такое быть?
Я пытался запускать прогресс-бар еще до определения переменных. Однако ничего не меняется.
Да и кстати - по ходу придумал наипростейший прогресс-бар, он работает всегда!
На любой винде есть шрифт Webdings, в нем буква "g" с номером 103 - это просто закрашенный квадратик. Создаем прогресс-бар повтором этих квадратиков функцией String(), на отдельном листе с заранее отформатированной ячейкой. Размер, цвет надо будет подобрать.
Допустим, в ячейку помещается 23 квадратика.
Прогресс-бар в одну строчку:Sheets("ProgressBar").Range("D7").Value = String(Round(23 * i / n), 103)
где i и n - ваши параметры. Например, выполнено i действий из n.
Алексей, форма должна быть немодальной, чтобы прогресс-бар отображался сверху
В свойствах формы поставьте ShowModal = FALSEПрогресс-бар работает быстро, - за секунду может сменить десятки состояний.
Если у вас что-то медленно работает, - проблема в вашем коде (или неправильном использовании прогресс-бара)
Смотрите пример файл из статьи, - там всё быстро работает.Добрый день
Почему-то тогда я пытаюсь показать прогресс-бар перед своей формой(окно) она отображается за ней, и я прогресс-бар не вижу, а вижу только свою форму. Также остается проблема, когда я свою форму скрываю на время. При этом чтобы прогресс-бар работал быстрее надо мышкой на него левой кнопкой нажать (а так ждать около 1 мин против 5 сек).Чтобы все работало - надо скопировать в ваш файл модуль класса и форму из прикреплённого файла
Здравствуйте выдает ошибку pi As New ProgressIndicator
У меня такое же было из-за того, что я скопировал в свой проект классмодуль ProgressIndicator, но забыл скопировать форму F_Progress - нужно копировать и то и другое, как скопировал ошибку перестало вываливать.
П.С. Автору индекатора/сайта уклон до земли, респект, уважуха .Игорь, добрый день.
Будет ли компонент работать в MS Access 2007 и выше?Все получилось!
Огромное спасибо за помощь!Вставьте этот код в новый модуль, проверьте, - все должно заработать.
Здравствуйте!
Добавил на прогресс-бар кнопку "Лог", которая появляется в конце работы.
Подскажите, пожалуйста, как привязать к ее нажатию запуск метода класса ShowLog? Т.е. я хочу чтобы при нажатии этой кнопки лог "открывался" в блокноте.
Заранее спасибо!Прогрессбар создает копию формы,
потому обращайтесь в коде в Label так:
pi.FP.Label3.Visible = TrueЗдравствуйте! Спасибо Вам за макрос.
Возник один вопрос:
Я добавил на форму свой элемент (Label), который в зависимости от условий должен быть либо виден, либо нет.
Изменение свойств посредством F_Progress.Label3.Visible = True либо F_Progress.Label3.Caption = FileName полностью игнорируется (ничего не происходит)
Подскажите - куда копать? у самого уже фантазия иссякла.
Что мешает изменению свойств объектов?I'm trying to learn how to use a progress bar with a userform.
The problem I have, with my code, is that it displays the progress bar after running the loop; it should be running the loop while showing the progress bar instead like 10%. 20%. 30%. 40%. 100%.
Can anyone help me fix my code to achieve this?
3 Answers 3
I believe a true status bar is not included in standard VBA (without references), however you can abuse a label control. Be aware that this method trades performance for user clarity (the user can see that the application is working, but it is slower than the same application without the status bar)
Simply add three labels, one for status text, one for the actual moving bar and one for full bar border. And format them to fit your application (see image below):
There are a few issues with your code, but to focus on the Progress Bar part, I'll share an example of one way to handle a progress bar in Excel (using the built-in status bar).
Instead of actually doing anything useful, this example is pausing for a split second between loops, but reports the status on the status bar.) Hopefully it will give you some ideas.
VBA has a progress bar control that can be added to forms. While you are learning, you can simply add this control to the form and then update that control during the loop where you are doing the useful form functions. The progress bar controls includes useful properties such as min and max.
If you are doing multiple things in your form, you can update a label to tell the user what is progressing as well as the amount of progress.
[More advanced] In some of my previous work, I have set up VBA routines to run in the background and created a progress bar form using events. This allows for a more sophisticated view with progress statements as well as a percentage run. But the basis of this form is still the progress bar control. While using events is more complicated it allowed me to make a more general progress bar form that can be used by any of my vba functions and these functions are then unaffected by any changes I make to the form because the events act as a kind of standard interface.
Update from a comment by @MathieuGuindon: "The control is actually a VB6 control and will only work in a 32-bit VBA host with the .OCX properly registered, which is getting more and more challenging to do with the more recent Windows versions; referencing and using these controls in VBA7 is heavily discouraged."
Читайте также: