今回はイミディエイトウィンドウを使用してマクロでマクロを出力してみる。
まずはイミディエイトウインドウの使い方を紹介しようと思う。
イミディエイトウインドウに 「?変数」と入力すると、その変数の値が表示される。「?オブジェクト.プロパティ」でも良い。
コードの実行中に値を確認したい時などに便利だ。
ちなみにコードの実行を中断するには以下4つの方法がある。
・エラーを発生させる
・break pointを設定する。
・Stop命令を書く
・Debug.Assert命令を書く
Stop命令は、コードに書くBreakPointだと思えば良い。実行すると必ずそこで中断し、F8でステップ実行で再開、F5で普通に再開する。
止まっている間に、イミディエイトウインドウを使用して変数の値やプロパティなどを確認できる。
Debug.Assertというのはあまり知られていないと思うが、条件式を書いてそれがFalseの場合にコードが停止される機能である。
たとえばループ中でiが3の時にそれぞれのオブジェクトがどうなっているか知りたい等の場合は、Debug.Assert i <> 3と書けばそこで停止するので、あとはイミディエイトウインドウで確認できる。
ただし、デバッグ用の機能なので、マクロが完成した際には削除する。
次に、Debug.Printでの出力であるが、以外と知られていないのが出力をカンマ区切りにするとタブで区切られること。
Debug.Print "aaa", "bbb", "ccc"と書くと、aaa bbb ccccのようにタブ区切りで表示される。
また、セミコロン区切りにすると、そのままつなげて表示される。
Debug.Print "aaa";"bbb";"ccc"→aaabbbccc
最後にコード自体を生み出す場として使うケース。やっとタイトルの内容である。
冗長なコードを作ることはなるべく避けたいが、それでも避けられないような時はマクロにコードを書かせるという選択肢がある。
たとえば覆面算を解くプログラムなどは記述がどうしても冗長になる。
【参考サイト】
こういうときは、まずイミディエイトウインドウにコードを出力させるプログラムを書いて、そこからコピーしてくると多少は楽にコーディングできる。
たとえば以下を実行すると、
Sub CodeGeneratorSample() Dim arr() As String arr = Split("u s a r p e c", " ") For i = 0 To UBound(arr) Line = "if (" For j = 0 To UBound(arr) If i <> j Then Line = Line & arr(i) & "==" & arr(j) & " || " Next j Debug.Print Left(Line, Len(Line) - 4) & ") continue;" Next i End Sub
次のようなCのコードが得られる。
if (u==s || u==a || u==r || u==p || u==e || u==c) continue; if (s==u || s==a || s==r || s==p || s==e || s==c) continue; if (a==u || a==s || a==r || a==p || a==e || a==c) continue; if (r==u || r==s || r==a || r==p || r==e || r==c) continue; if (p==u || p==s || p==a || p==r || p==e || p==c) continue; if (e==u || e==s || e==a || e==r || e==p || e==c) continue; if (c==u || c==s || c==a || c==r || c==p || c==e) continue;
何でCかって言うと、たまたま見つかった覆面算のサンプルがCだったから。以前VBAで作ったのだが紛失してしまった。わざわざ作るのも面倒なので今回は人様のブログから拝借させていただいた次第である。
今回の例に関して言えば、ジェネレーターマクロを作る方が手間かもしれないが、End IfやForのネストが多いコードではイミディエイトウインドウで作るという手もあるので、アイデアとして覚えておくと役に立つかもしれない。