プロが教える店舗&オフィスのセキュリティ対策術

こんにちは。

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関数について、
もう少しわかりやすく教えていただけませんか。
それから、最初に書いたコードで実行すると
ユーザーフォームの背景が真っ白になってしまう原因も
教えていただけませんか?

よろしくお願いいたします。

A 回答 (8件)

簡単に言うと、


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



コードの行頭にあるスペースは見易さのために全角スペースで作成していますので、これをこのままコピペするとエラーになるかもしれません。
コピペするなら行頭の全角スペースを半角スペースに直してください。
    • good
    • 6
この回答へのお礼

temtecomai2さん
とても詳しい御回答どうもありがとうございました。
今回、『再描画』という意味を初めて知りました。
勉強になります!

temtecomai2さんの書いていただいたコードをコピペしてみて
試してみました!
おかげ様でDoEventsの効果がよくわかりました。

それとDoEventsを入れるのと入れないのでは処理速度も違うんですね。
下の例ではDoEventsを入れた方は78秒、入れなかったほうは25秒でした。
これって制御をOSに渡す時間が下のコードの例では53秒(78-25)も掛かるって事なんでしょうか?

お礼日時:2006/03/06 22:00

No.7 の件について


このカテゴリーがVisual Basicの為、うっかりVBでプログラム
を作ってしまっていました。
手もとにあるExcel97とExcel2000とで作成してみましたが、
テキストボックスにGotFocusプロパティ自体無く、且つ実行
してもエラーも発生しませんでした。
(Win98SE 及びWin2000)

どうも 19746999 さんが使用しているExcel とはバージョン又
は実行環境が異なる為、動作が異なっている事が考えられ
ます。
    • good
    • 0
この回答へのお礼

don_goさん
こんにちは

・・しまった。。
「EXCELのVBAに関する質問」
って最初に書くの忘れていました。
ごめんなさい。これからは気をつけます・・・。

そうですね!
僕が使っているのはEXCEL2002で
VBAのバージョンは
Microsoft Visual Basic 6.0です。

結局違いがわからないままですが、
過去に書いていただいた方の
アドバイスを参考にして
理解していこうと思います。

それではあと1,2日で質問を締め切ろうと思います。
ポイントあげる人迷うなぁ・・・

お礼日時:2006/03/13 20:26

間違いの例としては、あまり良いのが浮かばなかったので申し訳ありませんが...


DoEvents の有無により動作の違う例を

Private Sub Text1_GotFocus()
MsgBox "GotFocus"
End Sub

Private Sub Command1_Click()
Text1.Text = 1
Text1.SetFocus
DoEvents

MsgBox "hoge"
End Sub
    • good
    • 1
この回答へのお礼

don_goさん
こんにちは
具体的なご回答ありがとうございます。

・・大変申し訳ないのですが
ユーザーフォームを作って
コマンドボタンとテキストボックスを
そのユーザーフォームの上に作って
(もちろんオブジェクト名は統一させました。)
教えていただいたイベントプロシージャを
コピペして試してみたのですが、
よくわかりません。

と言うより「Gotfocus」イベントが働きません。
なのでDoeventsの有無にかかわらず動きが同じに感じます。

試しにシート上にテキストボックスを作って
教えていただいたコードを入力して
(もちろんオブジェクト名は統一させた。)
Gotfocusイベントが働くか確認するために
そのテキストボックスをクリックすると、
ちゃんとGotfocusイベントが動くのですが、

コマンドボタンをクリックしてマクロを実行すると
setfocusメソッドでのところで下記のエラーが出てしまいます。
       ↓
オブジェクトは、このプロパティまたはメソッドをサポートしていません。(Error 438)

いろいろ考えたのですが
どこが間違っているのかわかりませんでした。

わかりにくい質問だと思いますが
何が間違っているのか教えていただけませんか?
何度も質問してしまって申し訳ございませんが
よろしくお願いします。

お礼日時:2006/03/12 11:22

DoEventsは、MS-WindowsがUNIXやLinux等のマルチタスクOSではなく、


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

但し、Form上のコントロールに対して値をセットした後、DoEventsを実行
した場合、ChangeやGetFocusイベントが実行され、思っていなかった動作
をする事があるので、使用する場所には十分注意する必要があります。
    • good
    • 1
この回答へのお礼

don_goさん
ご回答ありがとうございます。
たくさんのわかりやすいご回答を頂いてきましたが
更に重要な回答を投稿していただいてうれしいです。

それから、もしよろしければ

>但し、Form上のコントロールに対して値をセットした後、DoEventsを実行
した場合、ChangeやGetFocusイベントが実行され、思っていなかった動作
をする事があるので、使用する場所には十分注意する必要があります。

ごめんなさい・・・この部分もう少し詳しく教えていただけないでしょうか。

面倒くさかったら無視してください^-^

お礼日時:2006/03/09 08:19

題意と違うかも知れませんが。


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

colhanさん
ご回答ありがとうございました。

>題意と違うかも知れませんが。
とんでもない・・・
とても参考になりましたよ^-^

もうこれ以上良い回答は頂けないかと思ってましたが
待ってみるもんですね♪

お礼日時:2006/03/06 22:27

表題の>DoEvents関数って何?


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

imogasiさん
ご回答ありがとうございました

>DoEventsもOKWAVEで質問して、聞くのも良いが、WEB照会したら、働きの説明も、実例も多数出てきますよ。

・・・本当だいっぱい出てきた。

教えていただいてありがとうございます。。。

お礼日時:2006/03/06 22:20

Windowsはイベント-なにかが起きることー


(しかし、それは予期せぬものではなく約束されたもの)
が発生することにより動作します。
たとえばキーが押されたとか、時間が来たとか。

CPUは1っこしかないのでタイムシェアーでいろいろな
プログラムがイベントを発生させて動いています。

しかし、あなた(ユーザー)がそのことを考えずにプログラミング
すると、他のプログラムは自分の番が来ないので動けなくなり、
画面が真っ白になったままになったりするわけです。

最初のコードはCPUを占領します。(そうなっちゃう)
2番目のコードはDoEvents のところで一回処理を止め、
(windows に渡し)次に自分の番がきたときに、
次のステップを続けます。
当然処理速度は桁違いに遅くなります。
    • good
    • 2
この回答へのお礼

otto0001ottoさん
わかりやすいご回答ありがとうございました。

VBAもまだまだ未熟者ですが
パソコン全体の事はもっとド素人です。
もっとパソコンについてオールラウンドな
知識を身につけることが大切だと思いました。
これからも日々勉強を怠らずに頑張ります♪

また何かわからないことがあったら
よろしくお願いします。

お礼日時:2006/03/06 22:12

For文を使う必要があるのでしょうか?



Range("A1:A5000).ClearContents
一瞬で終わるはずですよ。
    • good
    • 1
この回答へのお礼

hana-hana3さん
おはようございます。

ご回答ありがとうございます。
そうか!clearContentsメソッドの存在をすっかり忘れてました。

質問以外のことも教えていただいてどうもありがとうございます。
これからもよろしくお願いいたします。

お礼日時:2006/03/06 07:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A