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

时间:2017-12-30 05:13:19

标签: excel vba excel-vba dictionary

我正在尝试编写查看数组“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

非常感谢。

6 个答案:

答案 0 :(得分: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

在添加键/值对或迭代词典时重复使用相同的变量。

  

dic.Add Key,1

     

对于dic中的每个键

您可以使用加入将所有打印到即时窗口。

  

Debug.Print" Keys:&#34 ;;加入(dic.Keys(),",")

     

Debug.Print" Items:&#34 ;;加入(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

答案 1 :(得分:2)

您需要声明字典对象。

  

我们声明字典如下

Dim dict As New Scripting.Dictionary
     

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

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

c.value在这里没有意义。 c item array 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

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

import javax.swing.*;
import java.awt.*;

public class GridBagTest {

    private static JFrame myFrame;
    private static JPanel mainPanel;

    public static void main(String[] args) {
        createFrame();
        createPanels();
        constructCells();
        myFrame.pack();
        myFrame.setVisible(true);
    }

    private static void createFrame() {
        myFrame = new JFrame();
        myFrame.setPreferredSize(new Dimension(800, 800));
        myFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        myFrame.setTitle("Simulator");
        myFrame.setResizable(true);
    }

    private static void createPanels() {
        mainPanel = new JPanel(new BorderLayout(10, 10));
        myFrame.getContentPane().add(mainPanel);
    }

    private static void constructCells() {
        for (int i = 0; i < 3; i++) {
            mainPanel.add(new Cell(i + 1), choosePosition(i + 1));
        }
    }

    private static String choosePosition(int number) {
        switch (number) {
            case 1:
                return BorderLayout.EAST;
            case 2:
                return BorderLayout.CENTER;
            case 3:
                return BorderLayout.WEST;
        }
        return null;
    }
}

答案 4 :(得分: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

End Sub

答案 5 :(得分:-1)

使用c.value意味着您将其视为范围对象并访问其“值”属性 - 您的代码将允许您将其作为c声明为变体。

但是,我认为你正在做的是循环遍历数组中的每个元素 - 在这种情况下你不应该使用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

未经测试,写在手机上。