- ベストアンサー
エクセルVBAでユーザーフォームBがリアルタイムに更新されない問題の解決方法
- エクセルVBAでユーザーフォームAとBがありますが、フォームBがリアルタイムに更新されない問題が発生しています。
- フォームBに変数を渡そうとしたり、ラベルやテキストボックス、リストボックスを使用しようとしたりしても、真っ白なまま更新されず、原因が分かりません。
- 解決方法を教えてください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
簡単な例を書くと Private Sub CommandButton1_Click() Dim i As Long With UserForm2 For i = 1 To 5 Application.Wait Now + TimeValue("00:00:01") .Label1.Caption = i .Repaint Next End With End Sub こんな感じで UserForm2.Repaint による再描画が必要ではないでしょうか。
その他の回答 (1)
- nda23
- ベストアンサー率54% (777/1415)
Windowsのアーキテクチャを理解すると、そういう 現象になるのは当然であることが分かります。 Windowsではウィンドウに何かしらの変化が発生 するとメッセージを発生させ、ウィンドウに送り ます。例えば、「上に乗っていたウィンドウが消え たから、その部分を描画し直せ」という具合です。 ウィンドウプロシージャはメッセージに応じた動作を 実施します。 「ボタンがクリックされた」というのも同じです。 そこから先はOnClickイベントプロシージャとして 利用者プログラムに制御が渡ります。 但し、メッセージは順繰りに処理されるので、前の メッセージの処理が終わるまで、次のメッセージは 送られません。 つまり、ボタンクリックから一連の動作を開始すると、 このスレッドでいくら画面の表示を変えたとしても、 「描画」メッセージは画面に送られず、キューに溜まる だけです。つまり、画面の表示に変化がありません。 ボタンクリックのスレッドがOSに制御を返すと、初めて 次のメッセージが送られ、再描画されます。従って、 最後の場面しか映りません。 実際のVBAでは微妙に違いますが、大体の流れはこの ようになっています。Cプログラムでは実行ボタンに よる処理は別スレッドを起動して処理し、メッセージの 処理は直ぐに制御をOSに戻すようにしています。 VBではマルチスレッドができないので、替わりに、 溜まったメッセージを先に処理させるステートメントを 使います。これがDoEventsステートメントです。 テキストボックスやラベルの内容を変更したら、この ステートメントを実行します。 但し、このステートメントはボタンのクリックなども 拾うので、OnClickイベントプロシージャの処理を 抜けないうちに、発生したスレッドにより、同プロ シージャが呼び出される可能性があります。また、 画面の表示を変えたことに伴って色々なイベントが 発生し、堂々巡りになったりする危険もあります。 こういった状態にならないよう制御します。 サンプル UserForm2.Label1.Caption = buf DoEvents 'ここでメッセージを処理させる