現在の職場で大規模な VB6 アプリを継承しています。私は仕事でVB6を学んでいますが、いくつかの問題があります。現時点での主な問題は、Collection オブジェクトにキーが存在するかどうかを確認する方法がわからないことです。誰でも助けることができますか?
9 に答える
私の標準機能はとてもシンプルです。これは要素の種類に関係なく機能します。割り当てを行う必要がないため、コレクションプロパティ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
@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
私はいつも次のような関数でそれを行ってきました:
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
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)構文はほとんどのコレクションクラスで共有されているため、実際に役立つ場合があります。
編集私はトーマス自身によって幾分パンチに殴られたようです。ただし、再利用を容易にするために、私は個人的に、プライベートな依存関係のない単一の関数を好みます。
コレクションにキーが存在しない場合にエラー ハンドラーを使用してケースをキャッチすると、「すべてのエラーで中断する」オプションを使用したデバッグが非常に煩わしくなります。不要なエラーを回避するために、コレクションに格納されたオブジェクトとディクショナリにすべてのキーを持つクラスを作成することがよくあります。Dictionary には exists(key) 関数があるため、コレクションからオブジェクトを取得する前にそれを呼び出すことができます。Dictionary には文字列しか格納できないため、オブジェクトを格納する必要がある場合は Collection が必要です。
「エラー ハンドラが既にアクティブな場合、エラー処理は失敗する」という記述は部分的にしか正しくありません。
ルーチン内に複数のエラー ハンドラを含めることができます。
したがって、同じ機能を 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 つのステートメントを実行するだけでよいため、オブジェクト以外のコードの速度が向上します。
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
より良い解決策は、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
このような機能を探しながら、次のように設計しました。これは、新しい変数を割り当てることなく、オブジェクトと非オブジェクトで機能するはずです。
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