Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在字典中为唯一值的2D数组设置字典?_Arrays_Vba_Excel_Dictionary - Fatal编程技术网

Arrays 如何在字典中为唯一值的2D数组设置字典?

Arrays 如何在字典中为唯一值的2D数组设置字典?,arrays,vba,excel,dictionary,Arrays,Vba,Excel,Dictionary,我试图得到唯一的国家名称以及该特定国家的任何独特水果(类似于下表)。我尝试使用2D数组,但它变得复杂了 最终结果是计划将国家放在一个组合框中,当选择该组合框时,第二个组合框将填充水果 我看到有人在字典里推荐一本字典,但我很难理解这个概念。我尝试了多种方法来设置文本词典,但我一直得到一个参数非可选或对象必需错误。我只是把语法弄错了,还是我所做的事情有根本性的问题 编辑 如果有人尝试这样做,我意识到将文本连接在一起,然后在需要时将它们拆分成一个数组要容易得多。见下文: Dim Arr As Va

我试图得到唯一的国家名称以及该特定国家的任何独特水果(类似于下表)。我尝试使用2D数组,但它变得复杂了

最终结果是计划将国家放在一个组合框中,当选择该组合框时,第二个组合框将填充水果

我看到有人在字典里推荐一本字典,但我很难理解这个概念。我尝试了多种方法来设置文本词典,但我一直得到一个
参数非可选
对象必需
错误。我只是把语法弄错了,还是我所做的事情有根本性的问题

编辑
如果有人尝试这样做,我意识到将文本连接在一起,然后在需要时将它们拆分成一个数组要容易得多。见下文:

Dim Arr As Variant
Dim rng1 As Range
Dim rng2 As Range
Dim newRng As Range
Dim name As String
Dim text As String
Dim j As Long
Dim i As Long
Dim dcName As Scripting.Dictionary

Set dcName = New Scripting.Dictionary
Set rng1 = tbl.ListColumns("Name1").DataBodyRange
Set rng2 = tbl.ListColumns("Name5 Text").DataBodyRange
Set newRng = Range(rng1, rng2)

Arr = newRng

For i = 1 To 10 Step 2
    For j = LBound(Arr) To UBound(Arr)
        name = Arr(j, i)
        text = Arr(j, i + 1)
        If name <> vbNullString Then
            dcName(name) = dcName(name) & "|" & text
        End If
    Next j
Next i

ReDim arrSort(0 To dcName.Count - 1, 0 To 1)
For Key = 0 To dcName.Count - 1
    arrSort(Key, 0) = dcName.Keys(Key)
    arrSort(Key, 1) = dcName.Items(Key)
Next Key

For i = LBound(arrSort) To UBound(arrSort) - 1
    For j = i + 1 To UBound(arrSort)
        If UCase(arrSort(i, 0)) > UCase(arrSort(j, 0)) Then
            tempName = arrSort(j, 0)
            tempText = arrSort(j, 1)
            arrSort(j, 0) = arrSort(i, 0)
            arrSort(j, 1) = arrSort(i, 1)
            arrSort(i, 0) = tempName
            arrSort(i, 1) = tempText
        End If
    Next j
Next i

Me.cbName.List = arrSort
Dim Arr作为变型
变暗rng1 As范围
变暗rng2 As范围
变暗新RNG As范围
将名称设置为字符串
将文本变暗为字符串
Dim j尽可能长
我想我会坚持多久
将dcName设置为Scripting.Dictionary
Set dcName=New Scripting.Dictionary
设置rng1=tbl.ListColumns(“Name1”).DataBodyRange
设置rng2=tbl.ListColumns(“Name5 Text”).DataBodyRange
设置新RNG=范围(rng1、rng2)
Arr=newRng
对于i=1到10,步骤2
对于j=LBound(Arr)至UBound(Arr)
name=Arr(j,i)
text=Arr(j,i+1)
如果名称为vbNullString,则
dcName(名称)=dcName(名称)&“|”&文本
如果结束
下一个j
接下来我
ReDim arrSort(0到dcName.Count-1,0到1)
对于dcName.Count-1的Key=0
arrSort(键,0)=dcName.Keys(键)
arrSort(键,1)=dcName.Items(键)
下一键
对于i=LBound(arrSort)到UBound(arrSort)-1
对于j=i+1至uBond(arrSort)
如果UCase(arrSort(i,0))>UCase(arrSort(j,0)),那么
tempName=arrSort(j,0)
TENTEXT=arrSort(j,1)
arrSort(j,0)=arrSort(i,0)
arrSort(j,1)=arrSort(i,1)
arrSort(i,0)=临时名称
arrSort(i,1)=EXT
如果结束
下一个j
接下来我
Me.cbName.List=arrSort
然后,您可以将文本值拆分为一个数组,并用它填充一个组合框。比我想象的容易多了

