VBA で ProgressBar UserForms をモーダルまたはモードレスとして表示するのはどちらが良いでしょうか?

StackOverflow https://stackoverflow.com/questions/2169975

質問

VBA で ProgressBar UserForms をモーダルまたはモードレスとして表示するのはどちらが良いでしょうか?VBA で進行状況インジケーターを開発するためのベスト プラクティスは何ですか?

モードレス ユーザー フォームでは、次の使用が必要です。 Application.Interactive = False, 一方、モーダル ユーザーフォームは、その性質上、コアの手順が完了するかキャンセルされるまで、アプリケーションとの対話をブロックします。

もし Application.Interactive = False が使用されますが、Esc キーはコードの実行を中断するため、 Application.EnableCancelKey = xlErrorHandler およびエラー処理 (Err.Number = 18) ユーザーフォームと呼び出しプロシージャの両方で必要です。

リソースを大量に消費する呼び出しプロシージャによって、次のような問題が発生する可能性もあります。 CommandButton_Click そして UserForm_Activate モードレス ユーザー フォームでイベントが誤発生する。

一般に、モーダル UserForm を使用する進行状況インジケーターは、実行中のコードが完全に UserForm モジュールに含まれており、変数を渡す必要が少ないため、より単純に見えます。

ただし、進行状況インジケーターにモーダル UserForms を使用する場合の問題は、呼び出し元のプロシージャが UserForm_Activate プロシージャ内にある必要があるため、進行状況インジケーターを必要とするすべてのプロシージャに個別の UserForm モジュールが必要になることです。

したがって、モードレス ユーザー フォームに単一の再利用可能な進行状況インジケーターを含めることは可能ですが、複数のモーダル ユーザー フォーム内からコードを実行する場合よりも信頼性が低くなります。

どちらの方法が良いですか?

ありがとう!

役に立ちましたか?

解決 2

私はこの1つを閉じて、モーダルが勝者であると言うつもりです。私は両方の方法を試してみましたが、あなたはモードレスユーザーフォームであまりにも多くの抜け穴を閉じるしようとして終わります。それは、より厳格であるため、モーダルはより困難であるが、それはともかく、長期的に優れている小さな塊にあなたのコードを壊すためにあなたを奨励しています。

他のヒント

Application.StatusBarを使用して、また、第三の方法があります。 あなたも、U + 25A0とU + 25A1の文字列を使用することにより、真のプログレスバーをシミュレートすることができます。

間違いモーダル。 あなたはモードレスを検討しようとしている場合は、別々のアウトプロセスのスレッドではないのExcel.exeメインスレッド上で実行するべきである。

質問が非常にうまくまとめられているため、Google が最初に見つけてくれるので、最初のトピックには返信する価値があると思います。

セクション 1 - 理論

最初のもの つまり、モジュール間で変数を転送するのはまったく難しいことではありません。

必要なのは、別のモジュールを作成し、そこにすべてのグローバル変数を配置することだけです。そうすれば、すべてのフォーム、シート、モジュールのどこからでもそれらを読み取ることができるようになります。

2番目のこと ウィンドウはモードレスである必要があります。どうして?答えは コードの可動性を維持するため, 、つまり

  1. 最も日常的な処理が実行される関数を UserForm モジュールに配置しない
  2. どこからでもプログレスバーを備えたウィンドウを呼び出すことができ、
  3. ルーチン関数/プロシージャ間の唯一の接続はグローバル変数です

ここで多用途であることは大きな利点です。

セクション 2 - 実践

1) モジュールを作成する "宣言" グローバル変数を使用して:

整数としてのパブリックストップフォース 'この変数は、ユーザーがキャンセルボタンを押したインジケーターとして使用されます

パブリックPCTDoneをシングルとして ' これは、すでに完了した作業の割合です

Public CurrentFile As String ' フォームに転送するその他のパラメータ。

2) ボタンでフォームを作成します。ボタンの OnClick イベントには、グローバル変数を参照するコードが必要です。 ストップフォース宣言 モジュール

 Private Sub CommandButton1_Click()

 Declaration.StopForce = 1
  End Sub

3) プログレスバーを更新するプロシージャを 1 つ追加します。

Sub UpdateProgressBar(PCTDone_in As Single)
With UserForm1
    ' Update the Caption property of the Frame control.
    .FrameProgress.Caption = Format(PCTDone_in, "0%")
    ' Widen the Label control.
    .LabelProgress.Width = PCTDone_in * _
        (.FrameProgress.Width)
    ' Display the current file from global variable   
    .Label1.Caption = Declaration.CurrentFile
End With
End Sub

4) 他のモジュールには、ルーチンが実行される関数またはプロシージャ/サブルーチンが必要です。

 For i=1 to All_Files

 Declaration.CurrentFile = myFiles (i)

 FormFnc.UpdateProgressBar (i / .Range("C11").Value)


 DoEvents

 If Declaration.StopForce = 1 Then
    GoTo 3
 End If

 Next i

実際には、プロパティを以下のあなたの必要性に応じて、長所/短所が生じています:

Type      | Impact on UI | Impact on caller execution
----------|--------------|-----------------------------
Modal     | Blocked      | Blocked until Form is closed
Modeless  | Not blocked  | Continues

あなたはUIをブロックし、呼び出し側が継続できるようにしたい場合は、あなたがApplication.OnTimeとモーダルモードでフォームを開く必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top