マクロを作るとき、その動作をイメージします。そのとき、無意識のうちに、人が手動で操作するときの動作を考えて「これって、すごく時間がかかるのでは」と誤解することが多いです。もちろん、人が手動でやれば膨大な時間を要する作業でも、VBAでやれば一瞬ということもあります。たとえば、ワークシートの中から、特定のセルを探し出すという動作は、手動で1セルずつ見ていったら大変です。でも、Excelの検索機能を使えば一瞬で終わります。今回は、先日のセミナー中に受講生から質問された話です。
膨大なワークシートから、特定のシートを探し出すにはどうしたらいいでしょう?
膨大なというのが、どれくらいか分かりませんが、ここでは1,000枚のワークシートから、任意のシートを探し出してみましょう。
この画像だけでは証拠になりませんが、シートが1,000枚あります。
質問された方は、セルの検索みたいな機能がないかと期待されたのだと思います。そんなものは、ありません。じゃ、どうするかといえば、簡単です。シートの名前を1枚ずつチェックしていけばいいんです。私がそう答えると「ええ?1,000枚もチェックしたら、さぞ時間がかかるのでは」と言いたげな表情をされていました。じゃ、やってみましょう。
Sub Sample1() Dim i As Long For i = 1 To Sheets.Count If Sheets(i).Name = "Sheet1000" Then Sheets(i).Range("A1") = Now End If Next i End Sub
パソコンの性能にもよりますが、こんなもんです。表示されている数値は、GetTickCountを使って計測した、ミリ秒単位の所要時間です。ああ、ちなみに、上記のコードで見つかる"Sheet1000"は、右端にある1,000枚目のシートです。
「VBA高速化テクニック」にも書きましたが、繰り返しの命令は、For NextよりもFor Eachの方が、ほんの少し速いです。これ、For Eachでやってみましょう。
Sub Sample2() Dim ws As Worksheet For Each ws In Sheets If ws.Name = "Sheet1000" Then ws.Range("A1") = Now End If Next ws End Sub
あるいは、ただ存在の確認をしたいだけでしたら、1枚ずつチェックしないでも、エラーを利用する方法もあります。たとえば、もし[Sheet1000]というシートが存在していたら、Sheets("Sheet1000").Nameを取得できます。もし存在していなかったら、Sheets("Sheet1000").Nameを取得しようとするとエラーになります。だから、試してに取得してみて、エラーになるかどうかで判定すればいいんです。
Sub Sample3() Dim A As String On Error Resume Next A = Sheets("Sheet1000").Name If Err.Number > 0 Then MsgBox "存在しません" Else MsgBox "存在します" End If End Sub
これも所要時間を計測したのですが、何回やっても0秒でした。