Как сделать прогресс бар в excel?

Линейный индикатор выполнения (прогресс бар) в Excel

Разберёмся как создать и настроить линейный индикатор выполнения (прогресс-бар) в виде диаграммы в Excel.

Приветствую всех, уважаемые читатели блога TutorExcel.Ru!

В современную экономическую жизнь прочно вошли понятия КПЭ (ключевые показатели эффективности, или KPI) и дашборда, которые помогают нам увидеть насколько эффективно выполняются те или иные цели. Грамотная визуализация позволяет сделать это приятным и понятным глазу языком.

Мы уже разбирали с вами примеры пулевой диаграммы, диаграммы в виде спидометра, сейчас остановимся ещё на одном варианте визуализации — индикаторе выполнения (также встречаются названия индикатор процесса или прогресс-бар от английского progress bar).

Для начала давайте поймем, что же это именно такое?

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

Сегодня предлагаю подробно рассмотреть линейный вариант графика, который представляет собой простую горизонтальную или вертикальную полосу:

Также в целом можно выделить 2 способа построения графика:

  • Без делений на шкале; в этом случае полоска нарисована как единый объект.
  • С делениями. В этом случае дополнительно рисуется шкала, которая отображает уровни выполнения (к примеру от 0% до 40% — красная зона, от 40% до 70% — желтая зона и т.д.).

Построение линейного индикатора (прогресс бара)

Вариант 1. Прогресс бар без шкалы

Давайте приступим к построению и начнем с самого простого варианта.

Для начала создадим таблицу, состоящую всего из 2 рядов с данными, в первом будет исходный процент (к примеру 85%), а во втором оставшаяся недостающая часть до 100% (т.е. в данном случае 15% = 100% — 85%):

Выделяем диапазон с данными A1:B2 и строим гистограмму с накоплением (в панели вкладок выбираем Вставка -> Диаграммы -> Линейчатая гистограмма с накоплением):

Как видим Excel не совсем правильно интерпретировал данные и построил график с 2 рядами данных, поэтому для корректного отображения поменяем местами строки и столбцы (выделяем диаграмму и в панели вкладок Конструктор выбираем Строка/Столбец), этим мы добьемся отображения всех данных в одному ряду:

Отлично, диаграмма уже начинает приобретать узнаваемый вид.

Далее устанавливаем минимальную и максимальную границы для оси (щелкаем правой кнопкой мыши по горизонтальной оси и попадаем в настройки Формата оси), как 0 и 1 соответственно, чтобы наша полоска полностью помещалась и показывалась на графике:

В результате мы получаем следующий вид графика:

Уберем ненужные на текущий момент детали в виде названия, дополнительных осей и прочего, чтобы они не отвлекали от построения (их, безусловно, можно не удалять и компоновать на ваше усмотрение):

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

Поэтому, чтобы растянуть диаграмму на всю возможную ширину и убрать лишние полосы, установим боковой зазор для ряда равным нулю (выделяем любой ряд с данными, щелкаем правой кнопкой мыши и выбираем Формат ряда данных -> Параметры ряда):

В итоге получаем более компактный вид:

Остались небольшие детали, покрасим части полоски в подходящие цвета и добавим подпись данных на ряд:

Все готово, перейдем к следующему варианту.

Вариант 2. Прогресс бар со шкалой

Отличие этого варианта от предыдущего заключается лишь в дополнительной подложке под полоску, которая показывает уровни выполнения показателя, остальные части практически повторяют предыдущий вариант построения.

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

В данном случае я указал шаг шкалы равным 10%, но можно поставить абсолютно любой по вашему усмотрению, главное чтобы сумма всех таких шагов давала 100% (10 шагов по 10% как в примере, или 20 шагов по 5% и т.д.).

Выделяем диапазон с данными A1:B11 и, как и в предыдущем примере, строим линейчатую гистограмму с накоплением:

Повторяем алгоритм и меняем строки и столбцы местами, чтобы диаграмма приобрела необходимый нам вид:

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

Покрасим каждый шаг шкалы в подходящий цвет, для этого левой кнопкой мыши выделяем каждый ряд по отдельности и делаем заливку соответствующим цветом (к примеру, первые 4 шага красим красным, 3 средние — желтым и 3 последние — зеленым):

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

В результате настройки типов осей получаем:

Далее также для обеих осей указываем 0 и 1 как минимальную и максимальную границы, чтобы график был ровно от 0% до 100%:

Убираем название, оси данных и прочие ненужные в данный момент детали, настраиваем нулевой боковой зазор:

Так как шкала на полученной диаграмме не видна за основной полоской, то для основного ряда с данными установим прозрачность (щелкаем по ряду правой кнопкой мыши, в контекстном меню выбираем Формат ряда данных -> Заливка и границы -> Заливка):

Также добавим подпись данных и получаем:

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

