VBAでのオブジェクト渡し

解決


にゃ  2006-05-18 06:59:26  No: 95443

Excel2002のVBAを使用して、データをリストボックスのアイテムとして追加する関数を作成しました

Public Function LstboxAdd(ByRef Box As ListBox, ByRef Str As String)

この関数を引数として渡すリストボックスと同じフォーム上に配置した
コマンドボタンのClickイベントとして下記のように呼び出しているのですが、何故かNULLが渡されてしまいます

MsgBox ListBox1.ListCount
Call LstboxAdd(ListBox1, Txt)

メッセージボックスには問題なくアイテム数が表示されるのですが、
リストボックスそのものはNULLとなっていて引数として渡すことが出来ないのです
同様に、コンボボックス用に作成した場合は問題なく動作するのですが……
これはリストボックスの制限か何かでしょうか?

分かる方がいらっしゃいましたらご教授下さい、お願いします


にゃ  2006-05-18 07:08:36  No: 95444

失礼、若干訂正です

MsgBox ListBox1.ListCount
Call LstboxAdd(ListBox1, Txt)

ではなく

Dim Res As Boolean
MsgBox ListBox1.ListCount
Res = LstboxAdd(ListBox1, Txt)

でした
問題はないと思いますが念のため訂正しておきます


魔界の仮面弁士  2006-05-18 08:04:02  No: 95445

# 何故、ByRef で渡しているのかが微妙に気になる…。

> 何故かNULLが渡されてしまいます
「NULL が渡され」たかどうかを、どのようにして確認していますか?

Excel.ListBox 型にしろ、MSForms.ListBox 型にしろ、そういった
オブジェクト型の変数に対しては、Nothing なら渡せますが、
Null値を渡す事はできないはずです。
# ただ、ListBox のメンバ(例えば、既定のプロパティ)から、Null値が
# 返される可能性ならばありえますけれどね。

本当に、オブジェクト型に Null が渡されているのかどうかを確認するために、
Public Function LstboxAdd(ByRef Box As ListBox, ByRef Str As String)
の中で、「Debug.Print VarType(Box)」を実行してみてください。
本当に Null ならば、vbNull すなわち「1」と表示されるはずです。


にゃ  2006-05-18 10:54:37  No: 95446

>魔界の仮面弁士 サマ
ご返答ありがとうございます

NULLの確認ですがイミディエイトウィンドウで確認しています
ですので表記はNULLですが値を確認したわけではありません
現在の環境では確認が取れないため、明日にでも確認をしてみようかと思います

#内容を変更することを明示的にするためRefにしたのですが、オブジェクト型相手ではByValで十分ですね
#参照対象を変更することは仕様的にないとはいえ、視覚的に分かりやすいかと思って安易にRefにしたのは迂闊でした


にゃ  2006-05-18 12:41:09  No: 95447

今更ながらミスに気付きました
実行時のエラーを書いていませんでしたね(書いていればすぐに何が悪かったのか気付けたはずなのに)
実行エラーは13、要するに引数の定義が悪かったようです

Public Function LstboxAdd(ByRef Box As MSForms.ListBox, ByRef Str As String)

こうするべきだったようで
魔界の仮面弁士サマの書き込みを湯船で思い出していたらふと気付いたので、自宅環境で下記のソースを実行して確認しました

Option Explicit

Private Sub CommandButton1_Click()
    Debug.Print VarType(ListBox1)
    Call LstAdd(ListBox1)
End Sub

Private Sub UserForm_Initialize()
    ListBox1.AddItem "A"
End Sub

Private Sub LstAdd(ByVal Lstbox As MSForms.ListBox)
    Debug.Print VarType(Lstbox)
    Lstbox.AddItem "NewItem"
End Sub

デバッグには1と表示されるのにもかかわらず、問題なく実行出来るのが理解に苦しみますが……
不明点はありますが、タイトルの案件については解決ということで現場で動作を確認次第、解決とさせていただきます

#1つ前の「明示的にするための〜」下りですが、多少ソースを読めるというレベルのプログラマ以外の者も読む可能性があるため、という意味です


魔界の仮面弁士  2006-05-18 18:24:45  No: 95448

> デバッグには1と表示されるのにもかかわらず、
もし、Sub UserForm_Initialize にて登録された「A」という文字が
選択状態であれば、vbNull ではなく、vbString になるはずです。

つまり、先の回答の
>> # ただ、ListBox のメンバ(例えば、既定のプロパティ)から、Null値が
>> # 返される可能性ならばありえますけれどね。
の方にあたるという事になります。すなわち、
  VarType(Lstbox.Value)
に対する判定が行われていたわけですね。
TypeName(LstBox) ならば、"ListBox" が返されるはずですし、
IsObject(LstBox) は True を返すはずです。

> 問題なく実行出来るのが理解に苦しみますが……
Sub LstAdd内の「Lstbox」の部分を範囲選択、右クリックして、
『ウォッチ式の追加』を選択してみてください。
そして、LstAdd 内で一時停止させてみれば、変数 Lstbox が
何型であるか、また、その値が何であるかを確認/変更できます。

ListBox の「既定のプロパティ」に惑わされてしまうかも知れませんが、
たとえば、『LstBox = Null』という代入式のコードを実行すると、
実際には「LstBox.Value = Null」を実行した事になります。
(ただし、LstBox As Variant の場合は別の結果になります)

これについては、たとえば、
    LstBox = "ListBoxに登録されていない値"
といったコードを試してみると、
    実行時エラー '380':
    Value プロパティを設定できません。 プロパティの値が無効です。
というエラーになり、既定のプロパティ Value が利用されている事を
確認する事ができるでしょう。


にゃ  2006-05-18 19:32:41  No: 95449

>魔界の仮面弁士 サマ
詳しい解説ありがとうございます

試してみた結果、仰られる通りValueの値が表示されているのが確認できました
暗黙的に処理される機会が多いVBだけに、明示的に宣言することに注意を払うべきなようですね
本当にご指摘ありがとうございました
動作も確認致しましたので、これにて解決とさせていただきます


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加