はじめに
今回は、ProgressBarのクラスの作成です。
参考に記載されている内容のままですが、次に作るマクロで利用しようと思い、そこで説明するには量が多すぎるため、前提として記載しておこうと思ったったのと、少し気になったところがあったので、それをメモするために記載します。
ProgressBarって今までも使っていましたが、Microsoftが用意する「Microsoft ProgressBar Control」を使ってきました。
今回は、「Label」を使った方法で、ProgressBar相当を自作することになります。
参考に、VBが入っていないと動作しないということが記載されていましたが、私の環境にはVBはインストールされていませんが、「Microsoft ProgressBar Control」は使えていました。
Microsoftのページをみると、「Microsoft ProgressBar Control」は、
「.NET
5 Preview 1
.NET Core
3.13.0
.NET Framework
4.84.7.24.7.14.74.6.24.6.14.64.5.24.5.14.54.03.53.02.01.1」
で適用とのことでしたが、上記に該当するものは、Windows 10のアプリ上では入っていないようで、使用できない環境がどういう時なのか判断つきませんでした。
はじめに2
今回、作成したものを実際に利用してみたところ、ValueやMaxValueの扱い方について、見直したほうが使いやすいと思ったため、修正します。
MaxValueはなくなり、Countに置き換えられます。
今回実施する内容
以下のような、処理に時間がかかる処理の進捗を示す進捗バーを表示します。
ついでにタイトルバーを削除したり、Stopボタンを消したりもできるようにします。
ソースコード(Git Hub)
VBA_06_ProgressBar
修正したファイルは、ファイル名に2を付けます。
環境
OS:Windows 10 JP
Excel: Excel 2019 (64bit)
参考
「プログレスバー」のクラス
プログレスバーのクラスを紹介しています。このサイトにはいつもお世話になっております。
タイトルバーのないユーザーフォームをドラッグで移動
タイトルバーのないユーザーフォームの作り方を紹介しています。
Excel VBA 第5回 Win32APIの取り込みと64bit対応とフォームのサイズ変更
用語
ProgressBarの動作イメージ
ProgressBarの動作のイメージは、以下のようになります。
- 処理開始とProgressBarの初期化
- ProgressBarを開いて処理開始
- 処理を実施
ProgressBarはモーダルなため、いったんProgressBarを開くとセルやシートの移動は抑止されます。
参考にモードレスの紹介もされておりモードレスについてのコメントがありました。
私はそれを読んで、モードレスよりはモーダルが良いと思いましたので、モーダルで作ります。
一番の理由は、処理中にセルなどをいじられて期待しない動作が発生することを防ぎたいということです。
ProgressBarクラスとProgressBarのユーザーフォームの作成
自作のProgressBarは、ProgressBarのクラスと、ProgressBarのユーザーフォームで構成されます。
ProgressBarクラスは、ProgressBarで必要な現在の進捗状況、最大値、ProgressBarの長さなどを管理し、それをProgressBarのユーザーフォームへ伝えます。
ProgressBarのユーザーフォームは、進捗を表すProgressBarを「Label」で実現します。
現在の進捗状況に応じて「Label」の幅を変えることで、進捗が動きを表現します。
Option Explicit
'-----Constant-----
Private Const MAX_WIDTH As Long = 250 'ProgressBarの最大(100%)の幅
'-----Global variable-----
Private G_caption As String 'ProgressBarのタイトル(タイトルバーに表示する名称)
Private G_closeFlag As Boolean 'クローズボタン、ストップボタンの有効無効を示す
Private G_validStop As Boolean '関数の処理中断を許容するかどうかを示す
Private G_stopFunc As Boolean '関数の処理を中断するかどうかを示す
Private G_count As Long 'ProgressBarのループする回数
Private G_value As Long 'ProgressBarの現在の値
Private G_percentage As Long 'ProgressBarのバーセントの値
Private G_progressWidth As Long 'ProgressBarの現在の値の幅(G_valueの値をMAX_WIDTHで換算したProgressBarのWidthの値)
Private G_funcName As String 'ProgressBarで進捗表示するときの実行する関数名
Private G_args() As Variant 'ProgressBarで進捗表示するときの実行する関数の引数の配列
'-----Property-----
'ProgressBarのタイトルバーに表示する名称を取得する。
Public Property Get Caption() As String
Caption = G_caption
End Property
'ProgressBarのタイトルバーに表示する名称を設定する。
Public Property Let Caption(strCaption As String)
G_caption = strCaption
End Property
'ProgressBar上で、クローズボタン、および、ストップボタンを有効にするかの設定を取得する。
Public Property Get CloseFlag() As Boolean
CloseFlag = G_closeFlag
End Property
'ProgressBarで、クローズボタン、および、ストップボタンを有効にするかを設定する。
'TrueはCloseボタン有効で、FalseはCloseボタン無効である。
'デフォルトはFalseであり、無効である。
Public Property Let CloseFlag(bCloseFlag As Boolean)
G_closeFlag = bCloseFlag
End Property
'ProgressBarで、関数の処理中断を有効にするかの設定を取得する。
Public Property Get ValidStop() As Boolean
ValidStop = G_validStop
End Property
'ProgressBarで、関数の処理中断を有効にするかを設定する。
Public Property Let ValidStop(bValidStop As Boolean)
G_validStop = bValidStop
End Property
'実行中の関数を中断するかどうかを設定する。
Public Property Get StopFunc() As Boolean
StopFunc = G_stopFunc
End Property
'実行中の関数を中断するかどうかを設定する。
Public Property Let StopFunc(bStopFunc As Boolean)
G_stopFunc = bStopFunc
End Property
'ProgressBarのループする回数を取得する。
Public Property Get Count() As Long
Count = G_count
End Property
'ProgressBarのループする回数を設定する。
Public Property Let Count(lngNewValue As Long)
G_count = lngNewValue
ProgressBarForm.Count = G_count
End Property
'ProgressBarの現在の値を取得する。
Public Property Get Value() As Long
Value = G_value
End Property
'ProgressBarの現在の値と、ProgressBarの幅を設定する。
'設定時に、最大値に達した場合はProgressBarの幅を最大値に設定する。
Public Property Let Value(lngNewValue As Long)
G_value = lngNewValue
If G_value >= G_count Then
ProgressBarForm.Value = G_value
ProgressBarForm.Percentage = 100
ProgressBarForm.ProgressBar.Width = MAX_WIDTH
Exit Property
End If
G_percentage = Int((G_value / G_count) * 100)
G_progressWidth = Int((G_value * MAX_WIDTH) / G_count)
G_stopFunc = ProgressBarForm.StopFunc
ProgressBarForm.Value = G_value
ProgressBarForm.Percentage = G_percentage
ProgressBarForm.ProgressBar.Width = G_progressWidth
DoEvents
End Property
'ProgressBarで進捗表示する関数名を取得する。
Public Property Get FuncName() As String
FuncName = G_funcName
End Property
'ProgressBarで進捗表示するときの実際の関数名を設定する。
Public Property Let FuncName(strFuncName As String)
G_funcName = strFuncName
End Property
'ProgressBarで進捗表示するときの実際の関数の引数を取得する。
Public Property Get Args() As Variant()
Args = G_args
End Property
'ProgressBarで進捗表示するときの実際の関数の引数を設定する。
Public Property Let Args(strArgs() As Variant)
G_args = strArgs
End Property
'-----Class Initialize-----
Private Sub Class_Initialize()
End Sub
'------Function-----
'設定した関数(FuncName)を処理する間、ProgressBarを表示し、処理する。
Public Sub Show()
ProgressBarForm.Caption = G_caption
ProgressBarForm.CloseFlag = G_closeFlag
ProgressBarForm.ValidStop = G_validStop
ProgressBarForm.FuncName = G_funcName
ProgressBarForm.Args = G_args
Call ProgressBarForm.Show 'ProgressBarの表示と処理実施。
Call Unload(ProgressBarForm) 'ProgressBarのUnload。
End Sub
ProgressBarクラスの機能
ProgressBarクラスの機能は主に以下です。
- ProgressBarのタイトルバーの名称設定
- ProgressBarのクローズボタン、およびストップボタンの表示可否
- ProgressBarの処理中断の有効無効設定
- ProgressBarの最大値設定
- ProgressBarの現在の進捗設定
- ProgressBarの幅設定
- ProgressBarで実施する関数(引数含む)の実施
ProgressBarのプロパティについて
画面に関するプロパティは、以下の通り。
プロパティ名 | 型 | 範囲 | 説明 |
---|---|---|---|
Caption | String | Stringの範囲。デフォルトはProgressBar。 | タイトルバーに表示される名称の取得、設定。現在のProgressBarの枠サイズで最大半角で48文字程度である。 |
CloseFlag | Boolean | True / False。デフォルトはFalse。 | タイトルバーの「x」ボタン、およびProgressBarの「Stop」ボタンを表示するかどうかを設定する。Trueは有効で、Falseは無効。 |
ValidStop | Boolean | True / False。デフォルトはFalse。 | ProgressBarで実施する関数による処理中断を有効にするかを設定する。Trueは有効で、Falseは無効。処理の中断は、Stopボタン、ESCキー、もしくは、Alt+F4キーで実施する。 |
ProgressBarの処理に関するプロパティは、以下の通り。
プロパティ名 | 型 | 範囲 | 説明 |
---|---|---|---|
StopFunc | Boolean | True / False。デフォルトはFalse。 | 関数実行中に関数を中断する場合に設定する。Trueは中断実施で、Falseは中断しない。 |
Count | Long | Longの範囲。デフォルトは0。 | ProgressBarのループする回数の取得、設定。 |
Value | Long | Longの範囲。デフォルトは0。 | ProgressBarの現在の位置の取得、設定。Countを超えることは想定されない。Countを超える設定する場合、ProgressBarの幅は、最大幅に抑えられる。 |
FuncName | String | Stringの範囲。デフォルトなし。 | 実行する関数の関数名の取得、設定。 |
Args() | Variant | Variantの範囲。デフォルトなし。 | 実行する関数の引数を含めた配列の取得、設定。引数の型は様々想定されるため、Variant型を使用する。 |
ソースの説明
参考に記載している内容とほぼ同じなため多くの説明を割愛しますが、変数名などはオリジナルから変えていますので少しわかりにくいかもしれません。
Constant
MAX_WIDTH
は250に設定していますが、ProgressBarのユーザーフォームのLabelで設定するwidthの値であり、ユーザーフォームでサイズを変えるようであれば変更する必要性があります。
本クラスとProgressBarのユーザーフォームはセットとして一緒に扱う必要があります。
Global variable
G_funcNameとG_args()は、実行する関数名と、引数です。
「G_args()」は引数を、Variant型の配列で設定します。
参考には記載がありませんでしたが、関数に引数を設けたかったため作りました。
Property
基本的に各Global変数の設定・取得のPropertyです。
MaxValueは、ProgressBar上の画面で数値で表示される最大値であり、設定と同時にProgressBarのユーザーフォームに設定します。
Valueは、ProgressBar上の画面で数値、および「Label」の幅で表示される現在の進捗状況を示す値であり、設定と同時に、ユーザーフォーム上でも設定します。
また、進捗をパーセント表示するため、パーセントの計算も行います。すべて実施するとDoEventsを実施して、画面の描画を行います。
Function
Show
は、事前に設定したPropertyに従って、ProgressBarを設定し、設定した関数を実施しながらProgressBarで進捗を表示します。処理が完了したら、ProgressBarをUnloadします。
処理がおわると、Unloadすることで、ProgressBarFormを初期状態に戻します。
1. 処理開始とProgressBarの初期化
処理を開始するSub関数の作成とProgressBarの初期化を実施します。
以下のModule1.bas
は、「3. 処理を実施」のソースも含みます。
実際に使用する場合は、この部分をプログラマーが作成しますので、今回はサンプルで2つ作りました。
ひとつは、ProgressBarのタイトルバーがあり実行する関数に引数がないパターンと、ProgressBarのタイトルバーがなく実行する関数に引数があるパターンです。
- ProgressBarのタイトルバーがあり実行する関数に引数がないパターン
ProgressBarMain
とLoopProcess
で構成されます。
ProgressBarMain
は、処理を開始するSub関数であり、ProgressBarの初期化を行います。
初期設定において、CloseFlagは設定するため、タイトルバーのあるProgressBarとなります。
G_PBar.Argsの設定はせず、関数の引数はありません。
LoopProcess
は、処理のループをしているだけでほとんど中身はありません。
LoopProcess
は、処理のループをしているだけでほとんど中身はありません。
ループ処理の初期値を0から開始して、G_PBar.Count - 1まで実施しています。処理内で、G_PBar.Valueの値をインクリメントすることで、ProgressBarの進捗を更新しています。
引数がないパターンであり、呼び出し元の都合上、引数は設定しており、p() As Variant
は必要です。しかし、関数内では使用していません。
- ProgressBarのタイトルバーがなく実行する関数に引数があるパターン
ProgressBarMain
とLoopProcess
で構成されます。
ProgressBarMain
は、処理を開始するSub関数であり、ProgressBarの初期化を行います。
初期化において、CloseFlagを設定しないため、タイトルバーのないProgressBarとなります。
ValidStopはTrueに設定するため、LoopProcess
は、処理のループをしているだけでほとんど中身はありません。
ループ処理の初期値を0
から開始して、G_PBar.MaxValueまで実施しています。処理内で、G_PBar.Valueの値をインクリメントすることで、ProgressBarの進捗を更新しています。
また、G_PBar.StopFuncがTrueになると関数を終了します。中断処理が必要な場合は、記載が必要です。
Option Explicit
Private Declare PtrSafe Sub Sleep Lib "KERNEL32.dll" (ByVal dwMilliseconds As Long)
Private G_PBar As Cls_ProgressBar
Public Sub ProgressBarMain()
Set G_PBar = New Cls_ProgressBar
G_PBar.Caption = "LoopProcess2"
G_PBar.Count = 5
G_PBar.FuncName = "LoopProcess"
G_PBar.CloseFlag = True
G_PBar.ValidStop = False
G_PBar.Show
End Sub
Public Function LoopProcess(p() As Variant)
Dim i As Long
For i = 0 To G_PBar.Count - 1
If G_PBar.StopFunc Then
Exit Function
End If
Sleep 10
Debug.Print i
G_PBar.Value = G_PBar.Value + 1
Next
End Function
Public Sub ProgressBarMain2()
Dim Args() As Variant
Set G_PBar = New Cls_ProgressBar
G_PBar.Count = 1000
G_PBar.FuncName = "LoopProcess2"
G_PBar.ValidStop = True
ReDim Args(0)
Args(0) = "ProgressBar"
G_PBar.Args = Args
G_PBar.Show
End Sub
Public Function LoopProcess2(p() As Variant)
Dim i As Long
For i = 0 To G_PBar.Count - 1
If G_PBar.StopFunc Then
Exit Function
End If
Sleep 10
Debug.Print p(0) & i
G_PBar.Value = G_PBar.Value + 1
Next
End Function
2. ProgressBarを開いて処理開始
G_Pbar.Showにより、ProgressBarが表示されて、そこで指定した関数が実施されます。
Object名 | 説明 |
---|---|
Value | 現在の進捗を示すLabel。進捗によって更新される。 |
Count | このループ処理を実施する回数を示すLabel。 |
Percentage | 進捗を割合で示すLabel。 |
StopButton | 処理を中断する場合に押すCommandButton。StopButtonのCancelをTrueに設定(ESCボタンで実行するため)。 |
ProgressBar | 進捗を示すLabelでValueの値に従って進捗を示す。 |
Label1 | 進捗の枠を示すLabel。特に画面上の枠のために使っているだけである。 |
Option Explicit
'-----Windows API宣言-----
Private Const GWL_EXSTYLE = (-20) '拡張ウィンドウスタイルのハンドラ番号
Private Const GWL_STYLE As Integer = (-16) 'ウィンドウスタイルのハンドラ番号
Private Const WS_EX_DLGMODALFRAME As Long = &H1 '拡張ウィンドウスタイルで二重境界線のウィンドウをつける。タイトルバーを付けるのに必要になる。
Private Const WS_MAXIMIZEBOX As Long = &H10000 'ウィンドウスタイルで最大化ボタンをつける
Private Const WS_MINIMIZEBOX As Long = &H20000 'ウィンドウスタイルで最小化ボタンを付ける
Private Const WS_THICKFRAME As Long = &H40000 'ウィンドウスタイルでサイズ変更をつける
Private Const WS_SYSMENU As String = &H80000 'ウィンドウスタイルでコントロールメニューボックスをもつウィンドウを作成する
Private Const WS_CAPTION As Long = &HC00000 'ウィンドウスタイルでタイトルバーをつける
Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
# If Win64 Then
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
# Else
Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
# End If
'-----Global variable-----
Private G_closeFlag As Boolean 'タイトルバーのクローズボタン、および、ストップボタンの有効無効を示す。
Private G_validStop As Boolean '関数の処理中断を許容するかどうかを示す。
Private G_stopFunc As Boolean '慣習の処理中断を実施するかどうかを示す。
Private G_funcName As String
Private G_args() As Variant
'-----Property-----
'ProgressBarで、クローズボタン、および、ストップボタンの有効無効を設定する。
'Trueはボタン有効で、Falseはボタン無効である。
'デフォルトはFalseであり、無効である。
Public Property Let CloseFlag(bCloseFlag As Boolean)
G_closeFlag = bCloseFlag
End Property
'ProgressBarで、関数の処理中断を許容するかどうかを設定する。
'Trueは中断有効で、Falseは中断無効である。
'デフォルトは処理中断無効である。
'クローズボタン、およびストップボタンが有効である場合、この設定は関係なく、処理中断可能となる。
Public Property Let ValidStop(bValidStop As Boolean)
G_validStop = bValidStop
End Property
'ProgressBarの進捗表示の実行中の関数を中断するかどうかを設定する。
Public Property Get StopFunc() As Boolean
StopFunc = G_stopFunc
End Property
'ProgressBarの進捗表示の実行中の関数を中断するかどうかを示す。
Public Property Let StopFunc(bStopFunc As Boolean)
G_stopFunc = bStopFunc
End Property
'ProgressBarで進捗表示するときの関数名を設定する。
Public Property Let FuncName(strFuncName As String)
G_funcName = strFuncName
End Property
'PregressBarで進捗表示するときの関数の引数を設定する。
Public Property Let Args(strArgs() As Variant)
G_args = strArgs
End Property
'-----Function-----
'ストップボタンをクリックした場合に動作する。
'実行中の関数の処理を中断する。
Private Sub StopButton_Click()
Call StopProcess
End Sub
'ProgressBarが活性化されたときに実施する。
'Closeボタンを非表示にする。
Private Sub UserForm_Activate()
Dim hwnd As LongPtr
Dim WndStyle As LongPtr
Dim lngHeight As Long
ProgressBar.Width = 0
If Not G_closeFlag Then 'クローズボタンを無効にする場合
lngHeight = Me.InsideHeight
hwnd = GetActiveWindow()
WndStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE) 'ウィンドウの拡張スタイルを取得
WndStyle = WndStyle And (Not WS_EX_DLGMODALFRAME)
Call SetWindowLongPtr(hwnd, GWL_EXSTYLE, WndStyle)
WndStyle = GetWindowLongPtr(hwnd, GWL_STYLE) 'ウィンドウのスタイルを取得
WndStyle = WndStyle And (Not WS_CAPTION)
WndStyle = WndStyle And (Not WS_SYSMENU)
Call SetWindowLongPtr(hwnd, GWL_STYLE, WndStyle)
Me.Height = lngHeight
StopButton.Top = 100
End If
Call Application.Run(G_funcName, G_args)
Call Me.Hide 'ここで本ユーザフォームを隠す。この処理がないとModal状態から抜けられない。
End Sub
'ProgressBarがクローズされる場合に実施する。
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then 'メニューのxボタンやAlt+F4などによる中断の場合
Call StopProcess
Cancel = True '閉じる処理をここではいったん中断するためにTrue。ここでクローズすると、StopProcessでこのFormが閉じられ、変数が初期化されるため。
End If
End Sub
Private Sub StopProcess()
If G_validStop Or G_closeFlag Then
G_stopFunc = True
End If
End Sub
ソースの説明
Windows API宣言
第5回にも使用したAPI宣言をしていますが、GWL_EXSTYLE
、WS_EX_DLGMODALFRAME
、WS_CAPTION
を追加しました。
タイトルバーのないユーザーフォームをドラッグで移動を参考に、タイトルバーを削除する実装を可能とするためです。
GWL_EXSTYLEは
、拡張スタイルのハンドラです。
ここで取得した拡張スタイルで、WS_EX_DLGMODALFRAME
をなしに設定すると、当該ウィンドウの外枠の線が消えます。
WS_CAPTION
は、タイトルバーの有無を設定できますので、これを設定すると、タイトルバーがなくなります。
Global variable
ここで、設定される変数は、ProgressBarクラスにある変数と同じものです。
Property
ここで、設定されるプロパティは、ProgressBarクラスにあるプロパティとほぼ同じものです。こちらは設定と取得だけで内部での処理は存在しません。
Function
StopButton_Click
は、StopButtonを押した場合に実行されます。StopButton
のCommandButtonのCancel
をTrueに設定するため、ESCキーを押しても実行されます。
処理を中断するStopProcess
を実行します。
UserForm_Activate
は、ユーザーフォームが活性化されたときに実行されます。
タイトルバーのないユーザーフォームをドラッグで移動を参考に作成しました。この参考資料では、UserForm_Initialize上で処理をするように記載がされていましたが、今回作成したProgressBarは、UserForm_Initializeではなく、UserForm_Activateで実施としました。
UserForm_Initializeでも試したのですが、今回作成したProgressBarでは、UserForm_Initializeが発生するタイミングは、Module1.bas
のProgressBarMain
で、G_PBar.Valueを設定したタイミングであり、その時には、まだProgressBarが表示されておらず、
GetActiveWindowで、ProgressBarFormの
hwnd`を取得できなかったためです。
今回のProgressBarは、Modalで作成しているため、処理が終了、もしくは中断するまでUserForm_Activateは1回しか発生しないと思われるため、よしとしました。
また、クローズボタンを無効にする場合(G_closeFlagがFalse)、タイトルバーをなくす都合上ProgressBarFormの高さHeightを変えていますが、これも参考とは違う形となりました。
参考では、
uf.Height = uf.Height - uf.InsideHeight + ih
となっており、ufは該当フォームのObject、ihはタイトルバーを削除する前の該当フォームの高さです。
ユーザフォームの高さ - 新ユーザフォームの内部の高さ + 旧ユーザフォームの内部の高さ
ということであり、タイトルバーを削除した前後で該当フォームの内部の高さが変化しているものを調整する式と思いますが、私の環境ではうまく動作しませんでした(前後でInsideHeightの値が同じになる)。
そのため、
Me.Height = lngHeight
として、高さをタイトルバー削除前の内部の高さにすることにしました。
たぶんこれでも問題ないようには思いますが、もしかすると少しマージンを加えたほうがよいのかもしれません。
StopButton.Top = 100
の部分は、Stopボタンを画面の外にだすための処理で、G_closeFlagで、クローズボタンをなくすときに、ボタンとして用意したStopボタンも見えなくしています。しかし、ESCキーによる中断は許容できるように、Visibleで消しているわけではなく、画面の範囲外にしています。
また、この関数内では、Application.Runを実行することで、関数名と引数を設定して関数を実施します。
Application.RunよりもCallByName関数を使用したほうが処理が速くなるのではと試行錯誤しましたが、そのためのクラスを作ったりとかなり面倒で、使う時に難解だったこと、処理が遅いといっても1回しか動作しない部分のためほとんど関係がないことから、そのままApplication.Runを使いました。
最後に、Me.Hideとし、ProgressBarFormを隠します。ProgressBarFormはモーダルのため、これを記載しないと、UserForm_Activate
から抜けることができず、ProgressBarが100%で止まって、そのままになってしまいます。
UserForm_QueryClose
は、ProgressBarが閉じられる場合に発生する関数です。正常に処理が終了した場合や、中断した場合に実行されますので、CloseModeがvbFormControlのような中断した場合に、中断処理するIf文としました。
If文内は、StopProcessを呼び出し、また、通常のClose処理を中断するため、Close = Trueとしました。
なお、正常終了する場合は、特別な処理はなく、そのままクローズされます。
StopProcess
は、中断処理が有効(G_validStop)か、クローズボタンがある場合(G_closeFlag)に、G_stopFuncをTrueにして中断処理を実施します。
G_validStopをFalseにしても、クローズボタンがあると中断処理ができてしまうところが、混乱の要因と思いましたが、クローズボタンなしで、ESCキーによる中断だけ許容などもあり得ると思ったため、このようにしました。
混乱をまねくようならば、ProgressBarクラスのProperty設定時にエラーを出力するようにしてもよいとは思いましたが、いまのところは何もしていません。
実際の中断処理は、Module1.bas
のLoopProcess
内に記載します。
おわりに
これで一通り動作します。
最初に記載した通り、作成してる内容は、参考に記載してある内容と同一であり、大変申し訳ありませんが、「はじめに」に記載の通り、備忘として載せました。