引数渡し方で、IsMissing結果が異なる

以下のソースは、mWARN_CallingParamsを2回呼び出しています。
自分としては同じ結果(予想は2番目)を期待していたのですが、
違いました。何故でしょうか。
確認環境:Libre Office 7.4.7.2 (x64)

Option Explicit
Option Base 0
Option Compatible

Private sub WARN_CallingParams_Main
CompatibilityMode(True)
Call mWARN_CallingParams aD:=“D”
Call mWARN_CallingParams , , ,“D”
end sub

Private Sub mWARN_CallingParams( _
Optional aA as String, _
Optional aB as String, _
Optional aC as String, _
Optional aD as String, _
Optional aE as String, _
Optional aF as String)

Msgbox _
	"aA(" & IsMissing(aA) & ")" & chr(13) & _
	"aB(" & IsMissing(aB) & ")" & chr(13) & _
	"aC(" & IsMissing(aC) & ")" & chr(13) & _
	"aD(" & IsMissing(aD) & ")" & chr(13) & _
	"aE(" & IsMissing(aE) & ")" & chr(13) & _
	"aF(" & IsMissing(aF) & ")" 

End Sub

あまりわかっていませんが、以下のようにVBASupportをオンにしたら2回とも全部がFalseになりました。なお、VBASupportの行を消した場合は、1回目と2回目の結果が異なりました。なお、どちらのケースでも呼び出しペインでERR448はでています。

Option VBASupport 1
Option Explicit
Option Base 0
Option Compatible

Private sub WARN_CallingParams_Main
CompatibilityMode(True)
Call mWARN_CallingParams aD:="D"
Call mWARN_CallingParams , , ,"D"
end sub

Private Sub mWARN_CallingParams( _
Optional aA as String, _
Optional aB as String, _
Optional aC as String, _
Optional aD as String, _
Optional aE as String, _
Optional aF as String)

Msgbox _
	"aA(" & IsMissing(aA) & ")" & chr(13) & _
	"aB(" & IsMissing(aB) & ")" & chr(13) & _
	"aC(" & IsMissing(aC) & ")" & chr(13) & _
	"aD(" & IsMissing(aD) & ")" & chr(13) & _
	"aE(" & IsMissing(aE) & ")" & chr(13) & _
	"aF(" & IsMissing(aF) & ")" 

End Sub

以下の2つのバージョンで試しましたがどちらも同じでした。

Version: 7.5.5.2 (X86_64) / LibreOffice Community
Build ID: ca8fe7424262805f223b9a2334bc7181abbcbf5e
CPU threads: 4; OS: Linux 5.10; UI render: default; VCL: gtk3
Locale: ja-JP (ja_JP.UTF-8); UI: ja-JP
Calc: threaded
Version: 7.4.7.2 / LibreOffice Community
Build ID: 723314e595e8007d3cf785c16538505a1c878ca5
CPU threads: 4; OS: Linux 5.10; UI render: default; VCL: gtk3
Locale: ja-JP (ja_JP.UTF-8); UI: ja-JP
Calc: threaded

VBASupportをオフにして、呼び出しペインでERR448がでた行を以下のように書き換えてみたら、ERR448がでずに、2回ともaAからaDまでがFalse、aEとaFがTrueになりました。

Call mWARN_CallingParams , , ,"D"
↓
Call mWARN_CallingParams ("","" ,"" ,"D")
Option Explicit
Option Base 0
Option Compatible

Private sub WARN_CallingParams_Main
CompatibilityMode(True)
Call mWARN_CallingParams aD:="D"
Call mWARN_CallingParams ("","" ,"" ,"D")
end sub

Private Sub mWARN_CallingParams( _
Optional aA as String, _
Optional aB as String, _
Optional aC as String, _
Optional aD as String, _
Optional aE as String, _
Optional aF as String)

Msgbox _
	"aA(" & IsMissing(aA) & ")" & chr(13) & _
	"aB(" & IsMissing(aB) & ")" & chr(13) & _
	"aC(" & IsMissing(aC) & ")" & chr(13) & _
	"aD(" & IsMissing(aD) & ")" & chr(13) & _
	"aE(" & IsMissing(aE) & ")" & chr(13) & _
	"aF(" & IsMissing(aF) & ")" 

