8

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

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

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

リソースを大量に使用する呼び出し手順によって、モードレス ユーザー フォームCommandButton_Clickでイベントが発生することもあります。UserForm_Activate

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

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

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

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

ありがとう!

4

5 に答える 5

1

これを締めくくり、モーダルが勝者だと言います。私は両方の方法を試しましたが、モードレスユーザーフォームであまりにも多くの抜け穴を閉じようとすることになります。モーダルはより厳密であるためより困難ですが、コードをより小さなチャンクに分割することをお勧めします。これはとにかく長期的には優れています。

于 2010-02-02T16:53:57.197 に答える
1

恐るべしモーダル。モードレスを検討する場合は、Excel.exe メイン スレッドではなく、別のアウトプロセス スレッドで実行する必要があります。

于 2010-11-29T00:24:28.157 に答える
1

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

セクション 1 - 理論

最初に言うことは、モジュール間で変数を転送することはまったく難しくないということです。

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

2 つ目は、ウィンドウが MODELESS であることです。どうして?答えは、コードの可動性を維持することです

  1. 最も定型的なプロセスが実行される関数は、UserForm モジュールには配置されません。
  2. どこからでもプログレスバーでウィンドウを呼び出すことができ、
  3. ルーチン関数/手順間の唯一の接続はグローバル変数です

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

セクション 2 - 実践

1)グローバル変数を使用してモジュール「宣言」を作成します。

Public StopForce As Integer 'この変数は、ユーザーがキャンセル ボタンを押したことを示すインジケーターとして使用されます

Public PCTDone As Single ' これは、既に完了した作業の割合です

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

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

 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
于 2013-08-08T15:31:21.017 に答える