【ExcelVBA】処理の経過(進行)をバーで表示するプログラム(プログレスバー)

How to create a progress bar with ExcelVBA

こんにちは!大阪市住之江区に拠点を置く会社『縁紡ぐ』の稲垣です。

当社は、Excel、ACCESS、RPAなどのシステム開発や既存ツールを使った業務効率化の提案、また、ITスキルアップのための教育に力を入れています。効率的なビジネス運営を目指している企業様、ITスキルの向上を図りたい企業や個人の方に、最適なご提案をさせていただきます。業務プロセスの改善とITスキルアップをサポートし、共に成長するパートナーでありたいと考えています。

目次

【ExcelVBA】処理の経過(進行)をバーで表示するプログラム(プログレスバー)

処理時間が長い時に、ユーザーがフリーズしたのか処理が長いだけなのかをわかってもらうための処理状況を表示するバーを表示するプログラムを紹介します。

作成の流れ

まずは全体の作成の流れです。

STEP
処理状況を表示するフォームを作成
STEP
処理状況を表示するクラスか標準モジュールを作成
STEP
クラスをインスタス化して使用するか、標準モジュールを使用する

クラスと標準モジュール両方ともで使いまわしが出来るように作成方法をご紹介します。

フォームの作成

まずは、処理状況を表示するためのフォームを作成をしていきましょう!

STEP
フォームの作成
STEP
フォームのオブジェクト名を「ProgressTimerForm」に変更
STEP
フォームオブジェクトのCaptainを「処理状況」に変更
STEP
バック用のラベルを配置してプロパティを変更
 オブジェクト名:lblBackground
 BackColor:&H80000000&
STEP
処理状況を表示するラベルを同じ場所に追加
 オブジェクト名:lblProgress
 BackColor:&H8000000D&

最初は、後で追加したlblProgressの幅を0にして、処理が進むごとにwidth(幅)を1,2,3と増やしていくことで、青のラベルの幅が広くなり処理が進んでいるように見えます。

クラスの作成

クラスの作成です。標準モジュールでの作り方は次に記載しています。

STEP
クラスの作成
STEP
クラスのオブジェクト名を「ProgressTimer」に変更
STEP
クラスにコードを記載する
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

標準モジュールの作成

次は、標準モジュールでの作成方法です。

STEP
標準モジュールを作成
STEP
モジュール名を「ProgressTimer」に変更
STEP
モジュールにコードを記載する
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.
  • 業務フロー図の作成や業務時間分析を通して、効率化ポイントを探る人
  • お客様にとって本当に良いことかを第一に考える人
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次