こんにちは。

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

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

このQ&Aに関連する最新のQ&A

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
    • 3
この回答へのお礼

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
    • 0
この回答へのお礼

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

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

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

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

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

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

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


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

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

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

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

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

表題の>DoEvents関数って何?


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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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



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

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

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

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

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

このQ&Aに関連する人気のQ&A

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

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q「Cell( n , "A" )よりも10上のセルに1 or 2 が記入されていなければ、Cell( n , "A" )に1を記入する」

「Cell( n , "A" )よりも10上のセルに1 or 2 が記入されていなければ、Cell( n , "A" )に1を記入する」
というコードを作ってみましたが、メチャクチャな動きになってしまいます(動きが読めません)。
どこが間違っているのか教えてください。
また、もし、よりわかりやすいコードがありましたら教えていただけると嬉しいです。
よろしくお願いいたします。

Sub Cell( n , "A" )に1を記入する()

Dim n As Long
Dim m As Long
Dim s As Long

'現在のセル( n , "A" )より14行上に数値がないことを確認するために
'14行上のセルを全て足し算しています。
For m = n - 14 To n - 1
s = s + Worksheets("Sheet1").Cells(m, "A").Value
Next

'足し算結果がゼロならば何も記入していないと判断し、
'数字の「1」を記入します。
If s >= 1 Then
Worksheets("Sheet1").Cells(n - 1, "A").Value = 0
ElseIf s = 0 Then
Worksheets("Sheet1").Cells(n - 1, "A").Value = 1
End If
End Sub

「Cell( n , "A" )よりも10上のセルに1 or 2 が記入されていなければ、Cell( n , "A" )に1を記入する」
というコードを作ってみましたが、メチャクチャな動きになってしまいます(動きが読めません)。
どこが間違っているのか教えてください。
また、もし、よりわかりやすいコードがありましたら教えていただけると嬉しいです。
よろしくお願いいたします。

Sub Cell( n , "A" )に1を記入する()

Dim n As Long
Dim m As Long
Dim s As Long

'現...続きを読む

Aベストアンサー

はいはい了解。

今着目しているセルが (n,1)であるとする。

条件: 今いるところから上に14行サーチして、一度でも1か2の値が見つかったら
     回答を0とする。14行すべてに1・2の値がひとつも含まれていなければ1とする。



Ans = 1

for i = 1 to 14

x = cells ( n - i , 1 ).value

if x = 1 or x = 2
then
Ans = 0
endif
next i


cells ( n , 1 ) = Ans


デフォルトの回答値=1としておき、一回でも条件にヒットしたら回答値=0にする。
ヒットしたらfor~nextを強制的に閉じてもいいけど、面倒なのでそのまま14回検索する。

QFor next使う場合、next iはできない?

vbsでFor next使う場合、next iはできないのですか?

for i = 1 to 2
msgbox ""
next i

をすると
"ステートメントの末尾が不正です"800A401
になります。

しかし
for i = 1 to 2
msgbox ""
next
にすると、問題ないです。

VBAではnext iでも実行できるけどVBSではだめなのでしょうか?
理由を教えてください。

Aベストアンサー

