【问题标题】:Object Defined error in Excel VBA scriptExcel VBA 脚本中的对象定义错误
【发布时间】:2015-05-01 04:25:47
【问题描述】:

我正在尝试构建一个脚本来提取列的前 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

【问题讨论】:

  • 我没有看到任何* 哪一行给你带来麻烦?
  • @Brad 抱歉,关于那个。我编辑了脚本以显示星号。除了我注释掉它的方式之外,我想不出其他方法来处理它。我想如果我能解决这部分问题,我可以处理为其他 3 个布尔值编写代码。

标签: vba excel excel-2013


【解决方案1】:

sht 很可能为空。

Dim sht as Worksheet 但永远不会 Set 它对任何东西。您的错误行是使用sht 的第一行,因此它恰好是引起您注意的错误。

我想你会想将它设置为与dest 范围关联的工作表。

set sht = dest.Worksheet

在处理cols 时,您需要小心不要重用该变量(您可能会考虑重命名这些变量以更明确地说明它们在做什么,但这是另一回事)。在您设置destrng 的方式中,不能保证它们来自同一张表,这在设置colcols 时会导致问题。如果您尝试用不同工作表上的单元格组成范围,则会出现异常。

【讨论】:

  • 感谢您提供的信息。老实说,我并不完全理解所有这些,但我会继续重读直到我明白为止。我添加了 set sht = dest.worksheet ,它让我超越了我被困住的地方。现在它在最后一部分给了我一个错误: For Each c In col.Cells c.Value = Left(Cells(i, cols.column), 6) Next c 你知道为什么我不能使用那种语法吗?我将 cols 设置为一个范围,并选择 i 和范围 cols 的列数,对吗?或者我可能误解了。
  • 语法看起来不错...您是否使用调试器查看过cols.column 的值?它指向哪张纸?使用 Locals 和 Watch 窗口了解变量的值。请记住,Cells 在不引用工作表的情况下使用(例如:Sheets(1).Cells(i,cols.Column) 将引用 Activesheet 中的范围。使用完全限定引用来解决此问题。每个范围对象(Range 或 @987654336 @) 是工作表的子对象。您希望尽可能明确地说明哪个工作表是父工作表。不要让 Excel 为您决定。
  • @flwr_pwr 这是我所说的“您设置 dest 和 rng 的方式不能保证它们来自同一张纸,这在设置 col 与 cols 时会导致问题”的示例: Set dest = Sheets(1).Range(Sheets(2).Cells(1, 1), Sheets(1).Cells(2, 3)) 这将抛出异常“应用程序定义或对象定义错误”。该错误是有道理的,因为您尝试从两个不同工作表上的单元格中组合 1 个连续范围。这样做并不合乎逻辑。
  • 非常感谢您的解释!我现在真的明白你的意思了,我现在明白了 .Parent 功能。在调试代码时,我现在正在查看 Local 和 Watch 窗口。希望这将提供一些关于它为什么出错的见解!
【解决方案2】:

在相关说明中,您可以使用 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

【讨论】:

  • 有趣。我尝试使用您提供的方法;但是,插入新列后,宏似乎没有做任何事情。您对为什么会这样有任何想法吗?我已经更新了原始帖子中的代码
  • @flwr_pwr - 我已将 sn-p 添加到完整更新的代码中
  • 效果很好!非常感谢。非常有效率。如果您不介意,您能否解释一下这部分代码:'FieldInfo:=Array(Array(0, 1), Array(6, 9))' 我只问是因为我还必须重新创建要拉取的函数范围的 Mid(7,4) 也是如此,我想使用相同的方法。不幸的是,在浏览完您提供的语法字符串之后,它超出了我的想象。
  • 我包含了一个指向TextToColumn method 官方文档的链接。如果您对某个概念有疑问,为什么不从那里开始并提出具体问题?
  • 会的。感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多