最近はずっと Microsoft の Excel でVBAプログラムを作成している。<br />
<br />
VBA だろうと何だろうと保守性の低いプログラムを作りたくないので、機能単位でクラスモジュールにしているが、所詮 Excel なので、Book 間でソースが共有できない。<br />
ここが、保守管理上一番の問題点かな？と感じている。<br />
100個プログラムを作って、共通部分に仕様変更があれば、100回修正を行うかモジュール単位でインポートを行う必要がある。<br />
一つのモジュール内に共通部分と独自部分が共存していれば、単にインポートすれば良い問題ではなくなる。しかし、<strong>VBA のクラスモジュールは継承が出来ないので、<em>機能単位に分けたときに、それをさらに共通部分と独自部分に分けて、独自部分を継承で作る</em>というわけに行かない。</strong><br />
<br />
今日、またクラスモジュールを作成し使おうとしたら、こける...<br />
原因を調べてる内に問題が見つかった。先ほど書いたこける問題とは別の問題だったのだが、動的配列に対し UBound を行うとこけるケースがあった。<br />
動的配列を作って最初はサイズを 0 にしていたのだが、サイズ 0 の配列に対し UBound を行うとエラーが発生する仕様らしい。どうにかして回避できる方法が無いか、調べていると以下のような回避方法を見つけた。<br />
<br />
まず、以下のように宣言を行う。<br />
<pre class="code">Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" _
   (ByVal cDims As Long, _
    ByRef ppsaOut() As Any) As Long
</pre>
<br />
実際に使用する前に、このAPI を適用します。関数内での使用であれば、宣言の直後にやっておくと良いかと思います。今回はクラスモジュールで使用したので、Clear と言うメソッドを作ってそこで使用しました。<br />
以下のような感じになりました。<br />
<pre class="code">
    Dim Hairetsu() As UserType
    SafeArrayAllocDescriptor 1, Hairetsu
</pre>
すると、以降で空配列に対して行う <em>UBound(Hairetsu) が -1</em> になりました。
<br />
でも、こける原因が実は別にあって、グローバルで宣言されていたのを使用していると思ったら、実はローカル関数内にも同じように定義していたので、それでアウトになっていたのでした。<br />
しかし、<strong>ウォッチにコンパイル出来ません</strong>と出すと何かまた別のエラーのように見えちゃいます...<br />
<br />
しかし、<em>もう二度と同じ手には引っかからないぞ！</em>という意味を込めてここにメモしておきます。