私の初めてのマクロ
私の初めてのマクロ
今さらながら、私と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
メソッドに置き換えてあります。
おわりに
他人の書いたマクロでも、自分の書いたマクロでも、かつてお世話になったものを見返すと、なかなか感慨深いものです。