Спасибо за внимание!
Если у вас есть вопросы по теме статьи — пишите в комментариях.

VBA Progress Bar

Excel VBA Progress Bar in Excel

Progress Bar is something which shows us how much of a process has been done or finished when we run large sets of codes which require larger time to execute we use progress bar in VBA to show the user about the status of the process, or if we have multiple processes running in a single code we use progress bar to show which process has progressed how much.

A progress bar shows the percentage of task completed when the actual task running behind the screen with a set of instructions given by the VBA code.

When the VBA code takes a considerable amount of time to execute, it is the user anxiety to know how soon it can finish. By default, we need to wait for the full time to complete the task but by inserting the progress bar we get to know the progress of the VBA code.

In almost all the computer software’s we see a progress bar chart which shows the progress of the task we are performing just like the below image.

In excel too we can create Progress Bar by using VBA coding. If you have ever wondered how we can create a progress bar then this is the article tailor-made for you.

Create Your Own Progress Bar

In order to create a progress bar, we need to follow several steps. Below are the steps to involve while creating the progress bar chart.

Step 1: Create or Insert new User form.

As soon as you click on the option above you will see a user form like the below.

Step 2: Press F4 key to see the VBA properties window.

In this properties tab, we need to change the properties of the VBA userform we have inserted.

Step 3: Change the name of the user form to UFProgressBar.

Now we can refer this user form with the name “UFProgressBar” while coding.

Step 4: Change the Show Model Property of the user form to FALSE.

Step 5: Now adjust the alignment of the user from to fit your needs. I have changed the Height of the user form to 120 and width to 300.

Step 6: Change the Caption of the user form to “Progress Status Bar”.

Step 7: Now from the toolbox of the user form insert LABEL to the user form at the top.

Читать еще:  Как сделать социометрию в excel?

With this label, we need to set the properties of the label. Delete the caption and make it blank and adjust the width of the label.

Step 8: Change the Name of the label to “ProgessLabel”.

Step 9: Now from the toolbox take the frame and draw just below the label we have inserted in the previous steps. Make sure the frame is at the center of the user form.

Step 10: Now we need to change some of the properties of the Frame to make it look exactly the same as the user form we have inserted.

Property 1: Change the Name of the frame to “ProgressFrame”.

Property 2: Delete the caption and make it blank.

Property 3: Change the Special Effect of the frame to 6 – fmSpecialEffectBump.

After all these changes our user form should look like this.

Step 11: Now insert one more label. This time insert the label just inside the frame we have inserted.

While inserting the label make sure the left side of the label exactly fits the frame we have inserted as shown in the above image.

Step 12: After inserting the label change the properties of the label as follows.

Property 1: Change the name of the label to “MainProgressLabel”.

Property 2: Delete the caption.

Property 3: Change the background colour as per your wish.

Ok, now we are done with the process of setting up the VBA progress bars in excel and at this point in time, it looks like this.

Now we need to enter codes to make this work perfectly.

Step 13: To make the framework add the below macro in excel.

Code:

Now if you run this code manually or through F5 key, we should see the progress bar like this.

Step 14: Now we need to create a macro to perform our task. I am performing the task of inserting serial numbers from 1 to 5000. Along with this code, we need to configure the progress bar chart as well, below code is the tailor-made code for you.

Code:

Recommended Articles

This has been a guide to VBA Progress Bar. Here we learn how to create a progress bar chart using VBA code in excel along with practical examples and a downloadable template. Below you can find some useful excel VBA articles –

Excel vba прогресс бар

Создание прогресс-бара выполнения макроса (Макросы/Sub)

​Смотрите также​​ ‘показывать’ в Application.StatusBar​
​ прорисовывать элементы с​ в и Delphi,​Прогресс бар ?​
​ Dim pi As​
​Application.Calculation = xlCalculationManual​
​ инете представлено достаточно​
​Удалите одну -​
​:=False, Transpose:=False​
​ Excel.Workbook​Alex_ST, 23.12.2016 в​
​ ChrW(9633))​ в первом посте)?​
​ String(11 — p​Application.StatusBar = False​
​UserForm1.Show​
​Viper25​alex_gearbox​
​ использованием манифеста винды.​ это не проблема,​
​Может я чего-то​
​ New ProgressIndicator ‘​
​For i =​
​ много вариаций создания​ и все заработает​
​Workbooks(Month + «_TEMP.xlsx»).Close​
​Set Gorod =​
​ 14:08, в сообщении​
​DoEvents​
​Alex_ST​
​ 10, ChrW(8700))​
​End Sub​

