VBA Excel 2010字典对象所需的错误

问题描述 投票:0回答:6

我正在尝试编写查看数组“arr”的代码,然后循环遍历该数组中的每个值以与新创建的字典进行比较。如果密钥已经存在,则密钥的值(计数)应该增加1,否则密钥应该添加值1。

但是,下面的行是抛出一个Object Required错误:

        If dic.Exists(c.Value) Then ' Runtime Error 424: Object Required

整个子目录如下:

Private Sub PODic()


    Dim arr As Variant
    Dim Counter As Long
    Dim dic As Object
    Dim lrow As Long
    Dim c As Variant


    Set dic = CreateObject("Scripting.Dictionary") ' late bind
        dic.CompareMode = vbTextCompare

    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With


    lrow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 4).End(xlUp).row
    lrow = lrow - 1
        Debug.Print lrow

    arr = ActiveSheet.Range("d2", ActiveSheet.Cells(lrow, "d")).Value

        For Each c In arr
            Debug.Print c
            If dic.Exists(c.Value) Then ' Runtime Error 424: Object Required
                dic(c.Value) = dic(c.Value) + 1
            Else
                dic.Add c.Value, 1
            End If
        Next

    For Each k In dic
        Debug.Print k & "," & dic(k)
    Next k



    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With

    MsgBox "Populate dictionary macro complete."



End Sub

我相信这可能与用于c的变量类型(或者可能是dic)有关,但我无法弄清楚问题出在哪里。我也尝试通过创建On Error GoTo来解决这个问题,但是遇到了同样的问题。

         On Error GoTo ERRINCVAL
            dic.Add cell.Value, 1
            On Error GoTo 0



ERRINCVAL:

    dic(c.Value) = dic(c.Value) + 1 ' Same error thrown on this line, if I try to use GoTo instead of If
    Resume Next

非常感谢帮助。

excel vba excel-vba dictionary
6个回答
0
投票

c.value在这里没有意义。 c这里是itemarray所以你可以直接参考它。

你应该这样试试......

For Each c In arr
    Debug.Print c
    If dic.Exists(c) Then
        dic(c) = dic(c) + 1
    Else
        dic.Add c, 1
    End If
Next

或者你也可以使用以下方法来获得所需的输出......

Dim i As Long
arr = ActiveSheet.Range("d2", ActiveSheet.Cells(lrow, "d")).Value

For i = 1 To UBound(arr, 1)
    Debug.Print arr(i, 1)
    If dic.Exists(arr(i, 1)) Then ' Runtime Error 424: Object Required
        dic(arr(i, 1)) = dic(arr(i, 1)) + 1
    Else
        dic.Add arr(i, 1), 1
    End If
Next

3
投票

@sktneer有正确的答案。我只是想展示一种更清晰的写作方式。

使用With语句可以使代码更具可读性并且更高效。

没有理由拥有Last Row变量。

范围(“D2”,单元格(Rows.Count,“D”)。结束(xlUp))。值

没有必要使用临时数组变量在For Each循环中使用。 VBA将在初始化循环时自动创建一个。

对于每个键入.Range(“D2”,。细胞(.Rows.Count,“D”)。结束(xlUp))。值

无需测试密钥是否存在,然后添加值为1的密钥或增加现有密钥。 VBA将自动创建它不存在的密钥。

dic(Key)= dic(Key)+ 1

添加键/值对或迭代字典时重用相同的Key变量。

dic.Add Key,1

对于dic中的每个键

您可以使用“连接”将所有键和项目打印到即时窗口。

Debug.Print“Keys:”;加入(dic.Keys(),“,”)

Debug.Print“Items:”;加入(dic.Items(),“,”)

Private Sub PODic()

    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With

    Dim dic As Object, Key As Variant

    Set dic = CreateObject("Scripting.Dictionary")
    dic.CompareMode = vbTextCompare

    With ActiveSheet
        For Each Key In .Range("D2", .Cells(.Rows.Count, "D").End(xlUp)).Value
            dic(Key) = dic(Key) + 1
        Next
    End With

    Debug.Print "Keys: "; Join(dic.Keys(), ",")
    Debug.Print "Items: "; Join(dic.Items(), ",")

    For Each Key In dic
        Debug.Print Key & "," & dic(Key)
    Next

    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With

    MsgBox "Populate dictionary macro complete."

End Sub

2
投票

您需要声明字典对象。

我们声明字典如下:

Dim dict As New Scripting.Dictionary

要么

Dim dict As Scripting.Dictionary
Set dict = New Scripting.Dictionary

有关在VBA at this site中设置和使用词典的更多信息。


另外,根据经验,在每个模块的顶部使用Option Explicit(特别是在排除故障时),以确保您的变量和对象都已正确设置。


1
投票

您可以使用简化的形式为字典赋值:

dic("key1") = dic("key1") + 1

0
投票

最终代码最终:

Private Sub PODic()

Dim arr As Variant
Dim Counter As Long

Dim lrow As Long
Dim c As Variant

Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary") ' late bind
    dic.CompareMode = vbTextCompare

With Application
    .ScreenUpdating = False
    .Calculation = xlCalculationManual
End With


lrow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 4).End(xlUp).row
lrow = lrow
    Debug.Print lrow

Dim i As Long
    arr = ActiveSheet.Range("d2", ActiveSheet.Cells(lrow, "d")).Value

For i = 1 To UBound(arr, 1)
    Debug.Print arr(i, 1)
    If dic.Exists(arr(i, 1)) Then
        dic(arr(i, 1)) = dic(arr(i, 1)) + 1
    Else
        dic.Add arr(i, 1), 1
    End If
Next

For Each k In dic
    Debug.Print k & "," & dic(k)
Next k
Debug.Print dic.Count


With Application
    .ScreenUpdating = True
    .Calculation = xlCalculationAutomatic
End With

结束子


-1
投票

使用c.value意味着你将它视为一个范围对象并访问它的'value'属性 - 你的代码将允许你这样做,因为c被声明为variant。

但是,我认为你正在做的是循环遍历数组中的每个元素 - 在这种情况下你不应该使用c.value,只能使用c。

我认为最好使用数组的ubound和lbound之间的for-next循环遍历数组。

所以尝试:

    Dim Index as Long

    For Index = lbound(arr,1) to ubound(arr,1)

If dic.Exists(arr(Index,1)) Then

' Array arr is 1-based but items in dic might be 0-based, so adjust if necessary'

dic(arr(Index-1,1)) = dic(arr(Index-1,1)) + 1
' if dic is not 0-based, get rid of the -1 above.'

Else

dic.Add arr(Index,1), 1

End If

    Next index

未经测试,写在手机上。

© www.soinside.com 2019 - 2024. All rights reserved.