Private Sub cbName1_Change()
    Dim i As Integer
    Dim selName As String
    Dim arrText As Variant

    Me.cbName1Text.Clear
    selIndex = Me.cbName1.ListIndex

    text = arrSort(selIndex, 1)
    arrText = Split(text, "|")

    For i = LBound(arrText) To UBound(arrText)
        If arrText(i) <> vbNullString Then
            Me.cbName1Text.AddItem arrText(i)
        End If
    Next i

End Sub  
Private Sub cbName1_Change()
作为整数的Dim i
将selName设置为字符串
以文本作为变体
Me.cbName1Text.Clear
selIndex=Me.cbName1.ListIndex
text=arrSort(selIndex,1)
arrText=拆分(文本“|”)
对于i=LBound(arrText)到UBound(arrText)
如果arrText(i)vbNullString,则
Me.cbName1Text.AddItem arrText(i)
如果结束
接下来我
端接头
以前尝试在字典中使用字典的工作
根据评论编辑

Sub GetAbilities()
Dim Arr As Variant
Dim rng1 As Range
Dim rng2 As Range
Dim newRng As Range
Dim name As Variant
Dim text As Variant

Dim dcName As Scripting.Dictionary
Dim dcText As Scripting.Dictionary
Set dcName = New Scripting.Dictionary
Set dcText = New Scripting.Dictionary

Set rng1 = tbl.ListColumns("Name1").DataBodyRange
Set rng2 = tbl.ListColumns("Text3").DataBodyRange
Set newRng = Range(rng1, rng2)

Arr = newRng
counter = 0

For j = 1 To 10 Step 2
    For i = LBound(Arr) To UBound(Arr)
        name = Arr(i, j)
        text = Arr(i, j + 1)

        If dcName.Exists(name) Then
            If Not dcText.Exists(text) Then
                dcText.Add text, counter
            End If
        Else
        Set dcText = CreateObject("Scripting.Dictionary")
            dcName.Add name, dcText
            If text <> vbNullString Then
                dcText.Add text, counter
            End If
        End If
        counter = counter + 1
    Next i
Next j

For Each n In dcName.Keys
    For Each t In dcName.item(n).Keys
        Debug.Print n, t
    Next t
Next n

End Sub
Sub-GetAbilities()
作为变体的Dim-Arr
变暗rng1 As范围
变暗rng2 As范围
变暗新RNG As范围
作为变体的Dim名称
变暗文本作为变体
将dcName设置为Scripting.Dictionary
将dcText设置为脚本。字典
Set dcName=New Scripting.Dictionary
Set dcText=New Scripting.Dictionary
设置rng1=tbl.ListColumns(“Name1”).DataBodyRange
设置rng2=tbl.ListColumns(“Text3”).DataBodyRange
设置新RNG=范围(rng1、rng2)
Arr=newRng
计数器=0
对于j=1到10,步骤2
对于i=LBound(Arr)到UBound(Arr)
name=Arr(i,j)
text=Arr(i,j+1)
如果dcName.存在(名称),则
如果dcText.不存在(文本),则
添加文本,计数器
如果结束
其他的
设置dcText=CreateObject(“Scripting.Dictionary”)
dcName.addname,dcText
如果文本为空字符串,则
添加文本,计数器
如果结束
如果结束
计数器=计数器+1
接下来我
下一个j
对于dcName.Keys中的每个n
对于dcName.item(n.Keys)中的每个t
调试。打印n,t
下一个t
下一个
端接头

您可以使用嵌套字典,但它需要更多的工作,因此您选择了正确的路径,将字符串作为字典项进行拆分和连接(嵌套字典对于大量数据更有效)

下面的解决方案只使用一个字典。我尝试复制您的设置,但不确定您的工作表名称和表名,因此我使用了Sheet1和Table1,如下图所示


活页1模块



通用模块(模块1)


"


GetUniques()
中,行
fullRng=tbl.DataBodyRange
将所有表数据获取到二维变量数组中:

GetUniques()
中的第一个For循环设置初始字典(未排序):

第二个用于排序每个键的项,类似于最终结果:

注:这不包括没有任何水果的国家


示例:

这将使用嵌套字典

在用户表单代码窗格中放置以下内容:

