Hash Table / Associative Array ใน VBA


90

ฉันไม่พบเอกสารอธิบายวิธีสร้างตารางแฮชหรืออาร์เรย์เชื่อมโยงใน VBA เป็นไปได้หรือไม่?

คุณสามารถเชื่อมโยงไปยังบทความหรือดีกว่าโพสต์รหัสได้หรือไม่



คำตอบ:


112

ฉันคิดว่าคุณกำลังมองหาวัตถุพจนานุกรมที่พบในไลบรารี Microsoft Scripting Runtime (เพิ่มการอ้างอิงถึงโครงการของคุณจากเมนูเครื่องมือ ... การอ้างอิงใน VBE)

มันใช้งานได้ดีกับค่าง่าย ๆ ที่สามารถใส่ในตัวแปรได้ (คีย์ไม่สามารถเป็นอาร์เรย์และการพยายามทำให้วัตถุเหล่านั้นไม่สมเหตุสมผลดูความคิดเห็นจาก @Nile ด้านล่าง):

Dim d As dictionary
Set d = New dictionary

d("x") = 42
d(42) = "forty-two"
d(CVErr(xlErrValue)) = "Excel #VALUE!"
Set d(101) = New Collection

คุณยังสามารถใช้ออบเจ็กต์ VBA Collection ได้หากความต้องการของคุณง่ายกว่าและคุณต้องการแค่คีย์สตริง

ฉันไม่รู้ว่าจริง ๆ แล้วแฮชอะไรหรือเปล่าดังนั้นคุณอาจต้องการค้นหาเพิ่มเติมหากคุณต้องการประสิทธิภาพที่เหมือนแฮชแท็ก (แก้ไข: Scripting.Dictionary ใช้ตารางแฮชภายใน)


ใช่ - พจนานุกรมคือคำตอบ ฉันพบคำตอบในไซต์นี้เช่นกัน stackoverflow.com/questions/915317/…
user158017

2
นั่นเป็นคำตอบที่ค่อนข้างดี: แต่กุญแจไม่เคยเป็นวัตถุ - สิ่งที่เกิดขึ้นจริงคือคุณสมบัติเริ่มต้นของวัตถุจะถูกส่งเป็นสตริงและใช้เป็นกุญแจ สิ่งนี้ใช้ไม่ได้หากวัตถุไม่มีคุณสมบัติเริ่มต้น (โดยปกติคือ 'ชื่อ') กำหนดไว้
Nigel Heffernan

@ ไนล์ขอบคุณ ฉันเห็นว่าคุณถูกต้องแน่นอน Emptyนอกจากนี้ยังดูเหมือนว่าถ้าวัตถุมีคุณสมบัติไม่มีการเริ่มต้นแล้วที่สำคัญพจนานุกรมที่สอดคล้องกันคือ ฉันแก้ไขคำตอบตามนั้น
jtolle

อธิบายโครงสร้างข้อมูลหลายอย่างที่นี่ - analystcave.com/… โพสต์นี้แสดงวิธีการใช้แฮชแท็ก. NEXT ใน Excel VBA- stackoverflow.com/questions/8677949/…
johny why

ลิงก์ด้านบนพิมพ์ผิด: .NET ไม่ใช่. NEXT
johny why


7

ลองใช้ Dictionary Object หรือ Collection Object

http://visualbasic.ittoolbox.com/documents/dictionary-object-vs-collection-object-12196


1
ลิงก์ที่ระบุใช้ไม่ได้อีกต่อไป สามารถดูเนื้อหาในขณะที่โพสต์ต้นฉบับได้ที่นี่: web.archive.org/web/20090729034340/http://…
Paul van Leeuwen

6

ไปเลย ... แค่คัดลอกโค้ดลงในโมดูลก็พร้อมใช้งาน

Private Type hashtable
    key As Variant
    value As Variant
End Type

Private GetErrMsg As String

Private Function CreateHashTable(htable() As hashtable) As Boolean
    GetErrMsg = ""
    On Error GoTo CreateErr
        ReDim htable(0)
        CreateHashTable = True
    Exit Function

CreateErr:
    CreateHashTable = False
    GetErrMsg = Err.Description
End Function

Private Function AddValue(htable() As hashtable, key As Variant, value As Variant) As Long
    GetErrMsg = ""
    On Error GoTo AddErr
        Dim idx As Long
        idx = UBound(htable) + 1

        Dim htVal As hashtable
        htVal.key = key
        htVal.value = value

        Dim i As Long
        For i = 1 To UBound(htable)
            If htable(i).key = key Then Err.Raise 9999, , "Key [" & CStr(key) & "] is not unique"
        Next i

        ReDim Preserve htable(idx)

        htable(idx) = htVal
        AddValue = idx
    Exit Function

AddErr:
    AddValue = 0
    GetErrMsg = Err.Description
End Function

