機能と数式 | VBA | セミナー | オンラインソフト | お問い合わせ | その他
Top > Excel > VBA > VBA高速化テクニック

無駄なSelectをしない



セル範囲A1:A5の各セルへ、順に数字を入力する操作をマクロ記録すると、次のようなコードが生成されます。

Sub Macro1()
    Range("A1").Select
    ActiveCell.FormulaR1C1 = "1"
    Range("A2").Select
    ActiveCell.FormulaR1C1 = "2"
    Range("A3").Select
    ActiveCell.FormulaR1C1 = "3"
    Range("A4").Select
    ActiveCell.FormulaR1C1 = "4"
    Range("A5").Select
    ActiveCell.FormulaR1C1 = "5"
    Range("A6").Select
End Sub

それぞれのセルを選択(Select)し、そのアクティブセルに対して数値を入力したのですから、このコードは間違いではありません。ただし、決して効率の良いコードとは言えません。

マクロ記録は、操作を1ステップずつコード化します。つまり「セルA1に1と入力する」操作は、まず「セルA1が選択された」「選択されたセルに1が入力された」さらにEnterキーを押すと「アクティブセルが1つ下に下がった」というように記録されるのです。このようなコードは速度的に不利なだけでなく、メンテナンス性も大きく損なわれます。

今回検証するのは、次のコードです。

Sub Test1()
    Dim i As Long
    Application.ScreenUpdating = False
    For i = 1 To 5000
        Cells(i, 1).Select
        Selection = i
    Next i
    Application.ScreenUpdating = True
End Sub

Sub Test2()
    Dim i As Long
    For i = 1 To 5000
        Cells(i, 1) = i
    Next i
End Sub

Test1は、前ページ「無駄な表示を止める」で使った"速い方"のコードです。ScreenUpdatingプロパティで画面の描画を抑止した結果、何もしないコードよりも高速になりました。しかし、そもそも

○○.Select
Selection.××

という記述が冗長なのです。今回のTest2は、Selectしていません。VBAは、これでいいんです。ScreenUpdatingプロパティにFalseを設定して画面描画を抑止するまでもありません。結果は次の通りです。

Test1 Test2 %
1回目  0.34 秒  0.15 秒  43.9% 
2回目  0.34 秒  0.15 秒  44.5% 
3回目  0.34 秒  0.15 秒  43.9% 
4回目  0.33 秒  0.15 秒  45.4% 
5回目  0.34 秒  0.15 秒  44.0% 
6回目  0.33 秒  0.15 秒  45.2% 
7回目  0.34 秒  0.16 秒  45.5% 
8回目  0.34 秒  0.16 秒  46.2% 
9回目  0.34 秒  0.16 秒  45.5% 
10回目  0.34 秒  0.16 秒  45.4% 
平均  0.34 秒  0.15 秒  45.0% 

分からないことがあったらマクロ記録する。それはいいんです。マクロ記録はそのためにある「調べる機能」だからです。しかし、記録されるコードは、決して最適化されていません。はっきり言えば「ものすごく冗長なコード」です。そりゃそうです。操作を1手順ずつ確実に記録するのですから。少しでもマクロのクオリティを気にするのなら、マクロ記録で記録されたコードを、そのまま使わないで、無駄な部分を削り、自分の望むコードに編集する作業が必要です。

  • マクロ記録する
  • コードが記録される
  • そのコードをそのまま使う

ではなく、

  • マクロ記録する
  • コードが記録される
  • 記録されたコードをよく読む
  • 分からないところはヘルプで調べる
  • 必要な部分だけ自分のマクロに組み込む

です。

言うまでもありませんが、記録されたコードが読めないと話になりません。そのために必要なことは、ただひとつ。VBAの基礎を正しく学習することです。"習うより慣れろ"でマスターできるほど、VBAは簡単ではありません。他の言語に精通しているからといって、使いこなせるほどVBAは単純ではありません。インターネットを検索して、コピペでマクロを完成させても、VBAのスキルが向上したわけではありません。翻訳サイトで日本語を英語に翻訳しても、英語を話せるようにならないのと同じことです。