Option Explicit

Dim dict As Scripting.Dictionary ' this will have 'dict' Dictionary accessible from all UserForm Subs/Functions and throughout its life

' change "ComboBox1" to your actual "Countries" combobox name and "ComboBox2" to your actual "Fruits" combobox name
Private Sub ComboBox1_Change() 
    Me.ComboBox2.List = dict(Me.ComboBox1.Value).Keys 
End Sub

Private Sub UserForm_Initialize()
    Me.ComboBox1.List = GetCountries(dict) ' fill combobox countries with countries names
End Sub
将以下内容放入任何模块中

Function GetCountries(dict As Scripting.Dictionary)
    Dim row As Range
    Dim j As Long
    Dim name As String, fruit As String

    Set dict = New Scripting.Dictionary 'change "Table1" to your actual table name and "mySheetName" to your actual table sheet name
    With Worksheets("mySheetName").ListObjects("Table1")
        For Each row In .DataBodyRange.Rows
            For j = 1 To .DataBodyRange.Columns.Count Step 2
                name = .DataBodyRange(row.row - 1, j).Value
                fruit = .DataBodyRange(row.row - 1, j + 1).Value
                If name <> "" Then
                    If Not dict.Exists(name) Then dict.Add name, New Scripting.Dictionary
                    If fruit <> "" Then dict(name)(fruit) = 1
                End If
            Next
        Next
    End With

    If dict.Count > 0 Then GetCountries = dict.Keys
End Function
函数GetCountries(dict As Scripting.Dictionary) 暗行作为范围 Dim j尽可能长 暗名称为字符串,水果为字符串 设置dict=New Scripting.Dictionary将“Table1”更改为实际表名,将“mySheetName”更改为实际表名 使用工作表(“mySheetName”).ListObjects(“表1”) 对于.DataBodyRange.Rows中的每一行 对于j=1到.DataBodyRange.Columns.Count步骤2 name=.DataBodyRange(row.row-1,j).Value 水果=.DataBodyRange(row.row-1,j+1).Value 如果名称为“”,则 如果不存在dict.Exists(name),则dict.Add name,New Scripting.Dictionary 如果水果为“”,则dict(名称)(水果)=1 如果结束 下一个 下一个 以 如果dict.Count>0,则GetCountries=dict.Keys 端函数
您需要指定一个键和值,因此dcText.Add text(沿右行)只添加一个键,而不添加任何值,因此会添加参数
Public Function BubbleSortStrItems(ByRef itms As String, ByVal sep As String) As String
    Dim vArr As Variant, i As Long, tmp As String, vArrMax As Long

    If Len(itms) > 0 And Len(sep) > 0 Then
        vArr = Split(itms, sep)
        vArrMax = UBound(vArr)
        If vArrMax > 0 Then
            For i = 0 To vArrMax - 1
                If vArr(i) > vArr(i + 1) Then
                    tmp = vArr(i)
                    vArr(i) = vArr(i + 1)
                    vArr(i + 1) = tmp
                End If
            Next i
        End If
    End If
    BubbleSortStrItems = Join(vArr, sep)
End Function
Option Explicit

Dim dict As Scripting.Dictionary ' this will have 'dict' Dictionary accessible from all UserForm Subs/Functions and throughout its life

' change "ComboBox1" to your actual "Countries" combobox name and "ComboBox2" to your actual "Fruits" combobox name
Private Sub ComboBox1_Change() 
    Me.ComboBox2.List = dict(Me.ComboBox1.Value).Keys 
End Sub

Private Sub UserForm_Initialize()
    Me.ComboBox1.List = GetCountries(dict) ' fill combobox countries with countries names
End Sub
Function GetCountries(dict As Scripting.Dictionary)
    Dim row As Range
    Dim j As Long
    Dim name As String, fruit As String

    Set dict = New Scripting.Dictionary 'change "Table1" to your actual table name and "mySheetName" to your actual table sheet name
    With Worksheets("mySheetName").ListObjects("Table1")
        For Each row In .DataBodyRange.Rows
            For j = 1 To .DataBodyRange.Columns.Count Step 2
                name = .DataBodyRange(row.row - 1, j).Value
                fruit = .DataBodyRange(row.row - 1, j + 1).Value
                If name <> "" Then
                    If Not dict.Exists(name) Then dict.Add name, New Scripting.Dictionary
                    If fruit <> "" Then dict(name)(fruit) = 1
                End If
            Next
        Next
    End With

    If dict.Count > 0 Then GetCountries = dict.Keys
End Function