Excel VBA 脚本中的对象定义错误

Object Defined error in Excel VBA script

我正在尝试构建一个脚本来提取列(用户定义)的前 6 个字符,然后插入一个新列并粘贴这些结果,或者只是将这些结果粘贴到一个已经存在的列上(用户的选择)但我不断收到对象定义错误(我在代码中用星号标记了该行)。

谁能告诉我我做错了什么?这是我的代码

 Sub AAC_Extract()
    Dim rng As Range, col As Range, arr
    Dim sht As Worksheet, shet As Worksheet

    On Error Resume Next
    Set rng = Application.InputBox( _
                Prompt:="Please select the column that contains the Standard Document Number. " & vbNewLine & _
                        " (e.g. Column A or Column B)", _
                Title:="Select Document Number Range", Type:=8)
    On Error GoTo 0
    hdr = MsgBox("Does your selection contain a header?", vbYesNo + vbQuestion, "Header Option")

    Set dest = Application.InputBox( _
                Prompt:="Please select the column that you would the AAC to be placed in. " & vbNewLine & _
                        " (e.g. Column B or Column C)", _
                Title:="Select Destination Range", Type:=8)

     If dest Is Nothing Then Exit Sub
     Set sht = dest.Worksheet
     Set shet = rng.Worksheet
    'If dest = rng Then
    '    MsgBox "Your Destination Range can not be the same as your Reference Range.  Please choose a valid Destination Range", vbExclamation
    '    Exit Sub
    'End If


     On Error GoTo 0
     yn = MsgBox("Do you want to insert a new column here?" & vbNewLine & _
                        "(Choosing 'No' will replace the current cells in your selected range." & vbNewLine & "All data in this range will be permanently deleted.)", vbYesNo + vbQuestion, "Destination Range Options")


    LastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row

    Application.ScreenUpdating = False
    If hdr = vbYes And yn = vbYes Then
        dest.Select
        With Selection
        .EntireColumn.Insert
        End With
        Set col = sht.Range(sht.Cells(2, dest.Column), _
                        sht.Cells(sht.Rows.Count, dest.Column).End(xlUp))
        Set cols = shet.Range(shet.Cells(2, rng.Column), _
                        shet.Cells(shet.Rows.Count, rng.Column).End(xlUp))
        'Columns = cols.Column
        'dest.EntireColumn.Insert
        'col = dest.Column
        'cols = rng.Column
        'For i = 1 To LastRow
        'Cells(i, col).Value = Left(Cells(i, cols), 6)
        'Next i
        'For Each c In col.Cells.Offset(0, -1) 'Offset due to the fact that dest moved when a column was inserted
        '    i = c.Row
        '    c.Value = Left(cols.Cells(i - 1), 6) 'Honestly, I'm not sure why I have to subtract 1 from i....i should be the same row as c
        'Next c
        With col
        .Value2 = cols.Value2
        .TextToColumns Destination:=.Cells, DataType:=xlFixedWidth, _
        FieldInfo:=Array(Array(0, 1), Array(6, 9))
        End With
    End If

End Sub

很可能 sht 为空。

Dim sht as Worksheet 但从来没有 Set 它对任何东西。您的错误行是使用 sht 的第一行,因此它恰好是引起您注意错误的地方。

我认为您可能希望将其设置为与 dest 范围关联的 sheet。

set sht = dest.Worksheet

尽管如此,您在处理 cols 时需要注意不要重用该变量(您可能会考虑重命名这些变量以更明确地说明它们在做什么,但这是另一回事)。在您设置 destrng 的方式中,不能保证它们来自同一个 sheet,这在设置 colcols 时会导致问题。如果您尝试用不同 sheets.

上的单元格组成一个范围,则会出现异常

在相关说明中,您可以使用 VBA 的 TextToColumn method 快速将最左边的六个字符放入整列,选择第一个字段的宽度为 6 并丢弃任何其他字段。对于长列的值,这应该比循环和提取每个单元格的前六个字符有明显的不同。

在您提供的代码的底部附近,您有以下循环。

    For Each c In col.Cells
        c.Value = Left(Cells(i, cols), 6)
    Next c

这似乎将 col 定义为源列 cols 前六个字符的目标。您遍历每个单元格并剥离前六个字符。

With col
    .Value2 = cols.Value2
    .TextToColumns Destination:=.Cells, DataType:=xlFixedWidth, _
      FieldInfo:=Array(Array(0, 1), Array(6, 9))
End With

这会将值从 cols 转移到 col,然后一次性删除第六个字符之后的所有内容。

对于少于几百个值,我不知道我是否会费心重写,但效率会提高您必须处理的更多行值。

代码段实现:

Sub AAC_Extract()
    Dim rng As Range, col As Range, cols As Range, arr
    Dim sht As Worksheet, shet As Worksheet, hdr As Long, yn As Long, LastRow As Long
    Dim dest As Range

    On Error Resume Next
    Set rng = Application.InputBox( _
                Prompt:="Please select the column that contains the Standard Document Number. " & vbNewLine & _
                        " (e.g. Column A or Column B)", _
                Title:="Select Document Number Range", Type:=8)
    On Error GoTo 0
    hdr = MsgBox("Does your selection contain a header?", vbYesNo + vbQuestion, "Header Option")

    Set dest = Application.InputBox( _
                Prompt:="Please select the column that you would the AAC to be placed in. " & vbNewLine & _
                        " (e.g. Column B or Column C)", _
                Title:="Select Destination Range", Type:=8)

     If dest Is Nothing Then Exit Sub
     Set sht = dest.Parent
     Set shet = rng.Parent

     On Error GoTo 0
     yn = MsgBox("Do you want to insert a new column here?" & vbNewLine & _
                 "(Choosing 'No' will replace the current cells in your selected range." & vbNewLine & _
                 "All data in this range will be permanently deleted.)", vbYesNo + vbQuestion, "Destination Range Options")


    LastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row

    Application.ScreenUpdating = False
    If yn = vbYes Then
        dest.EntireColumn.Insert
        Set dest = dest.Offset(0, -1)
    End If

    'I'm not sure about this because the next set starts in row 2 regardless
    'If hdr = vbYes Then
    '    Set dest = dest.Resize(dest.Rows.Count - 1, 1)
    'End If

    Set cols = shet.Range(shet.Cells(2, rng.Column), _
                    shet.Cells(shet.Rows.Count, rng.Column).End(xlUp))
    Set col = sht.Cells(2, dest.Column).Resize(cols.Rows.Count, 1)

    With col
        .Value2 = cols.Value2
        .TextToColumns Destination:=.Cells, DataType:=xlFixedWidth, _
          FieldInfo:=Array(Array(0, 1), Array(6, 9))
    End With

End Sub