Excel2003(Office2003)は持ち合わせていないので、2002の場合なら・・
VBE上で
for i = 1 to 2
msgbox ""
next i
となっていたら、for の所にカーソルを持って行って、F1 キーを押せば
該当すると思われるものがピックアップされます。
あるいは、For まで打ち込んで、F1 とか
イミディエイトウィンドウ(Ctrl + G で出現)で、For まで打ち込んで、F1 とか
2002なら
---------------------
For キーワード
キーワード For は、次の構文で使用します。
For...Next ステートメント
For Each...Next ステートメント
Open ステートメント
-------------------------
となりますので、For Each...Next ステートメント をクリックすると
前回回答のがでます。
たしか、2002の場合はVBAのヘルプはインストール時のオプション扱いだった記憶・・
2003は分かりません。
蛇足ですがOffice2010のVBAのヘルプは今までで一番使いやすいです。
ところが2013では
『以前のバージョンの Office に付属していた開発者用リファレンス ヘルプ ファイルは、セットアップから削除され、
Microsoft Developer Network (MSDN) で参照できるようになります。』
だとさ (-"-)
http://technet.microsoft.com/ja-jp/library/cc178954%28v=office.15%29

VBSのヘルプは、ここから
http://www.microsoft.com/ja-jp/download/details.aspx?id=1406
scd56jp.exe をダウンロードして
実行するとインストール先を聞いてきます。OSがWinXPなら既定のフォルダは
C:\Program Files\Microsoft Windows Script\ScriptDocs
ですので、そこから script56.chm だけをお好きな所にコピーします。
他のものに用は無いので、コントロールパネルからアンインストールしてください。
または解凍ソフトをインストールして
http://win.just4fun.biz/WSH/WSH%E3%81%AE%E3%83%98%E3%83%AB%E3%83%97%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%85%A5%E6%89%8B%E6%96%B9%E6%B3%95.html
にて。

Excel2003(Office2003)は持ち合わせていないので、2002の場合なら・・
VBE上で
for i = 1 to 2
msgbox ""
next i
となっていたら、for の所にカーソルを持って行って、F1 キーを押せば
該当すると思われるものがピックアップされます。
あるいは、For まで打ち込んで、F1 とか
イミディエイトウィンドウ(Ctrl + G で出現)で、For まで打ち込んで、F1 とか
2002なら
---------------------
For キーワード
キーワード For は、次の構文で使用します。
For...Next ステートメント
For Each...Next ステートメント
...続きを読む

QIf myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou こちらについて教えていただきたいです。

myTorikomibi = Range("A2").Value
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, 4) = myTantou
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, 14) = myTantou
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou
For i = 1 To 3
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, i + 4) = myTorikomibi
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, i + 14) = myTorikomibi
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, i + 24) = myTorikomibi
Next i
マクロを編集しようとしましたところこちらが解読できづに困っています。
こちらだけとりだして実行しながら解読していますが混乱してしまっています。ご存知の方いらっしゃいましたら教えてください。Then以降がわかりません。よろしくお願いいたします。

myTorikomibi = Range("A2").Value
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, 4) = myTantou
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, 14) = myTantou
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou
For i = 1 To 3
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, i + 4) = myTorikomibi
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, i + 14) = myTorikomibi
If myCityBUNRUINO = 2 Then Cells...続きを読む

Aベストアンサー

こんにちは。maruru01です。

ヘルプはご覧になりましたか?
特に、Cellsについて。
Cellsは、

Cells(行番号, 列番号)

で、セルを参照します。
なので、各条件の時に、変数「myTantou」や「myTorikomibi」に格納されている値をそれらのセルに代入しているだけですが。
ただし、行番号が、

「myPrefNO + 3 - 47」
「myPrefNO + 3 - 47 - myCityNu」

などとちょっとややこしくなっていますが。
これも、変数「myPrefNO」「myCityNu」に入っている値から行番号が決まるというだけです。
例えば、
myPrefNO=60
myCityNu=2
なら、下の例は、
60+3-47-2=14
で、14行目となるということです。

QExcelマクロでRange("A1:A5,C1:C5")をCellsで書きたいのですが

マクロ初心者です。
Excelマクロでグラフを作成するときに、元データを指定する所で、
Source:=Range("A1:A5,C1:C5")とするような場合、
「A1」とかアルファベットでの番地指定ではなく、
Cellsを用いて書きたいのです。

Source:=Range("A1:A5")であれば、
Source:=Range(Cells(1, 1), Cells(5, 1))と書けばいいことは分かるのですが、範囲指定を複数にする場合が分からないのです。

よろしくお願いします。

Aベストアンサー

Unionを使用したらできると思います。

Source:=Union(Range(Cells(1, 1), Cells(5, 1)), Range(Cells(1, 3), Cells(5, 3)))

今Excelがインストールされてないパソコンで作業していないので確認はしていないのですが・・・。

よかったら参考にして下さい

QDataGridView(1,1).Valueの型について

VB2008を使っています。
DataGridView(1,1).Valueの型はそのセルのデータによって
TypeName( DataGridView(1,1).Value) は異なると思いますが、
DataGridView(1,1).Valueの型は何でしょうか?

Dim v As DataGridViewCell = DataGridView(1,1).Value
で良いのでしょうか?

Aベストアンサー

DataGridView(1,1).Valueの方はOcject型です。(そのカラムってTextBoxカラムだと思っての回答です)

なので、なにをしたいかはわからないのですが、
Dim v As DataGridViewCell = DataGridView(1,1).Value
ではNGです。


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

このカテゴリの人気Q&Aランキング

おすすめ情報