Private Function RemoveValue(htable() As hashtable, key As Variant) As Boolean
    GetErrMsg = ""
    On Error GoTo RemoveErr

        Dim i As Long, idx As Long
        Dim htTemp() As hashtable
        idx = 0

        For i = 1 To UBound(htable)
            If htable(i).key <> key And IsEmpty(htable(i).key) = False Then
                ReDim Preserve htTemp(idx)
                AddValue htTemp, htable(i).key, htable(i).value
                idx = idx + 1
            End If
        Next i

        If UBound(htable) = UBound(htTemp) Then Err.Raise 9998, , "Key [" & CStr(key) & "] not found"

        htable = htTemp
        RemoveValue = True
    Exit Function

RemoveErr:
    RemoveValue = False
    GetErrMsg = Err.Description
End Function

Private Function GetValue(htable() As hashtable, key As Variant) As Variant
    GetErrMsg = ""
    On Error GoTo GetValueErr
        Dim found As Boolean
        found = False

        For i = 1 To UBound(htable)
            If htable(i).key = key And IsEmpty(htable(i).key) = False Then
                GetValue = htable(i).value
                Exit Function
            End If
        Next i
        Err.Raise 9997, , "Key [" & CStr(key) & "] not found"

    Exit Function

GetValueErr:
    GetValue = ""
    GetErrMsg = Err.Description
End Function

Private Function GetValueCount(htable() As hashtable) As Long
    GetErrMsg = ""
    On Error GoTo GetValueCountErr
        GetValueCount = UBound(htable)
    Exit Function

GetValueCountErr:
    GetValueCount = 0
    GetErrMsg = Err.Description
End Function

วิธีใช้ในแอป VB (A) ของคุณ:

Public Sub Test()
    Dim hashtbl() As hashtable
    Debug.Print "Create Hashtable: " & CreateHashTable(hashtbl)
    Debug.Print ""
    Debug.Print "ID Test   Add V1: " & AddValue(hashtbl, "Hallo_0", "Testwert 0")
    Debug.Print "ID Test   Add V2: " & AddValue(hashtbl, "Hallo_0", "Testwert 0")
    Debug.Print "ID Test 1 Add V1: " & AddValue(hashtbl, "Hallo.1", "Testwert 1")
    Debug.Print "ID Test 2 Add V1: " & AddValue(hashtbl, "Hallo-2", "Testwert 2")
    Debug.Print "ID Test 3 Add V1: " & AddValue(hashtbl, "Hallo 3", "Testwert 3")
    Debug.Print ""
    Debug.Print "Test 1 Removed V1: " & RemoveValue(hashtbl, "Hallo_1")
    Debug.Print "Test 1 Removed V2: " & RemoveValue(hashtbl, "Hallo_1")
    Debug.Print "Test 2 Removed V1: " & RemoveValue(hashtbl, "Hallo-2")
    Debug.Print ""
    Debug.Print "Value Test 3: " & CStr(GetValue(hashtbl, "Hallo 3"))
    Debug.Print "Value Test 1: " & CStr(GetValue(hashtbl, "Hallo_1"))
    Debug.Print ""
    Debug.Print "Hashtable Content:"

    For i = 1 To UBound(hashtbl)
        Debug.Print CStr(i) & ": " & CStr(hashtbl(i).key) & " - " & CStr(hashtbl(i).value)
    Next i

    Debug.Print ""
    Debug.Print "Count: " & CStr(GetValueCount(hashtbl))
End Sub

18
ฉันจะไม่ลงคะแนนผู้ใช้ใหม่ที่โพสต์โค้ด แต่โดยปกติแล้วการเรียกบางอย่างว่า "ตารางแฮช" หมายความว่าการใช้งานที่เป็นพื้นฐานนั้นเป็นตารางแฮชจริงๆ! สิ่งที่คุณมีอยู่ที่นี่คืออาร์เรย์เชื่อมโยงที่ใช้กับอาร์เรย์ปกติบวกการค้นหาเชิงเส้น ดูความแตกต่างได้ที่นี่: en.wikipedia.org/wiki/Hash_table
jtolle

7
แน่นอน. จุดของตารางแฮชคือ 'การแฮช' ของคีย์ที่นำไปสู่ตำแหน่งของค่าในที่จัดเก็บข้อมูลพื้นฐาน (หรืออย่างน้อยก็ใกล้พอในกรณีที่อนุญาตให้มีคีย์ซ้ำกัน) ดังนั้นจึงไม่จำเป็นต้องมีการค้นหาที่อาจมีค่าใช้จ่ายสูง
Cor_Blimey

4
ช้าเกินไปสำหรับแฮชแท็กขนาดใหญ่ การเพิ่ม 17,000 รายการใช้เวลามากกว่า 15 วินาที ฉันสามารถเพิ่ม 500,000 ภายใน 6 วินาทีโดยใช้พจนานุกรม 500,000 ในเวลาน้อยกว่า 3 วินาทีโดยใช้แฮชแท็ก mscorlib
Christopher Thomas Nicodemus
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.