1

Excel 用の VBA マクロを作成しているときに、構文オプションに問題があります。VBA では、次の 2 つの方法でオブジェクトのメソッドを呼び出すことができます。

foo.bar(arg1, arg2)

また

foo.bar arg1, arg2

私は 2 番目の種類の構文を絶対に嫌います。なぜなら、それには何らかの明確さが欠けているからです。そのため、通常は最初のオプションに従います。ただし、最初のオプションを使用するとエラーが発生し、2 番目のオプションは正常に実行されるという状況に遭遇しました。(これはおそらく、私のコードの他の問題を示している可能性があります。) 犯人のコードは次のとおりです。

Function GetFundList() As Collection
    Dim newFund As FundValues
    Range("A5").Select
    Set GetFundList = New Collection

    While Len(Selection.Value)
        Set newFund = New FundValues

        ' I set the fields of newFund and move Selection

問題は次の行にあります。

        GetFundList.Add newFund
    Wend
End Function

FundValues は私が作成したクラスで、本質的に単なる構造体です。ループ中に設定される 3 つのプロパティがあります。

基本的に、私が呼び出すGetFundList.Add(newFund)と、次のエラーが発生します。

実行時エラー '438': オブジェクトはこのプロパティまたはメソッドをサポートしていません

しかし、通話GetFundList.Add newFundはまったく問題ありません。

なぜこれが起こっているのかを説明するのに十分なVBAの複雑さを理解している人はいますか?

編集:説明をありがとう!

4

3 に答える 3

0

コレクションへのアイテムの追加は、値を返す関数としてではなく、サブルーチンとして定義されます。

Public Sub Add( _
   ByVal Item As Object, _
   Optional ByVal Key As String, _
   Optional ByVal { Before | After } As Object = Nothing _
)

別のサブルーチンを名前で呼び出して引数を送信する場合 ("Call" ステートメントを追加せずに)、括弧を追加する必要はありません。変数に値を返す
関数を呼び出すときは、括弧を追加する必要があります。

例:

Sub Test_1()
Dim iCnt As Integer
Dim iCnt_B As Integer
Dim iResult As Integer


iCnt = 2
iCnt_B = 3

fTest_1 iCnt, iResult, iCnt_B

End Sub

Public Function fTest_1(iCnt, iResult, iCnt_B)

iResult = iCnt * 2 + iCnt_B * 2

End Function

Sub Test_2()

Dim iCnt As Integer
Dim iCnt_B As Integer
Dim iResult As Integer


iCnt = 2
iCnt_B = 3

iResult = fTest_2(iCnt, iCnt_B)

End Sub

Public Function fTest_2(iCnt, iCnt_B)

fTest_2 = iCnt * 2 + iCnt_B * 2

End Function

明確でない場合はお知らせください。

于 2012-07-30T15:44:43.887 に答える
0

このDaily Dose of Excel の会話は役に立ちます。

括弧を使用すると、VBA に括弧内の内容を評価させ、結果をコレクションに追加します。NewFund にはデフォルトのプロパティがないため (推測しますが)、評価では何も得られず、追加できません。括弧がなければ、クラスのインスタンスに評価されます。これが必要です。

もう一つの例。これ:

Dim coll As Collection
Set coll = New Collection
coll.Add Range("A1")
Debug.Print coll(1); TypeName(coll(1))

この ...

coll.Add (Range("A1"))
Debug.Print coll(1); TypeName(coll(1))

... Value は Range のデフォルト プロパティであるため、両方とも debug.window の A1 にあるものを生成します。ただし、最初の例では「Range」の型が生成されますが、2 番目の例の型は A1 のデータ型です。つまり、1 つ目は範囲をコレクションに追加し、2 つ目は範囲の内容を追加します。

一方、これは機能します:

Dim coll As Collection
Set coll = New Collection
coll.Add ActiveSheet
Debug.Print coll(1).Name

...そしてこれはしません:

coll.Add (ActiveSheet)
Debug.Print coll(1).Name

ActiveSheet にはデフォルト プロパティがないためです。質問と同じように、実行時エラー 438 が表示されます。

于 2012-07-30T15:57:39.160 に答える
0

同じものを別の方法で見ると、次のようになります。

セル A1 に文字列 Hi! が含まれているとします。

Function SomeFunc(item1, item2)
    SomeFunc = 4
End Function

Sub Mac()
    ' here in both of the following two lines of code,
    '  item1 will be Variant/Object/Range, while item2 will be Variant/String:
    SomeFunc Range("A1"), (Range("A1"))
    Let i = SomeFunc(Range("A1"), (Range("A1")))

    'this following is a compile syntax error
    SomeFunc(Range("A1"), (Range("A1"))) 

    ' while here in both the following two lines of code, 
    '  item1 will be Variant/String while item2 will be Variant/Object/Range:
    SomeFunc ((Range("A1")), Range("A1")
    Let j = SomeFunc((Range("A1")), Range("A1"))

    'this following is a compile syntax error
    SomeFunc((Range("A1")), Range("A1"))

    Set r = Range("A1")       ' sets r to Variant/Object/Range
    Set r = (Range("A1"))     ' runtime error 13, type mismatch; cannot SET r (as reference) to string "Hi!" -- Strings are not objects in VBA
    Set r = Range("A1").Value ' runtime error (same)


    Let r = Range("A1")       ' set r to "Hi!" e.g. contents of A1 aka Range("A1").Value; conversion to value during let = assignment
    Let r = (Range("A1"))     ' set r to "Hi!" e.g. contents of A1 aka Range("A1").Value; conversion to value by extra ()'s
    Let r = Range("A1").Value ' set r to "Hi!" by explicit use of .Value 
End Sub

これは、混同される可能性のある 2 つのことが起こっていることを説明するために追加しただけです。

1つ目は、上記の他の回答で述べたように、項目をその Value プロパティに変換する式の () です。

2 つ目は、戻り値をキャプチャまたは使用する目的で呼び出された関数は、引数リスト全体を囲む余分な () を必要とするのに対し、戻り値をキャプチャまたは使用する意図なしに呼び出された関数 (またはサブルーチン) は、引数リストなしで (たとえば、ステートメントとして) 呼び出される必要があることです。引数リストを囲む同じ () 。これらの周囲の () は、.Value を使用して引数リストを変換しません。引数リストに 1 つのパラメーターしかない場合、この区別は特に混乱を招く可能性があります。

于 2012-07-31T01:23:47.823 に答える