• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:EXCELマクロの処理速度)

EXCELマクロの処理速度

このQ&Aのポイント
  • EXCELマクロでシートAから条件に合致する値を検索してシートBに自動入力する際、シートBを表示した状態と隠した状態で処理速度に差がある。
  • シートBを表示した方が処理速度が速いため、理論的な説明があるなら表示させて処理速度を向上させたい。
  • EXCELマクロにおいて、シートBの表示状態がマクロの処理速度に影響を与えることがあるのか疑問がある。

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

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

>今回のコードだけでこういう現象が起こるというなら問題があります。 おそらく処理内容の問題かと思います。 実際のデータが無いので何とも言えませんが、提示されたコードには無用な部分も見られる感じですから、もう少し整理が可能かと思います。 下記のコードでは、シートの表示・非表示では最大で0.02秒の差しかありませんでした。 test1とtest2の実行時間の差は約1秒。 --------------------------------------------------------------- シートAのA列の10000行までに適当な数字が入っています。 シートBのA列には、シートAのA列の値(隅奇)に応じて、0か1を入れます。 Sub test1() Dim tmp As Integer, i As Integer Dim work As Variant work = Timer For i = 1 To 10000 tmp = Worksheets("シートA").Cells(i, 1).Value If tmp Mod 2 = 1 Then Worksheets("シートB").Cells(i, 1).Value = 1 Else Worksheets("シートB").Cells(i, 1).Value = 0 End If Next Debug.Print Timer - work End Sub Sub test2() Dim tmp As Integer, i As Integer Dim work As Variant work = Timer For i = 1 To 10000 tmp = Worksheets("シートA").Range("A" & i).Value If tmp Mod 2 = 1 Then Worksheets("シートB").Range("A" & i).Value = 1 Else Worksheets("シートB").Range("A" & i).Value = 0 End If Next Debug.Print Timer - work End Sub >シートの表示、非表示による処理時間の差が納得がいかないです。 テストしたコードだけでは明確な理由を見つけ出す事は出来なかったので何とも言えませんが、余分なシートや表示を排除してシート間計算(集計?)だけにして試してみる必用があるかと思います。 >処理後のデータを別シートでグラフにしているため、生データを見る必要がないからです。 「ScreenUpdating」では描画を抑止するので、グラフの書き換えも止まるためかも知れませんね。 マクロ実行中でもイベントが発生して居ます。 セルの値が書き変わるとエクセルは自動的に再計算を行いますから、グラフも再描画される事になります。 Application.EnableEvents = False (実行終了時は必ず True に戻す事) で、イベントをキャンセルするとさらに高速化するかも知れません。

center69
質問者

お礼

回答、ありがとうございます。 お礼が遅くなり申し訳ありませんでした。 提示頂いたコードを参考に変更を加えたところ、シートの表示、非表示にかかわらず、処理の高速化に成功しました。 for nextのところを変数iのカウントアップから変数RowNumLongNowのカウントダウンに変更しました。 お恥ずかしい話なのですが、for nextでカウントダウンができるということを知らなくて、以前のようにわざわざ2変数を用いてカウントダウンを実現していました。 旧コードでのシート表示、非表示による処理時間の差の件はたぶん、イベント発生によるものだと思われます。 hana-hana3様が仰るようにApplication.EnableEvents = Falseを設定すると処理速度の差がなくなりました。 シートA、B以外のシートが多すぎるので、どのシートが悪さをしているかを見極めるのは難しいので、おまじない的にApplication.EnableEvents = Falseを設定するようにします。 ようやくすっきりしました。 ありがとうございました。

その他の回答 (2)

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

実際のコードの提示が無いので何とも言えませんが・・・。 最速はシートに関数を記入して行う方法です。 その次は、VBAでワークシート関数を使う方法になります。 VBA高速化テクニック(目次) http://officetanaka.net/excel/vba/speed/index.htm

center69
質問者

補足

回答ありがとうございます。 「VBA高速化テクニック」非常に参考になりました。 さて、実際のコードは以下の通りです。 Sub DataA_to_DataB() myDataSheetNameA = "シートA" myDataSheetNameB = "シートB" RowNumANow = 1126 RowNumB = 1126 For i = 1 To 1090 RowNumAPre = RowNumANow - 1 CellNameDataANow = "AO" & RowNumANow CellNameDataAPre = "AO" & RowNumAPre DataAnow = Worksheets(myDataSheetNameA).Range(CellNameDataANow).Value DataApre = Worksheets(myDataSheetNameA).Range(CellNameDataAPre).Value CellNameDateANow = "B" & RowNumANow CellNameDateB = "B" & RowNumB CellNameTime = "G" & RowNumB myDateANow = Worksheets(myDataSheetNameA).Range(CellNameDateANow).Value myDateB = Worksheets(myDataSheetNameB).Range(CellNameDateB).Value myTime = Worksheets(myDataSheetNameB).Range(CellNameTime).Value myTime = Hour(myTime) Do Until myDateB <= myDateANow And myTime < 8 CellNameBtoA = "CC" & RowNumB If DataAnow <= DataApre Then Worksheets(myDataSheetNameB).Range(CellNameBtoA).Value = 0 Else Worksheets(myDataSheetNameB).Range(CellNameBtoA).Value = 1 End If RowNumB = RowNumB - 1 CellNameDateB = "B" & RowNumB CellNameTime = "G" & RowNumB myDateB = Worksheets(myDataSheetNameB).Range(CellNameDateB).Value myTime = Worksheets(myDataSheetNameB).Range(CellNameTime).Value myTime = Hour(myTime) If RowNumB < 36 Then Exit For End If Loop RowNumANow = RowNumANow - 1 Next End Sub 普段、シートA、BはプロパティでVisible = FALSEにしています。処理後のデータを別シートでグラフにしているため、生データを見る必要がないからです。 このコードをシートA、Bを表示した場合(Visible = TRUE)と、非表示の場合で処理時間を計測したところ、表示した場合の方が約10分の1の時間で処理が終わりました。 非表示の場合でも、Application.ScreenUpdating = FALSEをつけると同じく10分の1の時間で処理が終了します。 処理時間だけを問題にするならApplication.ScreenUpdating = FALSEをつけて問題解決となるのですが、シートの表示、非表示による処理時間の差が納得がいかないです。 さらなる高速化を目指すなら、Application.ScreenUpdating = FALSEに、さらにシートを表示させればいいと言うことになりますが、今回のコードだけでこういう現象が起こるというなら問題があります。 よろしくお願いします。

  • extrabold
  • ベストアンサー率30% (7/23)
回答No.1

逆なら経験がありますが、表示させたほうが速いというのはあまり聞きません。 画面更新系は遅い部類の処理になるので、基本的には非表示で実行させるのが高速化と言われているものです。 ただ、非表示にするのを、プロパティのVisibleをFalseにする、という方法は取ったことがありません。 マクロ実行中は、ScreenUpdating=Falseを設定し、実行終了時にTrueに戻す方法が普通だと思われます。 回答としてはずれてしまいますが、データの取得・書き出しも複数方法があり、速度も違いますので余裕があれば調べられてはいかがでしょうか。

center69
質問者

補足

回答ありがとうございます。 ScreenUpdating=Falseによって処理時間が短縮されることを確認できました。 しかし、Visible=FALSE、TRUEによる処理時間の差に関しては疑問が解決しておりません。 ANo.2のhana-hana3様への補足に実際のコードを示させてもらいました。 何かお気づきの点がありましたら、よろしくお願いします。

関連するQ&A