私の初めてのマクロ
今さらながら、私とVBAとの出会いについて書いておこう。
VBAとの出会い
きっかけは、
番号入力セルに番号を入力してプリントアウト、次の番号を入力してプリントアウト、次の番号を入力してプリントアウト……を150回ぐらい繰り返す、という業務との出会い
であった。
ちょうどWordの差込印刷のような作業。
「Excelに差込印刷機能はないようだ。しかし、Wordで出来ることをExcelで実現しているやつがいないはずがない!」との確信をもとにインターネッツを調べ、
このページにたどり着いたのが始まりであった。
このページに載っていたコードが次のもの。
リスト1
Option Explicit
Sub 個人票印刷()
Range("個人番号") = Range("自")
Do While Range("個人番号") <= Range("至")
Sheets("個人票").PrintOut
Range("個人番号") = Range("個人番号") + 1
Loop
End Sub
たとえば、

このような「個人票」というシートがあり、「個人番号」欄(A4セル)に番号を入力したら、

このシートからデータを引っ張ってきて「名前」欄(B4セル)とか、「実数」欄(B7~B10セル)に表示する、というふうになっていると思ってほしい。
「個人票」シートでは、



このように、それぞれセルに名前を付けている。
で、上掲のコード。
なかなか壮絶なコードであるw
しかしながら、こいつのおかげで
番号入力セルに番号を入力してプリントアウト、次の番号を入力してプリントアウト、次の番号を入力してプリントアウト……を150回ぐらい繰り返す、という業務
があっという間に片付いたのである。
当時、ほぼこの作業のためだけに休日職場に出て行って、「昼までに終わるかなあ……」と思っていた私は驚きましたね。
エディケア、すごい…
と。
これがまさに、私とVBAとの出会いであった。
そして、一発でハマったのであった。
せっかくなので書き換える
それにしても、である。
世話になっておいてアレだが、リスト1のクソっぷりは何だ?!
今ならこう書く、というのを記念に残しておこう。
リスト2 シートモジュール
※「個人票」シートのモジュールです。
Option Explicit
Private Property Get StartNumber() As Long
Dim ret As Variant
ret = Me.Range("J3").Value
If Not IsNumeric(ret) Then ret = 0
If ret > 2 ^ 31 - 1 Then ret = 0
StartNumber = ret
End Property
Private Property Get EndNumber() As Long
Dim ret As Variant
Dim rng As Range
Set rng = Me.Range("J4")
ret = rng.Value
If Not IsNumeric(ret) Then ret = 0
If ret > 2 ^ 31 - 1 Then ret = 0
If ret < StartNumber Then _
ret = StartNumber: rng.Value = ret
EndNumber = ret
End Property
Private Property Get NumberCell() As Range
Set NumberCell = Me.Range("A4")
End Property
Private Sub insertionPrint()
Dim startNum As Long
startNum = StartNumber
If startNum = 0 Then Exit Sub
Dim endNum As Long
endNum = EndNumber
If endNum = 0 Then Exit Sub
Dim n As Long
n = startNum
With Me
NumberCell.Value = n
Do
Call .PrintOut
If n = endNum Then Exit Do
n = n + 1
NumberCell.Value = n
Loop
End With
End Sub
シートモジュールにプロパティとメソッドを生やす形にした。
元のコードよりもずいぶん記述が増えたが、この方が良いと思う。
元のコードのイマイチなところ
リスト1を再掲する。
リスト1 再掲
Sub 個人票印刷()
Range("個人番号") = Range("自") '……(1)'
Do While Range("個人番号") <= Range("至") '……(2)'
Sheets("個人票").PrintOut
Range("個人番号") = Range("個人番号") + 1 '……(3)'
Loop
イマイチその1
(1)の
Range("個人番号") = Range("自")
は何だ!?
ハダカのRangeとか、めちゃくちゃ気持ち悪い!
.Valueの省略も気持ち悪い!
イマイチその2
(2)の
Do While Range("個人番号") <= Range("至")
は何だ!?
.Valueの省略が気持ち悪いのはともかく、Range("個人番号")の値が不適切だったら処理をしない、と言うのなら、そもそも入り口でハネておくべきで、ループの継続条件と一緒くたにするべきではない。
多少冗長になっても、一つのステートメント(でいいのか?)には一つの役割、というようにすべきだ。
イマイチその3
(3)の
Range("個人番号") = Range("個人番号") + 1
は何だ!?
もはや.Valueの省略については何も言うまい。しかし、1ループごとにRange("個人番号")を評価して代入、というのは気持ち悪いぞ。
イマイチその4
そもそも、インデントの仕方が気持ち悪い。
以上、異論は認める。
実行
ちなみに、上記のマクロは、リスト1、リスト2ともに、

このように動作する。
もちろん、実際にプリントアウトしても仕方がないので、リスト1、リスト2ともに、PrintOutメソッドのところをPrintPreviewメソッドに置き換えてあります。
おわりに
他人の書いたマクロでも、自分の書いたマクロでも、かつてお世話になったものを見返すと、なかなか感慨深いものです。