​UserForm1.Label1.Width = 1​​: Здравствуйте.​: А я сделал​
​blanks​
​ тока как мне​
​ не понимаю.. Но​ создаём новый прогресс-бар​ 10 To 109​
​ Progressbar, но как​Viper25​
​Application.ScreenUpdating = True​
​ ThisWorkbook​
​ № 9 ()​Next​
​: Это точно. Я​Application.StatusBar = «Выполнено:​
​Sub test2()​For i =​
​Нужно создать прогресс-бар​
​ ProgressBar в StatusBar-е​
​: Как в ескселе​
​ это окно «вклеить»​

​ какой смысл в​​ pi.Show «Подождите, работает​​If Cells(i, 1).Value​​ его прописать? В​: Увы. Что я​Application.CutCopyMode = True​

​’Вставляем таблицу 1​​ 200?’200px’:»+(this.scrollHeight+5)+’px’);»>Спасибо, Слава.​’очищаем статус-бар от​ отходил от компа​ » & p​

​For i =​​ 1 To 100​ для наглядности работы​ Excel-я. На API-шных​
​ сделать пргресс бар​ в файл Экселевский,​ прогресс баре, если​ ​ макрос» ‘ отбражаем​
​ = «» Then​ идеале хотелось, чтобы​
​ не так сделал?​Application.DisplayAlerts = True​
​Dim filenameTEMP As​Udik​ значений после выполнения​ и не успел​ & «% «​ 1 To 10000​
​UserForm1.Label1.Width = Int(i​
​ макроса.​
​ вызовах. Могу прислать.​
​ по типу как​
​ если это возможно.​
​ отключено обновление экрана?​ индикатор ‘ код​
​ Rows(i).RowHeight = 0​ Progressbar выглядел аналогично​
​Спасибо.​End Sub​ String​: ага, увидел​Application.StatusBar = False​ сам ответить.​ & S: DoEvents​
​p = i​
​ * j)​
​Нашел такой пример.​
​Если кому интересно:​
​ копирование файла,​
​И можно ли​Лина​
​ макроса Application.ScreenUpdating =​’For Each cc​ с тем, который​Starbirst​Function GetFolderPath(Optional ByVal​filenameTEMP = myPath​Viper25​End Sub​
​Спасибо, Слава.​Next​ 100​For k =​
​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Sub Progress()​
​http://j-walk.com/ss/excel/tips/tip34.htm​
​т.е. движущиеся по​
​ остановить выполнение макроса.​
​: Вот файл​ False Range(«B22».Select Selection.AutoFill​
​ In [B10:B109].Columns​ появляется при нажатии​: Доброго времени суток!​ title As String​ + «» +​:​
​взял тут, там​Alex_ST​Application.StatusBar = False​Application.StatusBar = «Выполнено:​
​ 1 To 100000​
​’​
​-=Dj=-​
​ мере выполнения кода​
​Alex77755​Sanja​
​ Destination:=Range(«B2200», Type:=xlFillDefault Range(«B2200».Select​’cc.EntireColumn.Hidden = cc.Text​ на кнопку PDF.​ Ребята, окажите, пожалуйста,​ = «Выберите папку»,​ Month + «_TEMP.xlsx»​
​SLAVICK​ достаточно много вариантов​: Вызов своих процедур​End Sub​
​ » & p​
​Next k​
​’ Progress Bar​ ​: Здравствуйте! помогите с​

​ квадратики. ​​: Нет в стандартном​: А Вы все​

​ Range(«B201201».Select Selection.AutoFill Destination:=Range(«B201400»,​​ = «»​ Особо в макросах​ помощь! Во вложенном​ Optional ByVal initialPath​n = n​, спасибо.​ и с ЮзерФорм​ вставляйте между DoEvents​Sub test5()​

​ & «% «​​DoEvents​’​ прогресс баром (можно​vlth​

​ — кто мешает​​ по инструкции сделали?​ Type:=xlFillDefault Range(«B201400».Select Range(«E2».Select​’Next​ не волоку. Спасибо​
​ файле имеется кнопочка​

​ As String =​​ + 1 /​Viper25​ тоже​

​ и Next​​For i =​ & String(p ​Next​Dim intIndex As​

​ и статус бар).​​: Щёлкни правой клавишей​

​ нажать кнопочку?​​ Если прогрессбар именно​
​ ActiveCell.FormulaR1C1 = «1»​Next​ всем отозвавшимся!​
​ «С К Р​
​ «P:ФинДирОтделКонсолидацииБюджет») As String​ 2: p =​
​:​SLAVICK​
​Udik​ 1 To 10000​ 10 + 1,​
​End Sub​
​ Integer​У меня есть​
​ по панели ‘элементы​Для остановки процесса​ , то:​ Selection.AutoFill Destination:=Range(«E2:E400», Type:=xlFillDefault​Application.Calculation = xlCalculationAutomatic​Starbirst​ Ы Т Ь​Dim PS As​ 2 * n​SLAVICK​
​: для конкретного файла​
​: У меня лично​
​p = i​ ChrW(10000 + p​
​Viper25​
​Dim sngPercent As​
​ большой макрос, записанный​ управления’:​ в тело поставить​в Вашем файле​

​ Range(«E2:E400».Select Range(«C1».Select ‘Dim​​Application.ScreenUpdating = True​: Прилагаю отредактированный файл.​ П У С​
​ String: PS =​Application.StatusBar = «Выполнено:​, по Вашему примеру​ — нужно добавить​
​ не получается ничего​ 100: S​ 2))​:​ Single​

​ макрорекордером, выполняющий последовательные​​->Additional Controls. ->Microsoft ProgressBar​​ DoEvents и проверку​​ их нет​​ rng As Range​​End Sub​Формуляр​
​ Т Ы Е​ Application.PathSeparator​ » & n​
​ создал макрос, который​
​ 4е раза строки:​
​ показать в статусбаре​
​ = String(p ​DoEvents​
​Udik​
​Dim intMax As​
​ действия больше минуты.​
​ Control​​ глобальной переменной.​Лина​ With ThisWorkbook.Worksheets(«раскрой двп».Range(«C:C»​Формуляр​

​: Честно говоря, код​​ Я Ч Е​

​ и в ActiveX​​отвечать​ .FindNext() Loop While​Моих познаний Excel,​Application.Calculation = xlCalculationManual​
​ столбец B в​ .InitialFileName = initialPath​:=False, Transpose:=False​
​ еще один блок​
​ «% » &​
​ больше всего нравится​Next​

​ 100: S​​ процедуры.​DoEvents​
​ я находил не​

Progressbar к существующему макросу (Макросы/Sub)

​(‘фоновую’) сделать постоянной​​ есть ProgressBar 6.0(SP4)​?​ Not Rng Is​ не говоря уже​. ​ диапазоне , если​If .Show <>​Workbooks(Month + «_TEMP.xlsx»).Close​ «‘Вставляем таблицу 2″,​ String(p, ChrW(8700)): DoEvents​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Sub StatusBar3()​Application.StatusBar = False​ = «»: For​Alex_ST​’————————​ подходят)​ ширины, а шириной​ и ProgressBar 5.0(SP2)​Ama​ Nothing End If​ про макросы, недостаточно,​Application.ScreenUpdating = True​ в списке нет​ -1 Then Exit​’Вставляем таблицу 2​ макрос ругается.​SLAVICK​Dim lr As​End Sub​ j = 10102​: Вообще-то очень удобно​’ Your code​nilem​ другой​ какой выбрать. Просто​: Доброе время суток. ​ End With For​ потому понять, что​Application.Calculation = xlCalculationAutomatic​ данных (элемент управления​ Function​Dim filenameTEMP As​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Sub SBOR()​: так​ Long​Обсуждалось на Планете​ To 10102 +​ прогресс в статус-баре​

​необходимо управлять программно.​​ я ее буду​ Есть файл экселевский,​ Each cell In​
​ такое цикл, как​работать будет, наверняка,​ «список» для выбора​
​GetFolderPath = .SelectedItems(1)​
​ String​
​Application.ScreenUpdating = False​
​ScreenUpdating​
​Dim lAllCnt As​
​Udik​ p 10:​
​ показывать.​’————————​
​-=Dj=-​ Цвет фона надписей,​ тестить на работе​
​ с VBA. В​ Sheets(«раскрой двп».Range(«A2200» cell.Formula​ его задать, мне​ быстрее.​
​ формы в текущем​
​If Not Right(GetFolderPath,​
​filenameTEMP = myPath​Application.CutCopyMode = False​
​, и​
​ Long ‘кол-во итераций​
​: Так обычно обновления​
​ S = S​Вот у меня​
​Sleep 100​, привет​ само-собой, должен быть​
​ а там XP​ котором создаются листы​
​ = cell.Value Next​ достаточно сложно понять.​
​Может и прогрес-бар​
​ файле) . В​
​ 1) = PS​
​ + «» +​
​Application.DisplayAlerts = False​

Читать еще:  Как сделать из текста ссылку в excel?

​DisplayStatusBar​​Const lMaxQuad As​ экрана отрубают​ & ChrW(j): Next​
​ в заначке лежит​

​Next​​может лучше статус-бар?​ ​ разным.​ а у меня​ с данными с​ cell pi.Hide ‘​ Я брал разные​ не понадобится. ​ представленной таблице работа​ Then GetFolderPath =​ Month + «_TEMP.xlsx»​’задаем путь к​- это разные​ Long = 20​SLAVICK​Application.StatusBar = «Выполнено:​

VBA Прогресс бар

​ несколько примеров:​​End Sub​Просто вставьте в​Получаем ‘непрерывный’ (без​
​ Win7.​ помощью макроса. Хочу​ закрываем индикатор’ End​ макросы, пытался что-то​PS: Объявлять переменную​ макроса не занимает​ GetFolderPath & PS​n = n​ данным​ вещи.​ ‘сколько квадратов выводить​: Обновление экрана со​ » & p​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Sub test1()​Но не получается.​ нужных местах в​ квадратиков-сегментов) Progress Bar.​А DoEvents куда​ при выполнении вывести​ Sub​ изобрести — так​ в цикле тоже​ много времени, однако​End With​ + 1 /​Dim myPath As​Конечно если вы​lAllCnt = 10000​ статус баром не​ & «% «​For i =​Помогите, плиз.​ коде​Удачи!​ вставлять? В исполняемый​

​ окно с ProgressBar-ом​​The_Prist​ и получился макрос,​ как-то не принято.​ в настоящей таблице,​End Function​ 2: p =​ String​

​ его спрятали, то​​For lr =​ связано — действительно​
​ & S: DoEvents​
​ 1 To 10000​Спасибо.​Application.StatusBar = «Происходит этап​S_Isa​ макрос?​

​ чтобы показывало степень​​: Лина, читать код​

​ который я применял​​А внутренний цикл​ там, где помимо​SLAVICK​ 2 * n​
​myPath = GetFolderPath​ и не увидите.:​

​ 1 To lAllCnt​​ самый удобный способ​Next​

​p = i​​Udik​ №1″‘ следующий -​: А может вполне​​analyst​​ выполнения макроса, а​

ProgressBar в VBA

​ совершенно неудобно. Сами​​ по сей день.​ по одному столбц​ столбцов A, B,​: так Вы же​Application.StatusBar = «Выполнено:​’Задаем часть имени​Вот см так:​Application.StatusBar = «Выполнено:​ — статусбар. и​Application.StatusBar = False​ 100​: ну вот пример​ этап № 2.​ достаточно StatusBar?​: Можно здесь глянуть:​ так же хочу​ гляньте. Исправьте, пожалуйста,​
​ Спасибо большое!​ B никакого эффекта​ и С имеются​ смотрите на что​ » & n​ файла — номер​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Public Sub d()​
​ » & Int(100​ не нужно никаких​

​End Sub​​Application.StatusBar = «Выполнено:​ простенький​ 3 и т.д.​
​И ну его​Уведомление в процессе​ добавить кнопку остановки​ применив теги кода.​
​Лина​ не даёт.​

​ формулы в других​​ он ругается, и​ * 100 &​ месяца​Application.ScreenUpdating = 0​ * lr /​ юзерформ. Код работает​Sub test4()​ » & p​200?’200px’:»+(this.scrollHeight+5)+’px’);»>​а в конце​ к лешему лишние​ выполнения макроса​
​ выполнения. Трабл в​ Это кнопочка чуть​: Доброго времени суток.​

​И что остаётся?​​ столбцах, требует значительного​
​ что пишет.​ «% » &​

​Dim Month As​​Application.StatusBar = «111111:​ lAllCnt) & «%»​ сразу одинаково у​For i =​
​ & «% «​Public Sub test()​КодApplication.StatusBar = «»​

Создание графического прогрессбара в Excel

​ формы!​​Ama​ том что в​ выше поля, где​ Уважаемые знатоки нужна​
​Код200?’200px’:»+(this.scrollHeight+5)+’px’);»>Public Sub Скрыть()​ времени. Каким образом​У Вас дважды​

​ String(p, ChrW(8700)): DoEvents​​ String​ » ‘:DoEvents​ & String(CLng(lMaxQuad *​
​ всех.​ 1 To 10000​
​ & String(p ​Dim i As​-=Dj=-​А отражение ‘прогресса’​
​: С этим разобрался.​ стандартном наборе элементов​ набираете сообщение.​
​ ваша помощь.​Dim i As​ можно отобразить процесс​
​ в дном макросе​Workbooks.Open Filename:=filenameTEMP, UpdateLinks:=False​Month = Application.InputBox(«Введите​Application.ScreenUpdating = 1​
​ lr / lAllCnt),​Viper25​
​p = i​

​ 10 + 1,​​ Integer, j As​:​
​ вполне можно сформировать​ благодарю. В макросе​ в VBA ProgressBara​
​Alexander88​Не получается прилепить​ Integer​ работы макроса? Как​ повторяется строка:​Workbooks(Month + «_TEMP.xlsx»).Worksheets(«2»).Range(«A2:C10»).Copy​

​ номер месяца», Type:=2)​​Application.StatusBar = False​ ChrW(9632)) & String(lMaxQuad​: Подскажите, как прогресс-бар​ 100: S​

Прогресс бар выполнения макроса без цикла (Макросы/Sub)

​nilem​​ в текстовой переменной​ обрабатывал глобальную переменную​ нету.​
​: Приложите файл-пример, помогут​ к прогресс бару​Dim cc​ добавить к макросу​
​200?’200px’:»+(this.scrollHeight+5)+’px’);»>Dim filenameTEMP As String​Gorod.Worksheets(«ALL»).Range(«A12:C20»).PasteSpecial Paste:=xlPasteValues, Operation:=xlNone,​’Задаем имя отчета​
​End Sub​ — CLng(lMaxQuad *​ внедрить в мой​ = String(p ​DoEvents​j = UserForm1.Width​

​, такой вариант подойдет,​​ которую в нужные​​ .​​Можно окно создать​
​ быстрее​
​ макрос, выдает ошибку.​Application.ScreenUpdating = False​ простейший Progressbar? В​
​а это недопустимо.​ SkipBlanks _​Dim Gorod As​Цитата​
​ lr / lAllCnt),​
​ файл (в примере​

​ 10, ChrW(10152)) &​​Next​​ / 100​​ спасибо)​ моменты в алгоритме​

Прогресс бар в статус баре

1. Введение

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

В VB есть стандарный компонент ProgressBar. Применять его достаточно просто:

  • подключить к проекту компонент «Microsoft Windows Common Controls» (существует несколько версий);
  • дизайнером разместить прогресс-бар;
  • установить свойства «Min» и «Max»;
  • в коде приложениия (в нужном месте) устанавливать свойство «Value» (оно должно находиться в интервале [Min,Max]. При этом в линейке прогесс-бара будет отрисовано нужное к-во «квадратиков».

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

  • размещаем прогресс-бар на форме, установив его свойство «Align» в нуль (константа vbAlignNone). При этом прогресс-бар может иметь любые координаты;
  • делаем прогресс-бар невидимым (Visible=False);
  • размещаем на форме статус-бар с несколькими панелями. Решаем, в какой панели будем отображать прогресс-бар.
  • когда прогресс-бар понадобится, вычисляем координаты нужной панели и устанавливаем у нашего прогесс-бара (пока невидимого) свойства «Left», «Top», «Width» и «Height» так, чтобы прогресс-бар «вписался» в нужную панель;
  • делаем прогресс-бар видимым;
  • пользуемся прогресс-баром как обычно;
  • когда прогресс-бар больше не нужен — снова делаем его невидимым.

Способ, как видите, достаточно прост. К недосткам его можно отнести низкую эстетичность — панель для отображения прогресс-бара должна быть достаточно длинной, иначе «квадратики» будут выглядет не очень приглядно. Кроме того, цвет «квадратиков» нельзя менять (по крайней мере, я не знаю, как).

Как-то мне в руки попал известный пример «Прогресс-бар в системном трее». Я подумал: а неплохо было бы организовать прогресс-бар в статус баре в подобном же графическом стиле. Предлагаемая статья как раз об этом.

2. Основная идея

Мы сделаем прогресс-бар в выбираемой панели статус-бара, используя графические функции Windows. Эту же идею мы применим при конструировании прогресс-бара для использования в Excel.

Суть можно сформулировать очень просто: мы будем рисовать в нужной панельки статус-бара прямоугольник, ширина которого характеризует ход выполнения процесса. Одновременно в центре панельки будем показывать процент выполнения. Это будет выглядеть примерно так:

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

3. Приступаем к реализации

А, собственно, какие проблемы? Для рисования прямоугольника есть оператор Line, а для вывода текста — Print. Увы! Эти операторы применимы к форме или к PictureBox. У статус-бара таких методов нет. Что же делать? Можно, конечно, как было описано выше, разместить невидимый PictureBox на форме, а в нужный момент наложить его на выбранную панельку. Желающие могут это проделать, а мы пойдем другим путем: воспользуемся графическим интерфейсом Windows (GDI).

Следующее далее описание ни в коей мере не претендует на полноту; для желающих есть специальные (и очень объемные!) руководства. Автор пользовался «Библией API» Д.Эпплмана.

Базовым понятием графического интерфейса GDI является понятие контекста графического устройства. Контекст устройства можно сравнить с холстом художника — это то, на чем рисуют (наши коллеги-Дельфисты так его и называют «canvas» т.е. канва, холст). Все графические функции Windows требуют ссылки на какой-либо контекст. Как догадываются читатели, контекст — довольно сложная структура. Но нам не требуется проникновения в детали — достаточно получить ссылку на контекст. Visual Basic не позволят сделать это «в одно действие», нам придется сделать это самим.

Контекст можно получить для любого окна, при условии, что известен его хэндл (hwnd). Не у всех визуальных компонентов VB можно получить хэндл окна. К счастью, у статус-бара свойство hwnd обеспечено. Теперь, чтобы получить контекст устройства, достаточно вызвать функцию GetDC. Вот ее описание:

Здесь StatusBar — это статус-бар, расположенный на форме проекта; hwnd — хэндл его окна.

Идеология использования контекстов такова:

  • получаем контекст;
  • сохраняем его;
  • рисуем в контексте все необходимое;
  • восстаналиваем исходный контекст.

Для сохранения контекста служит вызов SaveDC:

Значение переменной iDc (результат, возвращаемый функцией) не следует изменять — он понадобится при восстановлении контекста.

Функцию SaveDc нужно, разумеется, предварительно объявить:

Для восстановления контекста служит функция RestoreDc. Обращение к ней выглядит так:

А вот объявление этой функции:

Итак, «тасовать холсты» мы научились. Займемся рисованием.

Художник рисует кистью. Пользователь Windows GDI — тоже. Кисть — это еще одно базовое понятие GDI. Кисть необходимо создать. Мы будем использовать простейшую кисть — она оставляет сплошной след. Вот как создается такая кисть:

Здесь Color& — цвет кисти (может быть сформирован функцией RGR(RR&,GG&,BB&) или QBcolor(n%). Естественно, функцию CreateSolidBrush нужно предварительно описать:

Читать еще:  Как сделать выпадающую ячейку в excel?

Чтобы нарисовать прямоугольник служит функция Rectangle. Вот ее описание:

Как и говорилось выше, первый параметр — это ссылка на контекст устройства («холст»). Четыре остальных параметра интуитивно понятны — это координаты левого верхнего и правого нижнего угла прямоугольника. Но где же ссылка на кисть? Ее нет. потому что ее нужно выбрать заранее. Это делает функция SelectObject:

Первый параметр — снова ссылка на контекст устройства, а второй — ссылка на кисть (то, что возвращает CreateSolidBrush). Когда кисть создана и выбрана, можно вызвать функцию Rectangle и рисовать прямоугольники.

Поскольку нам предстоит не только рисовать прямоугольники, но и выводить текст (процент выполнения), придется познакомиться с тем, как это делает Windows. Для вывода текста предназначена функция DrawText:

первый параметр — ссылка на контекст, второй параметр — это строка, которую мы хотим вывести, третий — длина строки (имейте в виду, что длина строки должна быть длинным целым). Четвертый параметр задает прямоугольник, в котором будет размещаться текст. Это переменная пользовательского типа RECT:

(Left, Top) — левая верхняя вершина, (Right, Bottom) — правая нижняя.

Параметр wFormat задает положение текста в прямоугольнике. Мы будем использовать вывод по центру:

А чем же задается цвет текста? Цветом кисти? Нет, кисти к тексту никакого отношения не имеют. Для задания цвет текста служит специальная функция SetTextColor:

Про первый параметр я уже не говорю, а второй — это цвет выводимого текста. Текст выводится поверх старого содержимого «холста». Можно задать режим «взаимодействия» текста со старым содержимым. Нас вполне устроит режим вывода текста «как есть» без изменения. Чтобы обеспечить такой режим вывода, нужно вызвать функцию SetBkMode:

декларируется эта функция так:

Результат этой функции (a&) не используется. Второй параметр (единица) как раз и задает нужный режим вывода.

Если не вызвывать функцию SetBkMode, то текст будет выводиться так:

что, согласитесь, не очень симпатично.

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

Все графические функции Windows в качестве единицы измерения понимают только пикселы. А VB позволяет разработчикам использовать самые разные единицы измерения: твипы, пункты, сантиметры, миллиметры, дюймы. Перед обращением к графической функции все координатные параметры должны быть переведены в пикселы. Как это сделать? Не очень трудно.

Начнем с твипов. По определению, твип это (1/1440) дюйма (т.н. «логического дюйма»; подробности — у Д.Эпплмана). Объект Screen в VB имеет два полезных метода:

Первая возвращает количество твипов на пиксел по горизонтали для Вашей видео-системы, вторая — соответственно количество твипов на пиксел по вертикали.

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

  • picX=TwipX/px — для горизонтали;
  • picY=TwipY/py — для вертикали.

Здесь TwipX, TwipY — горизонтальный и вертикальный размеры в твипах, а picX, picY — те же размеры в пикселах.

Теперь нам нетрудно «разделаться» и с другими единицами измерения:

Пункт — это (1/72) дюйма, т.е. пункт равен двадцати твипам. Поэтому для работы с пунктами формулы будут иметь вид:

Дюйм содержит 1440 твипов, поэтому для работы с дюймами формулы будут такие:

С дюймами и пунктами все ясно. Для сантиметров и миллиметров дело обстоит ненамного сложнее. Как известно, 1 дюйм=2.54 см. Поэтому для пересчета сантиметров в пикселы формулы будут такие:

Столь же легко решается проблема пересчета миллиметров в пикселы:

Visual Basic обеспечивает еще одну систему измерения координат — «Знаки». Это чуть более хитрая система. Для нее формулы перевода таковы:

При рисовании наших прямоугольников API-шными вызовами мы должны будем преобразовать все размеры в пикселы. Формулы перевода мы теперь знаем. Но как узнать, какую метрику использует разработчик (который будет пользоваться нашим прогресс-баром)? Заставлять его использовать только пикселы? Слишком жесткое ограничение. Сейчас мы его обойдем. Наш статус-бар, где будет располагаться прогресс-бар, находится на какой-то форме, верно? При этом он наследует ее метрику. А метрику формы задает ее свойство ScaleMode. Таким образом, величина

как раз то, что нам нужно:

Величина scMode- Метрика

Напомню, что Parent — это указатель на родительский объект. Для статус-бара это форма, на которой он расположен.

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

Теперь самое время обсудить интерфейс нашего прогресс-бара. На мой взгляд, лучше всего реализовать наш прогресс-бар в виде класса. Тогда статус-бар и номер панельки, в котором мы рисуем прогресс-бар, цвета всех основных элементов и, разумеется, Min,Max и Value будут свойствами. А отображение очередного состояния можно оформить как метод.

Использование класса оправдано еще и потому, что класс можно потом включить в ActiveX-Dll и распространять в виде библиотеки.

4. Промежуточные итоги

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

В этом классе собраны воедино все идеи, высказанные выше.

Если Вы внимательно анализировали код класса, то наверняка обратили на две внутренние (закрытые) переменные dxCurr и dxLast. Назначение их следующее. Предположим, что наш глобальный цикл, выполнение которого мы хотим визуализировать, выполняется несколько сот тысяч раз, а каждый «виток» выполняется очень быстро. Если вставить обращение к методу ShowProgress в такой цикл, то перерисовка прогресс-бара тоже будет выполняться на каждом витке. При этом возможно, что новое положение закрашенного прямоугольника не будет отличаться от предыдущего. Зачем же его (да, кстати, и текст в центре) перерисовывать? Кроме «отъедания» ресурсов и мигания такая перерисовка ничего не дает. Вот для предотвращения этой ненужной перерисовки и служат переменные dxCurr и dxLast. Если при очередном обращении к ShowProgress dxCurr=dxLast, то рисование обходится.

Как пользоваться этим классом? Очень просто.

Разместите на форме статус-бар с двумя или более панельками. Решите, в какой панельке будет прогресс-бар. Когда прогресс-бар понадобится, пишем:

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

5. Беда! Утечка памяти!

Пару лет назад, когда я создал этот «шедевр», со мной произошла неприятность. Отладив (как мне казалось) класс, я включил его в реальный проект и передал на тестирование. Тестирование ошибок не обнаружило, и программа была передана эксплуатационникам. Сначала все было хорошо. Но через несколько дней мне пожаловались, что при длительной работе моя программа завешивает компьютер. Помогает только перезагрузка. Поскольку проект без прогресс-бара исправно работал и не вызывал проблем, подозрение пало на прогресс-бар. Я быстренько воспроизвел ситуацию, о которой толковали эксплуатационники, и убедился, что при отключении прогресс-бара программа работает четко, а с прогресс-баром через некоторое время виснет. В чем же дело? Оказалось — в том, что я невнимательно читал Д.Эпплмана: созданные кисти нужно уничтожать при уничтожении объекта. Никто за нас это делать не будет!

Если приведенный выше код поместить в объемлющий цикл и выполнить пару тысяч раз — зависание почти неминуемо. Если запустить индикатор системных ресурсов, то отчетливо видно, как они стремительно «утекают». Ситуация эта, кстати, по-английски называется «memory leak» — «утечка памяти».

Чтобы уничтожить кисть нужно воспользоваться API-вызовом DeleteObject:

А вот как эта функция декларируется:

Код терминирования класса должен быть на самом деле таким:

Каюсь перед читателем! Я нарочно включил в тест класса не вполне корректный код терминирования чтобы продемонстрировать собственную (поучительную!) ошибку и сделать соответствующие выводы.

А пример-приложение содержит правильный класс. Он утечки памяти не вызывает.

6. А как быть с Excel?

Во введении я обещал сделать прогресс-бар и для использовании в VBA (применительно к Excel). В чем-то ситуация здесь проще, а в чем-то сложнее.

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

Этот вызов ищет окно по заголовку. У Excel заголовок — «XLMAIN». Естественно, что функция FindWindow должна быть продекларирована:

Функция Prepare теперь принимает вид:

А в остальном класс такой-же, как и для VB, за исключением того, что все размеры только в пикселах, и не нужен пересчет. Перед выводом прогресс-бара рекомендую установить Application.ScreenUpdating=False, а после завершения — вернуть Application.ScreenUpdating=True.

Открывая книгу PBtest.xls, Вы, естественно, должны включить макросы (иначе пример работать не будет!) Для запуска щелкните в главном меню по пункту «Прогресс-бар». Остальное, надеюсь, ясно.

Вы можете скачать готовые примеры на VB и VBA.

Ссылка на основную публикацию
Adblock
detector