t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

VBA 表のヘッダーを作成するコード…を作るコード

皆さんはマクロで表のヘッダーを作成するときにどういう風にされているだろうか。

もっともシンプルなのは、ひとつずつセルのValueを設定していく方法だ。

Sub ヘッダー設定A()
    Range("A1").Value = "氏名"
    Range("B1").Value = "住所"
    Range("C1").Value = "生年月日"
    Range("D1").Value = "性別"
End Sub

少しVBAをかじった方なら誰でも読めるというのがこのコードのメリットだ。

しかし、このコードにはヘッダーが増えた場合に書くのが面倒くさいというデメリットがある。
また、氏名と住所の間に、ふりがなを追加したいと思ったら、後続のセル指定をすべてずらす必要がある。

Sub ヘッダー設定A()
    Range("A1").Value = "氏名"
    Range("B1").Value = "ふりがな"  '←振り仮名をB1に追加したい。
    Range("B1").Value = "住所"  '←要修正
    Range("C1").Value = "生年月日"  '←要修正
    Range("D1").Value = "性別"  '←要修正
End Sub

これは非常に面倒くさいので、別の方法を考えてみた。

Sub ヘッダー設定B()
    ヘッダー = Split("氏名 住所 生年月日 性別", " ")
    For i = 0 To UBound(ヘッダー)
        Cells(1, 1).Offset(0, i).Value = ヘッダー(i)
    Next
End Sub

Split関数は、文字列を特定の文字で区切って配列にする関数である。

Split([対象文字列], [区切り記号])

これでヘッダー配列を作成し、For文でまわしながらCells(1,1)からの相対指定(Offset)でヘッダーを入力している。

氏名と住所の間にふりがなを入れたい場合、単純に挿入するだけで良い。

Sub ヘッダー設定B()
    ヘッダー = Split("氏名 ふりがな 住所 生年月日 性別", " ")
    For i = 0 To UBound(ヘッダー)
        Cells(1, 1).Offset(0, i).Value = ヘッダー(i)
    Next
End Sub

しかし、このコードのデメリットは複雑であることだ。
自分が担当を外れた後、だれかVBAのできる人にメンテナンスを任せようと思ったら、もう少し単純なほうが良いかもしれない。

メンテナンス性と、コードの単純さを両立させるにはどうすればよいか。
ひとつの解決策は、マクロにコードを書かせることだ。

Sub ヘッダーを作成するコードを作成するコード()
    ヘッダー = Split("氏名 住所 生年月日 性別", " ")
    For i = 0 To UBound(ヘッダー)
        Debug.Print "Range(""" & Chr(Asc("A") + i) & 1 & """).Value = """ & ヘッダー(i) & """"
    Next
End Sub

上記を実行すると、イミディエイトウインドウに以下が出力される。

Range("A1").Value = "氏名"
Range("B1").Value = "住所"
Range("C1").Value = "生年月日"
Range("D1").Value = "性別"

あとはメインコードに貼り付ければよい。

項目が増えても、単純に挿入するだけで良い。

Sub ヘッダー設定Aを作成するコード()
    ヘッダー = Split("氏名 ふりがな 住所 生年月日 性別", " ")
    For i = 0 To UBound(ヘッダー)
        Debug.Print "Range(""" & Chr(Asc("A") + i) & 1 & """).Value = """ & ヘッダー(i) & """"
    Next
End Sub

実行すると新しいコードが吐き出されるので、差し替えれば良い。

Range("A1").Value = "氏名"
Range("B1").Value = "ふりがな"
Range("C1").Value = "住所"
Range("D1").Value = "生年月日"
Range("E1").Value = "性別"

※ちなみに上記のコードはZ列までしか対応していない。

さて、色々書いているうちにもっと効率の良い方法を思いついた。

まず、シートにあらかじめヘッダーを手入力しておき、それを選択状態する。
f:id:t-hom:20150913002057p:plain

そして以下のマクロを実行する。

Sub 選択セルからコードを作るマクロ()
    Dim r As Range
    For Each r In Selection
        Debug.Print "Range(""" & r.Address(False, False) & """).Value = """ & r.Value & """"
    Next
End Sub

するとイミディエイトウィンドウに以下のように出力される。

Range("A1").Value = "氏名"
Range("B1").Value = "ふりがな"
Range("C1").Value = "住所"
Range("D1").Value = "生年月日"
Range("E1").Value = "性別"

あとはこれをメインコードに貼り付けて実行すれば、シート上のヘッダーを消しても再現できる。

こうしたテクニックはメタプログラミングと呼ばれる。

これは別にVBAに限ったテクニックではない。
たとえばC言語VBAを書かせることもできるし、VBAC言語のコードを書くこともできる。

コードを作成するためのマクロをいくつかストックしておくと、コーディングの効率アップになるので覚えておきたい。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。