何か、すごく時間のかかるループを実行すると、処理が終わるまでCPUの使用率が100%近くになることがあります。
Sub Sample1() Dim buf As String Const LogFile As String = "C:\log\ex090310.log" Open LogFile For Input As #1 Do Until EOF(1) Line Input #1, buf Debug.Print buf Loop Close #1 End Sub
上記の"C:\log\ex090310.log"は、サーバーのログファイルです。テキストファイルで約45MB、約20万行あります。さすがに、このボリュームになると、Line Inputで1行ずつ読むのには時間がかかります。そして、処理が終わるまで、CPUの使用率はずっと100%となります。
マクロが終わるまで、コーヒーでも飲んでいられればいいのですが、その間に別の仕事をしたいときには困ります。VBAがCPUを独占しているので、エディタで原稿を書こうとしても、いつものような快適さは望めません。
VBAのDoEvents関数を使ってはどうでしょう。DoEvents関数は、ヘルプによると「プログラムで占有していた制御をオペレーティング システムに渡すフロー制御関数」だそうです。確かに、こうした長い時間がかかるマクロを、ユーザーが途中で停止できるような仕組みでは必須ですが、CPUの使用率を抑える効果は期待できません。
Sub Sample1() Dim buf As String Const LogFile As String = "C:\log\ex090310.log" Open LogFile For Input As #1 Do Until EOF(1) Line Input #1, buf Debug.Print buf DoEvents Loop Close #1 End Sub
こんなときは、Windows APIのSleepを使うと、CPUの使用率を抑えられます。
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Sub Sample1() Dim buf As String Const LogFile As String = "C:\log\ex090310.log" Open LogFile For Input As #1 Do Until EOF(1) Line Input #1, buf Debug.Print buf Sleep 1 Loop Close #1 End Sub
Sleepは、指定した時間だけ処理を停止する命令です。引数はミリ秒単位ですから「Sleep 1000」で1秒停止します。上記のように指定した「Sleep 1」は、0.001秒になります。
0.001秒とはいえ、Sleepは処理を停止するのですから、マクロの実行速度はそれだけ遅くなります。上記のマクロなら、単純計算で「0.001秒×20万回=200秒」だけ余計に時間がかかります。しかし、マクロは速度を追求するだけではありません。このマクロがバックグラウンドで実行している間に、別の仕事をできるのですから、仕事全体を考えれば効率的と言えるでしょう。