在Excel中使用VBA时,如果没有对象,则会抛出“对象变量或With块变量未设置”的错误。

22

在我的代码中,我声明了这些变量:

Dim Field_Name, Datatype, row As Integer

然后,在一个 For 循环内,我有这段代码:

Field_Name = Worksheets(i).UsedRange.Find("Field Name").Column
Datatype = Worksheets(i).UsedRange.Find("Datatype").Column
row = Worksheets(i).UsedRange.Find("Field Name").row + 1

然而,该代码会引发“对象变量或块变量未设置”运行时错误。根据API,Range.Column和Range.row属性是只读的Long型。我尝试将变量的数据类型更改为Long,但没有成功。似乎VBA希望我做什么

Set Field_Name = Worksheets(i).UsedRange.Find("Field Name").Column
Set Datatype = Worksheets(i).UsedRange.Find("Datatype").Column
Set row = Worksheets(i).UsedRange.Find("Field Name").row + 1

然而,这些变量并不是对象,因此这样做会抛出“需要对象”编译错误。

如果您不确定如何修复它,则任何解决方法或替代方法来获取单元格的列号和行号都将非常感激。


1
将您的“Dim”更改为三个Dim,每个Dim仅有一个变量名称和类型。然后再试一次。如果仍有错误,请问它在哪一行?参考:http://msdn.microsoft.com/en-us/library/office/gg264241(v=office.15).aspx - Wayne G. Dunn
7
你的错误最有可能是因为 Find 返回了 Nothing,也就是字符串 "Field Name" 或者 "Datatype" 没有被找到。 - Dmitry Pavliv
很好能看到你的其余代码,因为有时候“未关闭”的循环或with语句可能会导致这种错误。但我同意simoco的观点,你的Find可能什么都没找到。 - Ron Rosenfeld
另一个批评意见:Dim Field_Name,Datatype,row As Integer只声明'row'为整数类型;其他两个将是Variant类型。请查看帮助以获取有关Dim语句的信息。 - Ron Rosenfeld
1
如果你被一个普遍的“对象变量或块变量未设置”问题困扰(因为这是该错误的第一个Google SE结果)……请确保在变量接收之前,将单词SET放在出现错误的行的最前面。7yphoid确实做到了这一点,但很可能这是你的错误……因为混淆/神秘的警告通常表明你正在尝试分配类似值的引用(=在Excel中不像许多语言那样可互换)。你正在传递“directions”,而不是一个值。 - JeopardyTempest
显示剩余2条评论
4个回答

20
尽管这是一个老问题,但我也想说一些话。
在使用.Find方法时,我遇到了同样的问题。我来到这个问题,其他人也会这样做。
我找到了一个简单的解决方案:
Find没有找到指定的字符串时,它会返回Nothing。在直接调用Find之后调用任何东西都会导致此错误。因此,您的.Column.row将引发错误。
在我的情况下,我希望找到单元格的Offset并以此方式解决了它:
Set result = Worksheets(i).Range("A:A").Find(string)
    If result Is Nothing Then
        'some code here
    ElseIf IsEmpty(result.Offset(0, 2)) Then
        'some code here
    Else
        'some code here
    End If

1
非常感谢您的回答,这正中要害。问题出在“Nothing”上。 - yngrdyn
感谢@matroid指出这一点。我甚至没有注意到宏记录器添加了.Activate,导致语句总是失败。 - Toby
如果不使用方法链,rng.find("Doesn't exist") 会导致对象无法设置并出现错误。 - DaveP

15

简化回答:

你的 .Find 调用引发了错误。

只需在该行代码前加上 "Set " 即可解决问题。即...

Set Datatype = Worksheets(i).UsedRange.Find("Datatype").Column

如果没有使用“Set”,你试图将“nothing”赋给一个变量。 “nothing”只能被赋给对象。

如果你只是想了解你的代码中所有其他(有效、有价值的)讨论的话,你可以停止阅读了。

简而言之,根据所有(有道理的)代码批评,你的 Dim 语句很糟糕。前两个变量没有被“typed”,结果成为变体。具有讽刺意味的是,这就是我刚刚描述的解决方案可行的原因。

如果你决定清理那个 Dim 语句,请把 DataType 声明为 variant...

Dim DataType as variant

2
@BigBen Find("whatever").AnyChainedMemberCall 实际上是 OP 报错 91 的地方;这里的第一部分有些偏差,因为在 RHS 被评估时引发了错误,变量甚至没有看到赋值的发生。OP 的变量名称具有误导性,这并没有帮助。声明为 As Integer 的行号也是一个潜在的问题,应该指出;16 位整数数据类型长时间以来已经无法容纳工作表中的行数。但是根据 OP 的声明,Set DataType = ... 不是完全后期绑定的语句吗? - Mathieu Guindon
1
“Set Datatype = Worksheets(i).UsedRange.Find("Datatype").Column” 是一个即时错误。SetColumn 不应该在同一行。另外,建议使用 Dim DataType As Variant 并不能改变 OP 的任何内容。Find 返回一个 Range,因此 Find 的结果应该分配给一个 Range 变量,而不是一个 Variant - BigBen

2
以下是代码内容:

以下是代码内容:

    For i = 1 to 1 ' change to the number of sheets in the workbook
    Set oLookin1 = Worksheets(i).UsedRange
    sLookFor1 = "Field Name"
    Set oFound1 = oLookin1.Find(What:=sLookFor1, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)

    If Not oFound1 Is Nothing Then
    Field_Name = oFound1.Column
    RRow = oFound1.Row +1

' code goes here

    Else
    Msgbox "Field Name was not found in Sheet #" & i
    End If

    Set oLookin2 = Worksheets(i).UsedRange
    sLookFor2 = "Datatype"
    Set oFound2 = oLookin2.Find(What:=sLookFor2, LookIn:=xlValues, LookAt:=xlWhole, MatchCase:=False)

    If Not oFound2 Is Nothing Then
    DataType = oFound2.Column

' code goes here

    Else
    Msgbox "Datatype was not found in Sheet #" & i
    End If
    Next i

4
鸟瞰视图:这应该可以工作。如果您声明变量并缩进代码,可能会更加完美。;) - Siddharth Rout

1

这是一篇旧帖子,但当我试图弄清楚为什么我突然无法将PDF导出文件导入到Excel表格时,我遇到了它。

对我来说,问题出在我试图匹配的一行被合并了 - 首先对整个工作表进行简单的取消合并,就可以轻松解决问题。

      '////// Select and open file
  FieldFileName = Application.GetOpenFilename(FileFilter:="Excel Files,*.xl*;*.xm*") 'pick the file
  Set frBook = Workbooks.Open(FieldFileName, UpdateLinks:=0, ReadOnly:=True, AddToMru:=False)
  For Each mySheet In frBook.Worksheets
    mySheet.Cells.UnMerge
  Next mySheet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接