はじめまして、ぺぱおと申します。
現在作成中のPGの共通関数・クラスが増えたので、共通DLLに
まとめてしまおうとしたのですが、クラス上の関数の最終引数が
Optional ByVal *** As Variant = Empty) となっているために、
「Visual Basic でサポートされていないオートメーションが変数
で使用されています。」
のエラーが表示されてしまいます。(+_+)
呼び出し側が、配列を与えてくるかどうかを判定する為に、関数
開始直後に IsEmpty(***) を使用していました。
ですので、Emptyで初期化できないのが具合が悪い状態です。
●そもそもなぜそのようなエラーが発生するのか?
●標準Exeではなぜ通用するのか?
●回避策はあるのか?
申し訳ありませんが、お知恵をお貸しくださいませ。 <(_ _)>
# VB6 と仮定して回答。
> 配列を与えてくるかどうかを判定する為に
IsArray 関数みたいなものですか?
> そもそもなぜそのようなエラーが発生するのか?
仕様ということなのでしょう。そういえば、Null も駄目だった様な…。
> 標準Exeではなぜ通用するのか?
外部公開しなければ、(Friend以下のレベルであれば)DLLでも使えますね。
> 回避策はあるのか?
初期値を無しにして、IsMissing による判定に切り替えるとか。
魔界の仮面弁士さん 早速の回答ありがとうございました。
># VB6 と仮定して回答。
すいません。使用Verを記載していませんでしたね。おっしゃるとおり
VB6です。
>> 配列を与えてくるかどうかを判定する為に
>IsArray 関数みたいなものですか?
はい、呼び出し側が要素数が不明の1次元配列データをパラメータ
として渡してくるか否かを判定するために、引数としてVariantで、
省略値をEnptyとしました。
Enptyとしたほうが、IsEmptyとして判定できるのと配列の初期化という
ニュアンスとしてはあっているかな?と思ったからです。
こんなケースだとIsArray関数での判定のほうが適切でしょうか?
>> そもそもなぜそのようなエラーが発生するのか?
>仕様ということなのでしょう。そういえば、Null も駄目だった様な…。
はい、質問の前にWebで情報を集めてみたところ、Nullも同様のことが
見受けられました。
また、同ケースに陥った方々はいらっしゃいましたが、それがタブーと
いうことで話が完結していて、対策がわからずじまいでした。
>> 標準Exeではなぜ通用するのか?
>外部公開しなければ、(Friend以下のレベルであれば)DLLでも使えますね。
今環境がないので、試せませんがFriend/Privateレベルであれば、可能と
いうことでしょうか?(Privateは使用する意味があまりありませんが。)
質問ばかりになり申しわけありませんが、仮にFriend関数に定義しなおし
た場合、Publicとなにが変わるのかがよくわかりません。(すいません)
>> 回避策はあるのか?
>初期値を無しにして、IsMissing による判定に切り替えるとか。
「初期値を無」とはどのようなことでしょうか?(Nothing ?)
後術されている IsMissingと合わせコードで説明いただけると助かり
ます。
# Enpty → Empty ですね。
> 呼び出し側が要素数が不明の1次元配列データをパラメータ
> として渡してくるか否かを判定するために、引数としてVariantで、
> 省略値をEnptyとしました。
呼び出し側から見ると、配列を渡さない場合には、
「Empty」
を指定し、配列を渡す場合には、
「要素数 0 の配列」
「初期化されていない 1 次元配列」
「ReDim 済みの 1 次元配列」
のいずれかを渡すということでしょうか?
> 仮にFriend関数に定義しなおした場合、
> Publicとなにが変わるのかがよくわかりません。(すいません)
Private メソッドは、クラス内のみで利用可能で、外部には公開されませんよね。
Public メソッドは、DLL の外からでも呼べるよう、外部に公開されますね。
Friend メソッドは、両者の中間で、DLL の中から呼べるよう、
内部に公開されることになります。(DLL の外から呼ぶ事はできません)
で……標準exe の場合、たとえ Public にしても、そのメソッドは
exe の外部には公開されませんよね。
ということで、
>> 標準Exeではなぜ通用するのか?
という質問に対しては、
「そのメソッドが、プロジェクト外部に対して公開されていないから」
ということになるのかな、と。
> 「初期値を無」とはどのようなことでしょうか?(Nothing ?)
『Optional ByVal x As Variant = Empty』ではなく、
『Optional ByVal x As Variant』にする、ということです。
そうすれば、DLL 側は IsMissing 関数を利用できますよね。
># Enpty → Empty ですね。
いや お恥ずかしい(^^ゞ しかも連発っ
>呼び出し側から見ると、配列を渡さない場合には、
> 「Empty」
>を指定し、配列を渡す場合には、
> 「要素数 0 の配列」
> 「初期化されていない 1 次元配列」
> 「ReDim 済みの 1 次元配列」
>のいずれかを渡すということでしょうか?
呼び出し側は、配列を渡さない場合は引数省略とし、渡す場合は
「ReDim 済みの 1 次元配列」を渡そうとしています。
渡さない場合は引数としてEmptyを渡せばいいだけの話なのですが、
いかんせん関数の使用頻度が高い(配列不要のケース)ため、
Optionalの省略値を利用すれば、コード的にもすっきりするかと
思いました。
>> 仮にFriend関数に定義しなおした場合、
>> Publicとなにが変わるのかがよくわかりません。(すいません)
>Private メソッドは、クラス内のみで利用可能で、外部には公開されません>よね。
>Public メソッドは、DLL の外からでも呼べるよう、外部に公開されます>ね。
>Friend メソッドは、両者の中間で、DLL の中から呼べるよう、
>内部に公開されることになります。(DLL の外から呼ぶ事はできません)
>
>
>で……標準exe の場合、たとえ Public にしても、そのメソッドは
>exe の外部には公開されませんよね。
>
>ということで、
>>> 標準Exeではなぜ通用するのか?
>という質問に対しては、
> 「そのメソッドが、プロジェクト外部に対して公開されていないから」
>ということになるのかな、と。
なるほど、ということは外部公開の可否が判断基準になるということですね。
ちなみに引数にFormやvaSpreadを使ったときに引数に使用できないとエラ
ーが発生したのですが、これも同じ理由なのでしょうか?
理由がわからず、引数の型をVariantにして、関数内でローカルに定義した
各コントロールの型に設定したのですが。。。気持ち悪いですが。
>> 「初期値を無」とはどのようなことでしょうか?(Nothing ?)
>『Optional ByVal x As Variant = Empty』ではなく、
>『Optional ByVal x As Variant』にする、ということです。
>そうすれば、DLL 側は IsMissing 関数を利用できますよね。
すいません。IsMissing関数というものがなじみがなかったもので。
ちなみに、今回の引数定義以外で、能動的にIsMissingの条件にかかるような
方法というのはあるのでしょうか?
IsEmptyならErase *, Is NothingならSet * = Nothing みたいな。
> 呼び出し側は、配列を渡さない場合は引数省略とし、渡す場合は
> 「ReDim 済みの 1 次元配列」を渡そうとしています。
ん?
それだけであれば、IsArray 関数だけで事は足りるのでは…。
または、複数の値を渡す事だけが目的なのであれば、ParamArray を
使うという方法もあるでしょうし、配列として渡したいのであれば、
引数を省略させるのではなく、空の配列を渡す仕様にする、とか。
> IsMissing関数というものがなじみがなかったもので。
そもそも、古いバージョン(VB2 とか VB4 とか)においては、
Optional に初期値を与えるという事ができませんでした。
# しかも当時は、Variant 型しか使えなかったという。
で、その Optional に対して「省略されたかどうか」を判定するために
用意されたものが、引数省略時に True を返す「IsMissing 関数」です。
この関数が、他の用途で用いられる事はありません。
(なお、初期値を持った引数に対しては、IsMissing は常に False を返します)
蛇足まで書いておくと、If IsMissing(x) Then による判定以外の手法として、
If IsError(x) Then あるいは、If VarType(x) = vbError Then によって、
Optional x As Variant 引数を省略されたかどうかを判定する方法もあります。
# ただし、IsMissing とは異なり、CVErr関数で生成された値に対しても
# 反応してしまうので、厳密な判定には向きませんけれども。
>> 呼び出し側は、配列を渡さない場合は引数省略とし、渡す場合は
>> 「ReDim 済みの 1 次元配列」を渡そうとしています。
>ん?
>それだけであれば、IsArray 関数だけで事は足りるのでは…。
>
>または、複数の値を渡す事だけが目的なのであれば、ParamArray を
>使うという方法もあるでしょうし、配列として渡したいのであれば、
>引数を省略させるのではなく、空の配列を渡す仕様にする、とか。
>
>> IsMissing関数というものがなじみがなかったもので。
>そもそも、古いバージョン(VB2 とか VB4 とか)においては、
>Optional に初期値を与えるという事ができませんでした。
># しかも当時は、Variant 型しか使えなかったという。
>
>で、その Optional に対して「省略されたかどうか」を判定するために
>用意されたものが、引数省略時に True を返す「IsMissing 関数」です。
>この関数が、他の用途で用いられる事はありません。
>(なお、初期値を持った引数に対しては、IsMissing は常に False を返しま>す)
>
>
>蛇足まで書いておくと、If IsMissing(x) Then による判定以外の手法とし>て、
>If IsError(x) Then あるいは、If VarType(x) = vbError Then によって、
>Optional x As Variant 引数を省略されたかどうかを判定する方法もありま>す。
># ただし、IsMissing とは異なり、CVErr関数で生成された値に対しても
># 反応してしまうので、厳密な判定には向きませんけれども。
ありがとうございます。
ParamArrayやIsMissingを使用して試してみたいと思います。
補足を入れていただいたのもすごくわかりやすく助かりました。
ツイート | ![]() |