19

現在の職場で大規模な VB6 アプリを継承しています。私は仕事でVB6を学んでいますが、いくつかの問題があります。現時点での主な問題は、Collection オブジェクトにキーが存在するかどうかを確認する方法がわからないことです。誰でも助けることができますか?

4

9 に答える 9

30

私の標準機能はとてもシンプルです。これは要素の種類に関係なく機能します。割り当てを行う必要がないため、コレクションプロパティgetを実行するだけです。

Public Function Exists(ByVal oCol As Collection, ByVal vKey As Variant) As Boolean

    On Error Resume Next
    oCol.Item vKey
    Exists = (Err.Number = 0)
    Err.Clear

End Function
于 2009-12-01T10:57:21.983 に答える
22

@Mark Biek あなたの keyExists は、私の標準の Exists() 関数とほぼ一致します。COM に公開されたコレクションと数値インデックスのチェックでこのクラスをより便利にするために、sKey と myCollection を型指定しないように変更することをお勧めします。関数がオブジェクトのコレクションで使用される場合は、'set' が必要です (val が設定されている行で)。

EDIT : オブジェクトベースと値ベースの Exists() 関数の要件が異なることに気付いていないことに悩まされていました。オブジェクト以外のコレクションを使用することはめったにありませんが、これは、存在を確認する必要があるときに追跡するのが非常に難しいバグの完璧なボトルネックのように思えました。エラー ハンドラーが既にアクティブな場合、エラー処理は失敗するため、新しいエラー スコープを取得するには 2 つの関数が必要です。Exists() 関数だけを呼び出す必要があります。

Public Function Exists(col, index) As Boolean
On Error GoTo ExistsTryNonObject
    Dim o As Object

    Set o = col(index)
    Exists = True
    Exit Function

ExistsTryNonObject:
    Exists = ExistsNonObject(col, index)
End Function

Private Function ExistsNonObject(col, index) As Boolean
On Error GoTo ExistsNonObjectErrorHandler
    Dim v As Variant

    v = col(index)
    ExistsNonObject = True
    Exit Function

ExistsNonObjectErrorHandler:
    ExistsNonObject = False
End Function

機能を確認するには:

Public Sub TestExists()
    Dim c As New Collection

    Dim b As New Class1

    c.Add "a string", "a"
    c.Add b, "b"

    Debug.Print "a", Exists(c, "a") ' True '
    Debug.Print "b", Exists(c, "b") ' True '
    Debug.Print "c", Exists(c, "c") ' False '
    Debug.Print 1, Exists(c, 1) ' True '
    Debug.Print 2, Exists(c, 2) ' True '
    Debug.Print 3, Exists(c, 3) ' False '
End Sub
于 2008-09-02T21:42:50.493 に答える
7

私はいつも次のような関数でそれを行ってきました:

public function keyExists(myCollection as collection, sKey as string) as Boolean
  on error goto handleerror:

  dim val as variant

  val = myCollection(sKey)
  keyExists = true
  exit sub
handleerror:
  keyExists = false
end function
于 2008-09-02T21:02:09.920 に答える
5

Thomasが指摘したように、Letではなくオブジェクトを設定する必要があります。これは、値とオブジェクトタイプに対して機能する私のライブラリの一般的な関数です。

Public Function Exists(ByVal key As Variant, ByRef col As Collection) As Boolean

'Returns True if item with key exists in collection

On Error Resume Next

Const ERR_OBJECT_TYPE As Long = 438
Dim item As Variant

'Try reach item by key
item = col.item(key)

'If no error occurred, key exists
If Err.Number = 0 Then
    Exists = True

'In cases where error 438 is thrown, it is likely that
'the item does exist, but is an object that cannot be Let
ElseIf Err.Number = ERR_OBJECT_TYPE Then

    'Try reach object by key
    Set item = col.item(key)

    'If an object was found, the key exists
    If Not item Is Nothing Then
        Exists = True
    End If

End If

Err.Clear

End Function

Thomasのアドバイスにもあるように、これを一般化するために、コレクションタイプをオブジェクトに変更できます。.Item(key)構文はほとんどのコレクションクラスで共有されているため、実際に役立つ場合があります。

編集私はトーマス自身によって幾分パンチに殴られたようです。ただし、再利用を容易にするために、私は個人的に、プライベートな依存関係のない単一の関数を好みます。

于 2008-09-02T22:29:36.370 に答える
3

コレクションにキーが存在しない場合にエラー ハンドラーを使用してケースをキャッチすると、「すべてのエラーで中断する」オプションを使用したデバッグが非常に煩わしくなります。不要なエラーを回避するために、コレクションに格納されたオブジェクトとディクショナリにすべてのキーを持つクラスを作成することがよくあります。Dictionary には exists(key) 関数があるため、コレクションからオブジェクトを取得する前にそれを呼び出すことができます。Dictionary には文字列しか格納できないため、オブジェクトを格納する必要がある場合は Collection が必要です。

