こんにちは。vc掲示板でお世話になったCoffeeと申します。
今度はvbで質問があり投稿しました。
以下のような構造体配列を作成しています。
------------------------------------
public type typAAA
aaa as integer
bbb as long
ccc as string
end type
public XXX() as typAAA
------------------------------------
使用するときはReDimで再生成をするのですが
ReDimする前にXXXが生成されているか?をチェックしたいのです。
if XXX is nothing then 〜〜〜
if XXX is null then 〜〜〜
if IsNothing(XXX) then 〜〜〜
if IsNull(XXX) then 〜〜〜
でも全てコンパイルエラーでした。
チェックする方法は無いのでしょうか?
生成されているかというのは、配列の要素があるかどうかということでしょうか。
それとも変数として宣言されているかどうかということでしょうか。
参考になりますか?
http://hpcgi1.nifty.com/kenzo30/b_cbbs/cbbs.cgi?mode=al2&namber=37781&rev=&no=0&P=R&KLOG=250
チェックしたいのは 【配列の要素があるかどうか?】 です。
BlueさんのURLからIsArray関数を利用してチェックしてみましたが
エラー
「パブリック オブジェクト モジュールで定義されたユーザー定義型に限り、変数に割り当てることができ、実行時バインディングの関数に渡すことができます。」
と出ました。
これは確かFriend関数がどうとかだったような気がするのですが、よく分かりません/(-_-)\
IsArrayはVariant型に対して使うものです。(とリンク先にも書いてあるはず)
On Error GoTo でUBoundの例外を捕まえるのが一番手っ取り早いと思いますよ。
# GetMem4の方法はユーザ定義型で出来るのか自信がないので。
何度も訂正恐縮です。
【配列の要素数を求める】にはUBound関数で求められますが
XXXをRedimしていないとUBound関数は使えません。
ややこしくなったのでまとめると、
XXXを定義した状態(Redimも何もしない。定義しただけの状態)で
XXXはRedimされているか?
を判定したいのです。
ふと思いついた案で
【ZEROは値が無い状態】として
--------------------------------------
Redim XXX(0)
if Ubound(XXX) = 0 then
'何も値が無いので処理できない
end if
--------------------------------------
とすれば良いのかなぁと…。
それでも良いかと思います。
要素数が0は初期値で
要素数が1以上なら再定義されている
という判断ですよね?
まぁBlueさんの仰るとおり、UboundのエラーをCatchして処理する方法
も考えられる一つの方法だと思います。
その通りです。
要素数がZEROが初期値と考え、1から有効値と考えます。
Blueさんの案でも良いのですが
なるべくエラーは出さないコーディング規約なので
上記の案でいってみようと思います。自己解決してしまいました。('A`)
お二方共ありがとうございました。
># GetMem4の方法はユーザ定義型で出来るのか自信がないので。
試してみたけど(Excel VBAですが)、普通に使えるようです。
Option Explicit
Private Declare Sub GetMem4 Lib "msvbvm60" (ByRef Addr() As Any, RetVal As Long)
Public Type typAAA
aaa As Integer
bbb As Long
ccc As String
End Type
Public XXX() As typAAA
Sub Macro1()
Dim p As Long
GetMem4 XXX, p
If p = 0 Then
MsgBox "ReDimされていない"
Else
MsgBox "ReDimされている"
End If
ReDim a(0)
GetMem4 a, p
If p = 0 Then
MsgBox "ReDimされていない"
Else
MsgBox "ReDimされている"
End If
End Sub
SAFEARRAY Data Type
http://msdn2.microsoft.com/en-us/library/ms221482.aspx
より先頭4バイトを見れば配列として扱っているかが判定できるというわけなんでしょう。
VB(6以前やそれと互換性のあるVBAなど)の配列は、C的な表記では
○ SAFEARRAY*
であって、
× SAFEARRAY
ではありません。言い換えれば、
○ if (NULL == (SAFEARRAY*)psa)
をチェックするのであって、
× if (0 == (SAFEARRAY*)psa->cDims)
をチェックしているわけではありません。
>K.J.K.さん
間違って認識していたようです。
メモリの中身を見ているかとばかり思っていました。
VarPtr見たいなものだったんですね。
# 確かにcDimsの値ではないですね。
# ってか、リンク先でSafeArrayGetDimをその後使っているし。 orz
ツイート | ![]() |