• ベストアンサー

DoEvents関数って何?

こんにちは。 VBAやプログラミングに詳しい皆様に 教えていただきたい質問があります。 cells(1,1)からcells(5000,1)までの値を消去するときに 処理の進行状況を表示するためにuserform上にプログレスバーを表示したいと思います。 そこで下記のようなコードを入力しました。 userform1.show for i =1 to 5000 cells(i,1)="" userform1.progressbar1.value=i/5000*100 next i unload userform1 しかしこれだとuserformの背景が真っ白になってしまい ラベルの文字も消えてしまいます。 そこで「EXCEL VBA パーフェクトマスター」という本を見たら for i =1 to 5000 cells(i,1)="" userform1.progressbar1.value=i/5000*100 DoEvents next i unload userform1 と入力すれば解決することがわかりました。 しかし「DoEvents」についてあまり詳しく書いていなかったのでDoEvents関数をヘルプで見ると、 「発生したイベントがオペレーティング システムによって処理されるように、プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数です。」 と書いてあるのですが正直、書いてあることがよくわかりません。 どなたかDoEvents関数について、 もう少しわかりやすく教えていただけませんか。 それから、最初に書いたコードで実行すると ユーザーフォームの背景が真っ白になってしまう原因も 教えていただけませんか? よろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

簡単に言うと、 OS に制御を渡すってことです。(ヘルプそのまんま) 時間が掛かるループ処理などの場合、ループが終わるまで制御は独占されてしまいます。 ですのでループ中は OS や Excel そのものにも再描画をさせる暇さえ与えません。 途中に DoEvents を入れると制御が OS に渡るので、OS は溜まっていた処理をそこで行うことができます。 結果、フォームの再描画などが行われることになります。 注意点ですが、 Private Sub CommandButton1_Click()   Dim i As Long   For i = 1 To 50000     DoEvents     Cells(i,1) = ""   Next i End Sub Private Sub CommandButton2_Click()   MsgBox "hoge" End Sub っていうフォームのコードがあった場合、 DoEvents を入れることによって、ループ中にユーザーがCommandButton2 を押すことによって CommandButton2 のクリック イベントも動いちゃいます。 CommandButton1 のクリック イベントではループの前に CommandButton1.Enabled = False CommandButton2.Enabled = False を書いてフォーム上の CommandButton を無効にしておき、ループが終わったら CommandButton1.Enabled = True CommandButton2.Enabled = True と書いて CommandButton を有効に戻してください。 これを工夫すれば、CommandButton2 で CommandButton1 のループを途中キャンセルする処理もすることができます。 Private Canceled As Boolean Private Sub CommandButton1_Click()   CommandButton2.Enabled = False   Dim i As Long   For i = 1 To 50000     DoEvents     If Canceled = True Then       MsgBox "キャンセルしました"       Exit Sub     End If     Cells(i, 1).Value = ""   Next i End Sub Private CommandButton2_Click()   Canceled = True End Sub コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。 コピペするなら行頭の全角スペースを半角スペースに直してください。

19746999
質問者

お礼

temtecomai2さん とても詳しい御回答どうもありがとうございました。 今回、『再描画』という意味を初めて知りました。 勉強になります! temtecomai2さんの書いていただいたコードをコピペしてみて 試してみました! おかげ様でDoEventsの効果がよくわかりました。 それとDoEventsを入れるのと入れないのでは処理速度も違うんですね。 下の例ではDoEventsを入れた方は78秒、入れなかったほうは25秒でした。 これって制御をOSに渡す時間が下のコードの例では53秒(78-25)も掛かるって事なんでしょうか?

その他の回答 (7)

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.8

No.7 の件について このカテゴリーがVisual Basicの為、うっかりVBでプログラム を作ってしまっていました。 手もとにあるExcel97とExcel2000とで作成してみましたが、 テキストボックスにGotFocusプロパティ自体無く、且つ実行 してもエラーも発生しませんでした。 (Win98SE 及びWin2000) どうも 19746999 さんが使用しているExcel とはバージョン又 は実行環境が異なる為、動作が異なっている事が考えられ ます。

19746999
質問者

お礼

don_goさん こんにちは ・・しまった。。 「EXCELのVBAに関する質問」 って最初に書くの忘れていました。 ごめんなさい。これからは気をつけます・・・。 そうですね! 僕が使っているのはEXCEL2002で VBAのバージョンは Microsoft Visual Basic 6.0です。 結局違いがわからないままですが、 過去に書いていただいた方の アドバイスを参考にして 理解していこうと思います。 それではあと1,2日で質問を締め切ろうと思います。 ポイントあげる人迷うなぁ・・・

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.7

間違いの例としては、あまり良いのが浮かばなかったので申し訳ありませんが... DoEvents の有無により動作の違う例を Private Sub Text1_GotFocus() MsgBox "GotFocus" End Sub Private Sub Command1_Click() Text1.Text = 1 Text1.SetFocus DoEvents MsgBox "hoge" End Sub

19746999
質問者

お礼