于 2008-09-09T19:52:44.690 に答える
3

「エラー ハンドラが既にアクティブな場合、エラー処理は失敗する」という記述は部分的にしか正しくありません。

ルーチン内に複数のエラー ハンドラを含めることができます。
したがって、同じ機能を 1 つの関数だけに収めることができます。
コードを次のように書き換えるだけです。

Public Function Exists(col, index) As Boolean
Dim v As Variant

TryObject:
    On Error GoTo ExistsTryObject
        Set v = col(index)
        Exists = True
        Exit Function

TryNonObject:
    On Error GoTo ExistsTryNonObject

        v = col(index)
        Exists = True
        Exit Function

ExistsTryObject:
   ' This will reset your Err Handler
   Resume TryNonObject

ExistsTryNonObject:
        Exists = False
End Function

ただし、ルーチンの TryNonObject セクションにのみコードを組み込む場合は、同じ情報が得られます。
オブジェクトと非オブジェクトの両方で成功します。ただし、アイテムがコレクション内に存在することをアサートするために 1 つのステートメントを実行するだけでよいため、オブジェクト以外のコードの速度が向上します。

于 2012-03-02T14:49:48.273 に答える
2

http://www.visualbasic.happycodings.com/Other/code10.htmlを参照 してください。 ここでの実装には、オプションで見つかった要素を返すという利点もあり、(コメントによると) オブジェクト/ネイティブ型で動作します。

リンクが利用できなくなったため、ここに再現します。

コレクションに項目が存在するかどうかを判断する

次のコードは、アイテムがコレクション内に存在するかどうかを判断する方法を示しています。

Option Explicit

'Purpose     :  Determines if an item already exists in a collection
'Inputs      :  oCollection         The collection to test for the existance of the item
'               vIndex              The index of the item.
'               [vItem]             See Outputs
'Outputs     :  Returns True if the item already exists in the collection.
'               [vItem] The value of the item, if it exists, else returns "empty".
'Notes       :
'Example     :

Function CollectionItemExists(vIndex As Variant, oCollection As Collection, Optional vItem As Variant) As Boolean
    On Error GoTo ErrNotExist

    'Clear output result
    If IsObject(vItem) Then
        Set vItem = Nothing
    Else
        vItem = Empty
    End If

    If VarType(vIndex) = vbString Then
        'Test if item exists
        If VarType(oCollection.Item(CStr(vIndex))) = vbObject Then
            'Return an object
            Set vItem = oCollection.Item(CStr(vIndex))
        Else
            'Return an standard variable
            vItem = oCollection.Item(CStr(vIndex))
        End If
    Else
        'Test if item exists
        If VarType(oCollection.Item(Int(vIndex))) = vbObject Then
            'Return an object
            Set vItem = oCollection.Item(Int(vIndex))
        Else
            'Return an standard variable
            vItem = oCollection.Item(Int(vIndex))
        End If
    End If
    'Return success
    CollectionItemExists = True
    Exit Function
ErrNotExist:
    CollectionItemExists = False
    On Error GoTo 0
End Function

'Demonstration routine
Sub Test()
    Dim oColl As New Collection, oValue As Variant

    oColl.Add "red1", "KEYA"
    oColl.Add "red2", "KEYB"
    'Return the two items in the collection
    Debug.Print CollectionItemExists("KEYA", oColl, oValue)
    Debug.Print "Returned: " & oValue
    Debug.Print "-----------"
    Debug.Print CollectionItemExists(2, oColl, oValue)
    Debug.Print "Returned: " & oValue
    'Should fail
    Debug.Print CollectionItemExists("KEYC", oColl, oValue)
    Debug.Print "Returned: " & oValue
    Set oColl = Nothing
End Sub
于 2009-12-01T10:50:45.630 に答える
2

より良い解決策は、TryGet 関数を作成することです。多くの場合、存在を確認してからアイテムを取得します。同時に行うことで時間を節約できます。

public Function TryGet(key as string, col as collection) as Variant
  on error goto errhandler
  Set TryGet= col(key)
  exit function
errhandler:
  Set TryGet = nothing  
end function
于 2009-05-19T14:39:53.200 に答える
0

このような機能を探しながら、次のように設計しました。これは、新しい変数を割り当てることなく、オブジェクトと非オブジェクトで機能するはずです。

Public Function Exists(ByRef Col As Collection, ByVal Key) As Boolean
    On Error GoTo KeyError
    If Not Col(Key) Is Nothing Then
        Exists = True
    Else
        Exists = False
    End If

    Exit Function
KeyError:
    Err.Clear
    Exists = False
End Function
于 2013-03-05T10:22:35.917 に答える