記事カテゴリ

ユーザー機能


 2024年5月 3日(金) 22:46 JST

[VB/VBA] 空配列のUBoundが-1にならない?

  • 投稿者:
  • 表示回数
    17,394
最近はずっと Microsoft の Excel でVBAプログラムを作成している。

VBA だろうと何だろうと保守性の低いプログラムを作りたくないので、機能単位でクラスモジュールにしているが、所詮 Excel なので、Book 間でソースが共有できない。
ここが、保守管理上一番の問題点かな?と感じている。
100個プログラムを作って、共通部分に仕様変更があれば、100回修正を行うかモジュール単位でインポートを行う必要がある。
一つのモジュール内に共通部分と独自部分が共存していれば、単にインポートすれば良い問題ではなくなる。しかし、VBA のクラスモジュールは継承が出来ないので、機能単位に分けたときに、それをさらに共通部分と独自部分に分けて、独自部分を継承で作るというわけに行かない。

今日、またクラスモジュールを作成し使おうとしたら、こける...
原因を調べてる内に問題が見つかった。先ほど書いたこける問題とは別の問題だったのだが、動的配列に対し UBound を行うとこけるケースがあった。
動的配列を作って最初はサイズを 0 にしていたのだが、サイズ 0 の配列に対し UBound を行うとエラーが発生する仕様らしい。どうにかして回避できる方法が無いか、調べていると以下のような回避方法を見つけた。

まず、以下のように宣言を行う。
Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32" _
   (ByVal cDims As Long, _
    ByRef ppsaOut() As Any) As Long

実際に使用する前に、このAPI を適用します。関数内での使用であれば、宣言の直後にやっておくと良いかと思います。今回はクラスモジュールで使用したので、Clear と言うメソッドを作ってそこで使用しました。
以下のような感じになりました。
    Dim Hairetsu() As UserType
    SafeArrayAllocDescriptor 1, Hairetsu
すると、以降で空配列に対して行う UBound(Hairetsu) が -1 になりました。
でも、こける原因が実は別にあって、グローバルで宣言されていたのを使用していると思ったら、実はローカル関数内にも同じように定義していたので、それでアウトになっていたのでした。
しかし、ウォッチにコンパイル出来ませんと出すと何かまた別のエラーのように見えちゃいます...

しかし、もう二度と同じ手には引っかからないぞ!という意味を込めてここにメモしておきます。

トラックバック

このエントリのトラックバックURL:
https://www.blackcat.xyz/trackback.php/vbvba_ubound1_1

以下のコメントは、その投稿者が所有するものでサイト管理者はコメントに関する責任を負いません。