なぜマクロの記録だけでプログラムが書けないのか?

ブログ

はじめに

 ExcelVBAをはじめようとしている人の中には、「マクロの記録」を使えば自由にプログラムが書けるのではないか?と考える人もいるのではないだろうか。

 ところがある程度の事まではマクロの記録で実現できるが、少し複雑な事をしようとすると途端に思い通りの動作ができないという事に気付く事になる。

 理由は簡単で、マクロの記録はその時に使われるオブジェクトやそのプロパティを記録してくれる機能しか持ち合わせていないからだ。

マクロの記録はオブジェクトを示すだけ

 初心者にはオブジェクトというものが何か分からないと思うので、そこから解説したいと思う。
※実は初心者にオブジェクトを説明するほど大変な事はないのだが、、

 オブジェクトとは、ExcelVBAの場合、Excelの部品と考えてもらうと通りが良い。
具体的には、セルやシート、ブックなどがオブジェクトにあたる。

 オブジェクトにはプロパティとメソッドという2種類のメンバーがいる。
プロパティとは「属性」のことで、メソッドは「命令」になる。

 ここではセルオブジェクトを例にして考えてみよう。
セルのプロパティはたくさんあるが、「値」「背景色」「フォント」「文字色」などがそうだ。
対してメソッドは、「選択」「コピー」「貼り付け」「削除」などだ。

 理屈ばかり話してもわかりずらいと思うので具体例を見ていこう。

マクロの記録が吐き出すコード

 マクロの記録で、A1セルを選択してコピーし、A2セルにペーストした時、吐き出されたコードが以下のものだ。コメント部分は筆者が追記している。

Sub Macro1()
'
' Macro1 Macro
'

'
    Range("A1").Select  'A1セルを選択
    Selection.Copy      '選択したセルをコピー
    Range("A2").Select  'A2 セルを選択
    ActiveSheet.Paste   '現在のシートにペースト
End Sub

 このコードでは、選択、コピー、選択、ペーストという具合にメソッドのみを使っている。
次は、プロパティを変更している例を見てみよう。

 以下のコードは、A1セルの背景色を黄色に変更する操作をマクロの記録で吐き出してみた。

Sub Macro2()
'
' Macro2 Macro
'

'
    Range("A1").Select
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .Color = 65535
        .TintAndShade = 0
        .PatternTintAndShade = 0
    End With
End Sub

 このコードでは、With ~ End With が使われているのが特徴的だ。
With XXXXX とした場合、End With が来るまで、その部分を省略して良いというルールがある。
これを省略せずに書くと以下のようになる。

Sub Macro2a()
    Range("A1").Select
    Selection.Interior.Pattern = xlSolid    '塗りつぶしのパターン(網掛けなし)
    Selection.Interior.PatternColorIndex = xlAutomatic  'パターンの色(自動)
    Selection.Interior.Color = 65535    'パターンの色(黄色)
    Selection.Interior.TintAndShade = 0 '暗さ(標準)
    Selection.Interior.PatternTintAndShade = 0  '濃淡と網掛けのパターン(標準)
End Sub

 今度は、コメントを追記している。実は、背景色を黄色にするだけなら、.Interior.Colorの部分だけで十分なので、以下のように書いても良い。

Sub Macro2b()
    Range("A1").Select
    Selection.Interior.Color = 65535    'パターンの色(黄色)
End Sub

なぜプログラミングできないのか?

 ここまででかなりの事ができそうなのだが、実はプログラミングの大事なファクターをマクロの記録は実現できない。

 それは、繰り返し処理条件分岐だ。具体的にはFor文とIf文というのは、マクロの記録では出て来ない。
そもそもプログラミングの基本要素は、変数、繰り返し処理、条件分岐が必要になる。近年では、オブジェクト指向が当たり前になっているので、前述のオブジェクトを使用するのが当たり前になっているが、マクロの記録では、オブジェクトの操作は記録できても、繰り返し処理や条件分岐は表現できないのである。

 具体的には、For If が出て来ない。ちなみに、変数に関しては、Select や Selection で補う形になっている。

 逆を言えばマクロの記録にFor文やIf文を付け加える事でプログラミングする事が可能になる。

For文と取り入れてみる

 マクロの記録でプログラムコードを吐した後に、For文を追加してプログラミングしてみよう。

 以下の図は、マクロの記録でA1セルからG1セルまでを選択して薄い青色の背景色にしてみた様子だ。


マクロの記録で吐き出されたコードは以下のようになる。

Sub Macro1()
'
' Macro1 Macro
'

