こんにちは!大阪市住之江区に拠点を置く会社『縁紡ぐ』の稲垣です。
当社は、Excel、ACCESS、RPAなどのシステム開発や既存ツールを使った業務効率化の提案、また、ITスキルアップのための教育に力を入れています。効率的なビジネス運営を目指している企業様、ITスキルの向上を図りたい企業や個人の方に、最適なご提案をさせていただきます。業務プロセスの改善とITスキルアップをサポートし、共に成長するパートナーでありたいと考えています。
【ExcelVBA】処理の経過(進行)をバーで表示するプログラム(プログレスバー)
処理時間が長い時に、ユーザーがフリーズしたのか処理が長いだけなのかをわかってもらうための処理状況を表示するバーを表示するプログラムを紹介します。
作成の流れ
まずは全体の作成の流れです。
クラスと標準モジュール両方ともで使いまわしが出来るように作成方法をご紹介します。
フォームの作成
まずは、処理状況を表示するためのフォームを作成をしていきましょう!
オブジェクト名:lblBackground
BackColor:&H80000000&
オブジェクト名:lblProgress
BackColor:&H8000000D&
最初は、後で追加したlblProgressの幅を0にして、処理が進むごとにwidth(幅)を1,2,3と増やしていくことで、青のラベルの幅が広くなり処理が進んでいるように見えます。
クラスの作成
クラスの作成です。標準モジュールでの作り方は次に記載しています。
Option Explicit
'#######################################
'目的:処理時間をバー形式で表示する
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
'インスタンス変数
Private frmProgressProgress As ProgressTimerForm
Private lblBackground As MSForms.Label
Private lblProgress As MSForms.Label
Private maxStep As Long
Public Sub Class_Initialize()
'#######################################
'目的:コンストラクタ
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:ProgressTimerFormを利用
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
Set frmProgressProgress = ProgressTimerForm
Set lblBackground = frmProgressProgress.lblBackground
Set lblProgress = frmProgressProgress.lblProgress
frmProgressProgress.StartUpPosition = 1 'Windowsの既定値
lblProgress.Width = 0 ' 初期状態で進捗バーを幅0にする
End Sub
Property Let setMaxStep(ByVal maxStepValue As Long)
'#######################################
'目的:インスタンス変数maxStepに値を代入
'引数:整数
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
maxStep = maxStepValue
End Property
Public Sub updateProgress(ByVal step As Long)
'#######################################
'目的:現在処理しているステップ数を引数に進捗状況バーを更新する
'引数:現在のステップ数を正数で
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing And Not lblProgress Is Nothing And Not lblBackground Is Nothing Then
If maxStep < 10000 Then
lblProgress.Width = (step / maxStep) * lblBackground.Width
frmProgressProgress.Repaint '再描画
Else
If step Mod 100 = 0 Then
lblProgress.Width = (step / maxStep) * lblBackground.Width
frmProgressProgress.Repaint '再描画
End If
End If
End If
End Sub
Public Sub show()
'#######################################
'目的:処理状況を描画するProgresssTimerFormを表示する
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing Then
frmProgressProgress.show vbModeless
End If
End Sub
Public Sub hide()
'#######################################
'目的:処理状況を描画するProgresssTimerFormの表示を終了する
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing Then
frmProgressProgress.hide
End If
End Sub
クラスをインスタンス化して使う方法
それでは、早速つくったクラスで処理バーを表示してみましょう!
Option Explicit
Sub TestProgressBar()
'ProgressTimerの変数宣言とインスタンス作成
Dim progressTimer As progressTimer
Set progressTimer = New progressTimer
'変数宣言
Dim i As Long
Dim maxSteps As Long
maxSteps = 10000000 ' 進捗の最大ステップ数を設定
progressTimer.setMaxStep = maxSteps 'インスタンス変数に代入
progressTimer.show 'フォームを表示
'繰り返し処理
For i = 1 To maxSteps
' 進捗を更新
progressTimer.updateProgress i
Next i
'後処理
progressTimer.hide 'フォームを閉じる
Set progresstime = Nothing
End Sub
標準モジュールの作成
次は、標準モジュールでの作成方法です。
Option Explicit
'#######################################
'目的:処理時間をバー形式で表示する
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/8/3 合同会社縁紡ぐ 稲垣
'#######################################
Private frmProgressProgress As ProgressTimerForm
Private lblBackground As MSForms.Label
Private lblProgress As MSForms.Label
Private maxStep As Long
Public Sub InitializeProgressBar()
'#######################################
'目的: 処理状況を描画するProgresssTimerFormの初期化と表示
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:ProgressTimerFormを利用
'作成日 作成者 2024/8/3 合同会社縁紡ぐ 稲垣
'#######################################
Set frmProgressProgress = ProgressTimerForm
Set lblBackground = frmProgressProgress.lblBackground
Set lblProgress = frmProgressProgress.lblProgress
frmProgressProgress.StartUpPosition = 1 'Windowsの既定値
lblProgress.Width = 0 ' 初期状態で進捗バーを幅0にする
frmProgressProgress.show vbModeless
End Sub
Public Sub setMaxStep(ByVal maxStepValue As Long)
'#######################################
'目的:maxStepに値を代入
'引数:整数
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/8/3 合同会社縁紡ぐ 稲垣
'#######################################
maxStep = maxStepValue
End Sub
Public Sub updateProgress(ByVal step As Long)
'#######################################
'目的:現在処理しているステップ数を引数に進捗状況バーを更新する
'引数:現在のステップ数を正数で
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/8/3 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing And Not lblProgress Is Nothing And Not lblBackground Is Nothing Then
If maxStep < 10000 Then
lblProgress.Width = (step / maxStep) * lblBackground.Width
frmProgressProgress.Repaint '再描画
Else
If step Mod 100 = 0 Then
lblProgress.Width = (step / maxStep) * lblBackground.Width
frmProgressProgress.Repaint '再描画
End If
End If
End If
End Sub
Sub HideProgressBar()
'#######################################
'目的:処理状況を描画するProgresssTimerFormの表示を終了する
'引数:なし
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/8/3 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing Then
frmProgressProgress.hide
Set frmProgressProgress = Nothing
End If
End Sub
使ってみる
Option Explicit
Sub TestProgressBar()
'変数宣言
Dim i As Long
Dim maxSteps As Long
maxSteps = 10000000 ' 進捗の最大ステップ数を設定
progressTimer.setMaxStep maxSteps
progressTimer.InitializeProgressBar 'フォームを表示
'繰り返し処理
For i = 1 To maxSteps
' 進捗を更新
progressTimer.updateProgress i
Next i
'後処理
progressTimer.HideProgressBar 'フォームを閉じる
End Sub
処理状況を表示することで処理が遅くなる💦
今回は、ExcelのVBAで処理状況を表示する方法をご紹介しました。ただし、この処理状況を表示することによって、かなり処理速度が遅くなります💦
描画を何度もやり直しているのが原因です。
100000回描画を更新した場合
10回に1回描画を更新した場合
全然スピードが変わりますね。
変更点は、updateProgressメソッドに再描画する条件をつけます。
Public Sub updateProgress(step As Long)
'#######################################
'目的:現在処理しているステップ数を引数に進捗状況バーを更新する
'引数:現在のステップを整数で
'戻り値:なし
'エラー処理:
'メモ:
'作成日 作成者 2024/4/15 合同会社縁紡ぐ 稲垣
'#######################################
If Not frmProgressProgress Is Nothing And Not lblProgress Is Nothing And Not lblBackground Is Nothing Then
If step Mod 10 = 0 Then
lblProgress.Width = (step / maxStep) * lblBackground.Width
frmProgressProgress.Repaint '再描画
End If
End If
End Sub
処理の最大数によって、条件をわけるのもありだと思います。適宜修正してもらったらと思います。
まとめ
今回は、処理の進捗状況を表示するバーを作成しました。が、あまりにも描画の更新数が多いと、処理がかなり遅くなるという欠点もわかりましたね!
大切なのは、ユーザーがExcelが固まったのか、ちゃんと動いるけど処理に時間がかかっているからまだ待たないといけないのか。これが、わかってもらうことです。
稲垣
- Excel、ACCESSでのシステム開発が得意
- ITスキルを共有し実践的に学びながら成長する人を見るのが幸せ
- 自家焙煎するほどのコーヒー好き
- 使用言語 VBA、Python、Javascript、Java、HTML、CSS etc.
- 保有資格 Kintoneアソシエイト、日商簿記検定2級、マンション管理士、管理業務主任者、情報セキュリティマネジメント、ExcelVBA etc.
- 業務フロー図の作成や業務時間分析を通して、効率化ポイントを探る人
- お客様にとって本当に良いことかを第一に考える人
コメント