たとえば、Sheet1のセルA1を、Sheet2のセルB2にコピーする操作を考えてみましょう。マクロ記録すると、次のようなコードが記録されます。

Sub Macro1()
    Range("A1").Select
    Selection.Copy
    Sheets("Sheet2").Select
    Range("B2").Select
    ActiveSheet.Paste
End Sub

まず、

○○.Select
Selection.××

を消します。VBAは、ほとんどの場合、こうした記述は

○○.××

と、SelectとSelectionを消せます。単純にSelectとSelectionを消せないのは、グラフやオートシェイプなどの操作をマクロ記録した場合です。ブック・ワークシート・セルを操作しているだけなら、一般的にはすべて消せると考えていいです。

Sub Macro1()
    Range("A1").Copy
    Sheets("Sheet2").Select
    Range("B2").Select
    ActiveSheet.Paste
End Sub

次に、セルをコピーする命令が"Copy"と分かったら、これをヘルプで調べます。すると、次のように書いてあります。



Copyは、引数Destinationにコピー先(貼り付け先)を指定できるとなっています。この引数を省略するとクリップボードにコピーされます。マクロ記録で記録されたコードは、引数を省略しています。だから、クリップボードにコピーされたのです。そりゃそうです。セルA1をコピーした時点では、まだ貼り付け先が特定されていないのですから、こう記録するしかありません。クリップボードにコピーしたデータを貼り付けたので、そのための命令Pasteが記録されたんです。

このように、VBAをマスターしようと思うなら、ヘルプは必ず読まなければなりません。とはいえ、ヘルプに書いてあることは分かりにくいですよね。それはヘルプが、VBAの初級者から上級者までを対象に書いてあるからです。決して初級者のための"始めてみようガイド"ではありません。ヘルプに書かれていることを、すべて正確に理解できるのは上級者だけでしょう。だから、ヘルプを読むときのコツは、

分からないところは、読み飛ばす。見なかったことにする。

です。上図ヘルプの

データ型:バリアント型(Variant)
とか
戻り値:バリアント型(Variant)

って、何のことだか分かりませんよね。分からなかったら、見なかったことにすればいいんです。で、意味の分かるところだけ拾い読みします。それを繰り返していると、だんだんと意味の分かるところが増えてきます。それがVBAのスキルアップです。

さらにCopyのヘルプには、次のように使用例も載っています。



このサンプルをコピーして、実際に実行してみます。すると、確かにセルが別シートにコピーされるのが分かります。したがって、さっきの記録されたコードは、次のようにわずか1行で済むんです。

Sub Macro1()
    Range("A1").Copy Sheets("Sheet2").Range("B2")
End Sub

なお、ここでは引き数名の「Destination:=」を省略しました。なぜ省略できるかは、当サイト「今さら聞けないVBA」の、下記ページで詳しく解説していますので、ぜひご覧ください。


さて、せっかくですから、速度も検証してみましょうか。まぁ、やるまでもありませんが(笑)

Sub Test1()
    Dim i As Long
    For i = 1 To 100
        Sheets("Sheet1").Select
        Range("A1").Select
        Selection.Copy
        Sheets("Sheet2").Select
        Range("B2").Select
        ActiveSheet.Paste
    Next i
End Sub

Sub Test2()
    Dim i As Long
    For i = 1 To 100
        Sheets("Sheet1").Range("A1").Copy Sheets("Sheet2").Range("B2")
    Next i
End Sub

Test1 Test2 %
1回目  3.94 秒  1.06 秒  26.9% 
2回目  3.92 秒  1.06 秒  26.9% 
3回目  3.94 秒  1.06 秒  26.9% 
4回目  3.91 秒  1.07 秒  27.3% 
5回目  4.08 秒  1.05 秒  25.6% 
6回目  3.89 秒  1.06 秒  27.2% 
7回目  3.91 秒  1.05 秒  26.9% 
8回目  3.92 秒  1.06 秒  26.9% 
9回目  3.94 秒  1.06 秒  26.9% 
10回目  3.92 秒  1.16 秒  29.6% 
平均  3.94 秒  1.07 秒  27.1% 

Excel VBAでは、まず「Selectしない」「Selectionを使わない」ことを心がけてください。



このエントリーをはてなブックマークに追加