don_goさん こんにちは 具体的なご回答ありがとうございます。 ・・大変申し訳ないのですが ユーザーフォームを作って コマンドボタンとテキストボックスを そのユーザーフォームの上に作って (もちろんオブジェクト名は統一させました。) 教えていただいたイベントプロシージャを コピペして試してみたのですが、 よくわかりません。 と言うより「Gotfocus」イベントが働きません。 なのでDoeventsの有無にかかわらず動きが同じに感じます。 試しにシート上にテキストボックスを作って 教えていただいたコードを入力して (もちろんオブジェクト名は統一させた。) Gotfocusイベントが働くか確認するために そのテキストボックスをクリックすると、 ちゃんとGotfocusイベントが動くのですが、 コマンドボタンをクリックしてマクロを実行すると setfocusメソッドでのところで下記のエラーが出てしまいます。        ↓ オブジェクトは、このプロパティまたはメソッドをサポートしていません。(Error 438) いろいろ考えたのですが どこが間違っているのかわかりませんでした。 わかりにくい質問だと思いますが 何が間違っているのか教えていただけませんか? 何度も質問してしまって申し訳ございませんが よろしくお願いします。

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.6

DoEventsは、MS-WindowsがUNIXやLinux等のマルチタスクOSではなく、 疑似マルチタスクで有るため必要になるものです。 通常マルチタスクOSでは、同時に実行される各種のプログラムに対して 処理に必要な時間と順序をOSが配分して実行しますが、MS-Windows ではプログラムから処理が戻ってから(今回ではプロシージャが終了して から)、次のプログラムやキー入力、マウス入力イベント等を実行します。 従って、時間のかかる処理や無限ループなどがあると、他の処理が実行 できなくなり、極端に全体の反応が遅くなったり、動かなくなったりします。 #画面が白くなるのは、表示の更新が行われなくなるためです。 そうなる事を防ぐ為、DoEventsを実行して、他のプログラムやイベント 処理を実行させる必要があります。 但し、Form上のコントロールに対して値をセットした後、DoEventsを実行 した場合、ChangeやGetFocusイベントが実行され、思っていなかった動作 をする事があるので、使用する場所には十分注意する必要があります。

19746999
質問者

お礼

don_goさん ご回答ありがとうございます。 たくさんのわかりやすいご回答を頂いてきましたが 更に重要な回答を投稿していただいてうれしいです。 それから、もしよろしければ >但し、Form上のコントロールに対して値をセットした後、DoEventsを実行 した場合、ChangeやGetFocusイベントが実行され、思っていなかった動作 をする事があるので、使用する場所には十分注意する必要があります。 ごめんなさい・・・この部分もう少し詳しく教えていただけないでしょうか。 面倒くさかったら無視してください^-^

  • colhan
  • ベストアンサー率31% (201/631)
回答No.5

題意と違うかも知れませんが。 For ~ Next文は、とっても強力で、 中の処理が終了するまで、他のWindowsの処理にすら移りません。 この中に重い処理を入れると、再描画が掛からなくなり、ユーザーフォームが真っ白になったりします。

19746999
質問者

お礼

colhanさん ご回答ありがとうございました。 >題意と違うかも知れませんが。 とんでもない・・・ とても参考になりましたよ^-^ もうこれ以上良い回答は頂けないかと思ってましたが 待ってみるもんですね♪

  • imogasi
  • ベストアンサー率27% (4737/17069)
回答No.4

表題の>DoEvents関数って何? について、DoEventsは関数に分類されず、「ステートメント」に分類されています。 VBAの解説書などでは、 オブジェクト プロパティ メソッド ステートメント 関数 に分類されています。念のため。 意味はWEBで照会してください。 ーー DoEventsもOKWAVEで質問して、聞くのも良いが、WEB照会したら、働きの説明も、実例も多数出てきますよ。

19746999
質問者

お礼

imogasiさん ご回答ありがとうございました >DoEventsもOKWAVEで質問して、聞くのも良いが、WEB照会したら、働きの説明も、実例も多数出てきますよ。 ・・・本当だいっぱい出てきた。 教えていただいてありがとうございます。。。

回答No.3

Windowsはイベント-なにかが起きることー (しかし、それは予期せぬものではなく約束されたもの) が発生することにより動作します。 たとえばキーが押されたとか、時間が来たとか。 CPUは1っこしかないのでタイムシェアーでいろいろな プログラムがイベントを発生させて動いています。 しかし、あなた(ユーザー)がそのことを考えずにプログラミング すると、他のプログラムは自分の番が来ないので動けなくなり、 画面が真っ白になったままになったりするわけです。 最初のコードはCPUを占領します。(そうなっちゃう) 2番目のコードはDoEvents のところで一回処理を止め、 (windows に渡し)次に自分の番がきたときに、 次のステップを続けます。 当然処理速度は桁違いに遅くなります。

19746999
質問者

お礼

otto0001ottoさん わかりやすいご回答ありがとうございました。 VBAもまだまだ未熟者ですが パソコン全体の事はもっとド素人です。 もっとパソコンについてオールラウンドな 知識を身につけることが大切だと思いました。 これからも日々勉強を怠らずに頑張ります♪ また何かわからないことがあったら よろしくお願いします。

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.1

For文を使う必要があるのでしょうか? Range("A1:A5000).ClearContents 一瞬で終わるはずですよ。

19746999
質問者

お礼

hana-hana3さん おはようございます。 ご回答ありがとうございます。 そうか!clearContentsメソッドの存在をすっかり忘れてました。 質問以外のことも教えていただいてどうもありがとうございます。 これからもよろしくお願いいたします。

関連するQ&A