VBAより便利で手軽?
Rubyist Magazine #27に「VBAより便利で手軽Excel操作スクリプト言語『Ruby』へのお誘い(前編)」という記事が掲載されていたので、読んでみたのだがちょっと寒い内容だ。VBAでもきっちりサンプルソースを書いた上でrubyとの比較をしていただきたい。むろん僕自身はVBA自身はバッドノウハウ(すでに死語の気もするが)の巣窟であり、出来る限る捨て去りたい物であるのはと思っていることを否定しないし、VBAになんの思い入れもない。VBAの話題自身がいまさらだろうが。
新規にVBAプログラムを書く鉄則はPerlの「use strictとuse warningsを必ず書け」というのと同様に「Option Explicitを必ず書け」で、静的型付け言語なので注意して書きましょうと言うのが前提。これをやってエラーが出るソースは放置するか捨てましょう。放置しておいたほうがよいものに関わってはいけません。(笑)
で、話を戻す。「VBA での文字列操作の不満やイライラを Ruby で解消する」と言う項で書かれているような定型なテンプレートにCellに入力した値を動的に入れて文書やソースを自動で生成したいと言う場合は、ソースにテンプレートを埋め込むと確かにぐちゃぐちゃになってしまうので、やらないというかやってはいけない。ただしヒアドキュメントの埋め込みのようなことはVBAでは出来ないので、下図のA5セルのように適当にテンプレートを書式を保ってCellに入れるか、外部のテキストファイルにしておく。(この記事で実際のテンプレート、置換データの入力、出力データの出力法は本質的ではないので、適当に決めうちで適当なセルに入れたりDebug.Printに出力したが、ちゃんと考えること。) 僕の趣味では外にテキストファイルを作る場合が多く、出力もテキストファイルにしてしまうことが多い。こんな感じのワークシートがあるとする。
VBAが現代的なスクリプト言語に対して弱いところはテキストの取り扱い。特に正規表現周りだが、これは過去の私の日記記事「なんでもかんでもExcel症候群」で触れたように、VBScriptのRegExpオブジェクトを使えば解決するし、おそらく一般的なオフィスにおけるどのWindowsマシンでもExcel VBAとWSHがインストールされていることは期待して良いので、ライブラリ依存問題が問題になるようなことは少ない。「なんでもかんでもExcel症候群」ではテキストファイルを読み込んで走査するようなものを想定して書いてみたが、正規表現による置換を行う関数を分けて共用化して良さそうなので、今回分けてみたのが、下記のソースである。VBAないしはVBユーザーは積極的にWindowsの機能を使っていくべきである。このような便利なライブラリはデファクトの物があっても良さそうなのだが無いようだ。
String型に入れられる文字列のサイズはExcelのバージョン依存であるが、Excel2003以降だと実際試した限りでは数百MBはOKそうである。(おそらく最大2GB?) 従って適切な方法で文字列に入れて、じゃんじゃん置換するのが手っ取り早いと思われる。下手にワークシートに入れると行数や列数の制限で痛い目に遭うので、最終的な出力以外はすべてプログラムで閉じておいた方が良いと思う。
Option Explicit
Public Function RegTr(OrigString As String, Pattern As String, ReplaceString As String) As String
Dim RExp As Object
Set RExp = CreateObject("VBScript.RegExp")
With RExp
.Pattern = Pattern
.IgnoreCase = False
.Global = True
End With
RegTr = RExp.Replace(OrigString, ReplaceString)
Set RExp = Nothing
End Function
Public Sub RESample()
Dim i As Integer
Dim buf As String
Dim outtext As String
buf = Cells(5, 1).Value
For i = 1 To 4
outtext = RegTr(buf, "%package%", Cells(i, 1).Value)
outtext = RegTr(outtext, "%class_name%", Cells(i, 2).Value)
outtext = RegTr(outtext, "%return_type%", Cells(i, 3).Value)
outtext = RegTr(outtext, "%method_name%", Cells(i, 4).Value)
Debug.Print outtext
Next i
End Sub
こんな感じでどうだろうか。単純に置換すればいいのであれば素直に置換を使うべきなのだ。
あとセルなどの書式設定もソースを難読化する要因の一つなので、可能な限りVBAでやってはいけない。(これはRubyとかPerlでExcelやWordをさわる時も同じ。) このへんのスマートな方法は故 石井勝さんの「RubyによるWin32OLEプログラミング - Excelプログラミング(文書作成編)」が参考になる。この記事は元の記事と同じくRubyのWin32OLEプログラミングを扱った記事であるが秀逸な内容の記事である。ここで述べられている手法は言語によらず応用可能なので、VBAでマクロを書く人も参考にすべきだろう。
VBAはすでに枯れた言語でExcel2007への移行があまり行われていないことから仕様もそこそこ安定している。ひょっとしたらPerlに倣って「Excel VBA Best Practice」とか「Excel VBA Hacks」とか出版されれて、Modern VBA Programingとかのたまう連中が出てくれば、ぐちゃぐちゃ度は改善されるかもしれないが、ぐちゃぐちゃな世界は放置して関わらない方が吉であるのも事実なので、こういう本は出ないのだろう。またそこまで柔軟な言語でもないか。