End Sub

enokiさん
追加確認ありがとうございます。
「Option VBASupport 1」追加の挙動。 こちらの(7.4.7.2 x64)環境でも同じ結果(2回とも全てFalse)を確認できました。

自分は、MS_OFFICEを所有していないので、稼働確認できませんが、下記MSサイト(参考URL(1))でIsMissing関数の仕様を確認すると、IsMissingに引き渡す引数はOptional で Variant型が前提となっているようです。もしかしたら、「Option VBASupport 1」追加により、前述の前提が適用され仕様外の挙動になったのかもしれません。
※ちなみに、引数の型をVariantに変更すると、「Option VBASupport 1」追加しない場合と挙動が一致しました。

参考URL(1):IsMissing 関数 (Visual Basic for Applications) | Microsoft Learn

enokiさん
「Err448を出さない対策」の提案ありがとうございます。

当方環境(7.4.7.2. x64)でも、空文字を渡せば、Err448(MSでは名前付き引数が見つからない)は発生しないことが確認できました。

コマンドリファレンスにOptionalのページがあります(参考URL(1))。そこには記述例として、位置パラメタが一部無指定のケースが記載されていますが、これを実行すると前述の内部エラーの発生が確認できます。もしかしたErr448の発生を前提にIsMissing関数の挙動が実装されているのかもしれないと思ったりします。
そうなると、むしろ名前付き引数を指定した場合、無指定の引数がIsMissingでFalseを返すのは解せません。
そんなわけで、Err448の発生は引数引き渡し文法について実装上想定範囲ではないかと思ったりもします。

参考URL(1):Optional (in Function Statement)

1 Like

関係があるかもしれないバグ報告

Bug 143706 - Missing Optional argument is not properly missing, when ‘:=’ syntax is used
「:=」構文が使用されている場合、オプションの引数が適切に欠落していません
https://bugs.documentfoundation.org/show_bug.cgi?id=143706

2 Likes

nobuさん

連絡遅くなってスイマセン(見落としてました…)

連携頂いたBug 143706の掲載内容確認しました、
本問い合わせが 既にBugとして登録されていたのですね、
しかも対応難しそうみたい…

Bugなら、修正が反映するまで 現状を受け入れて利用するしかありませんね。

Libre Askに問い合わせする前に、今後はBugzillaもみなきゃですね。
(英語ダメダメの私としては、甚だ心もとないのですが…)

ご紹介、ありがとうございました。

1 Like

Bugzillaのチェックはしていなくても、Askに質問してもいいと思います。
そこのハードルがあがって、Askに質問がでなくなってしまう方がコミュニティにとってはよくないのでは?と思っています。

チェックして自己解決された場合でも、そのことを含めて投稿していただけるとAskにナレッジが溜まってありがたいです。

1 Like

的確な話かは判りませんけど、

ステップ実行時、スタックの呼び出しペインは表示されていますか?

二回目では3つのパラメータはERR448が表示されています。

Microsoftと互換かどうかも判りませんけど、名前付き引数が見つかりません
となっています。

YOKOMAYA3さん

【初心者ゆえ、的確な返信でない場合はご指摘ください】

早々の回答ありがとうございます。当方でも2回目のmWARN_CallingParams呼び出しで、
StepModeでStackPainにaA~aCについてError 488の表示を確認できました。

私としては、1回目のmWARN_CallingParams呼び出しで、StepModeでStackPainの
aA~aCについてError 488と表示がされないのが解せません…が、再現性があるわけですから
これが実際の仕様(挙動)なんですかね(引数の順番通り渡す場合は、途中の引数省略は
Errorがでるので使っちゃいけないのかなぁ?)

しかし、名前付き引数を使った場合は、その引数より手前に位置する引数を
指定しない場合、IsMissing関数はFalse(つまり引数が設定されている)と
判定されますので、他の手段で指定してない判断を行わないといけなくなります。
※引数のaA~aFをVariant宣言してIsEmptyの追加判定が必要ですね。

言語仕様とこの挙動が一致しているか比べる術を持ち合わせていませんが、
StepModeで稼働状況を確認すると違いが表れていたので、本件は一旦Close
したいと思っています。

ありがとうございました。

1 Like