'
    Range("A1:G1").Select
    With Selection.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorAccent1
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
    End With
End Sub

 黄色い下線部分を逐次変更していけば、以下のように縞模様のセルを描く事ができそうだ。

 プログラムの変更の仕方はいくつかあるが、今回は以下のようにしてみた。

Sub Macro1a()

    For i = 1 To 10 Step 2
    
        Range(Cells(i, "A"), Cells(i, "G")).Select
        With Selection.Interior
            .Pattern = xlSolid
            .PatternColorIndex = xlAutomatic
            .ThemeColor = xlThemeColorAccent1
            .TintAndShade = 0.799981688894314
            .PatternTintAndShade = 0
        End With
    
    Next i
    
End Sub

 変更したのは、黄色い下線部分になる。
まず、For文の所では、i という変数を使っている。ここでは、最初に i に 1 が代入されて、これが10になるまで繰り返し実行される、更に Step 2 となっているので、1つ飛ばしになる。つまり i は、1,3,5,7,9 と変化していく。

 繰り返し部分は、Next までだ。NextからForまで戻って処理が繰り返されることになる。

 難しそうなのは、Range(Cells(i, “A”), Cells(i, “G”)).Select の部分だろう。
Rangeにはいくつかの書き方があって、Range(開始セル,終了セル) とすると複数のセルを対象にする事ができる。
 さらに、For文を使うときには、RnageよりもCellsを使った方が相性が良い。Cellsでは、Cells(,)とする事でセルを指定する事ができる。Rangeが文字列でセルの場所を指定するのに対して、Cellsでは、数値で行や列を指定する事ができる。(列に関してはアルファベットも可能だ)

 これらの事を利用すれば、A列からG列までのセルを数値でコントロールできるようになる。

If文を取り入れてみる

 次は、If文を取り入れてみよう。If文は「もし○○なら**」するという条件分岐処理だ。
書式は以下のようになる。

 If 条件式 then
条件式が真なら実行
 End If

 ここでは、以下のように数値が並んでいる時、偶数の場合にセルに背景色を付けてみよう。
背景色の付け方は上記のプログラムをそのまま使う。

 プログラムは以下のようにしてみた。

Sub Macro1b()

    For i = 1 To 10
    
        If Cells(i, "B") Mod 2 = 0 Then
        
            Cells(i, "B").Select
            With Selection.Interior
                .Pattern = xlSolid
                .PatternColorIndex = xlAutomatic
                .ThemeColor = xlThemeColorAccent1
                .TintAndShade = 0.799981688894314
                .PatternTintAndShade = 0
            End With
        
        End If
    Next i
    
End Sub

 プログラムの内容を見ていこう。
まず、For文はB列の1行目~10行目までを繰返す。今回は1行づつ進めるので Step は省略できる。

 次がIf文。条件式は、Cells(i, “B”) Mod 2 = 0 の部分だ、
 少々わかりずらいと思うが、Mod は、左辺を右辺で割った余りを返す演算子となる。
ここでは、B列のセルを 2 で割って答えが 0 の場合、If文の内部を実行する事になる。

 If文の内部は、前のプログラムと殆ど同じだが、セルの選択は Cells のみとなっている。

 実行結果は以下の通りだ。

 ちなみに、1行目は数字が無いが、背景色が塗られている。これは空白のセルの値を計算式に入れると 0 として判断されるからだ。

まとめ

 今回のトピックで、なぜマクロの記録でプログラミングができないのかが理解できただろう。
勘の良い人なら、Macro1()のコードでRange部分を変更して書き連ねていけば同じような事ができるじゃないかと思うだろう。ただ、それは「記録」であってプログラミングとはならない。

 結果だけ求めるならその方法でも間違いではないが、汎用性がなく転用もしにくくなってしまう。

マクロの記録とどう向き合うべきか

 マクロの記録を使って楽にプログラミングできないか?と考えているなら、初心者はその考えを捨てた方が良いだろう。結局遠回りになってしまうからだ。

 初心者であれば、セルの扱いを中心に細かなルールをコツコツ覚えていく方が上達は早いだろう。コツとしては一度にたくさんの事を詰め込もうとせず、少しづつ知識を重ねていく事だ。

 ある程度、プログラミングの知識が身に付いてきた時、マクロの記録はとても役に立つ。実はオブジェクトというのは膨大なプロパティとマクロがある。ある処理に対してどのようなオブジェクトのプロパティを使っているのかを調べる時、マクロの記録は非常に役に立つ。

 マクロの記録はプログラミングに慣れてから使うのが吉と言えるだろう。

コメント

タイトルとURLをコピーしました