我正在尝试创建一个打印函数,它可以从一个长列表底部的范围中进行选择。宏可以工作,但在宏完成后,每次“需要对象”时都会给我一个错误。我不知道如何清理这个错误并防止错误发生。
Option Explicit
Sub SchedulePrint()
Dim lRow As Range
Application.ScreenUpdating = False
With Sheets("Line 3")
Set lRow = Range("G1024").End(xlUp).Offset(-3, -6).Resize(20, 14).PrintOut
'The above is the line where I get the debug error message
End With
Application.ScreenUpdating = True
End Sub
3条答案
按热度按时间2lpgd9681#
需要对象
这条线爆炸了:
因为
Range.PrintOut
方法不返回任何内容(它是一个Sub
,不是Function
),所以实际上赋值语句的右边得到了求值,因为它是右边的一个副作用语句,所以副作用在表达式求值时发生(也就是说,你 * 确实 * 得到了一个打印输出)。这应该是一个编译时错误,但是VBA编译器将许多检查推迟到运行时,所以...VBA然后获取RHS表达式的结果,并尝试执行
Set lrow
指令......但RHS没有生成任何对象引用,因此您会得到一个 * object required * 错误,因为当您在赋值的LHS上有Set xyz
时,RHS * 必须 * 计算为对象引用。解决办法是从赋值中删除副作用:
现在,RHS计算
Range.Resize
的结果,它是一个Range
对象,因此,当此指令完成时,lrow
持有对该Range
的引用。现在,另一条指令可以调用该
Range
对象的PrintOut
方法:但还有一个问题。
隐式ActiveSheet引用
这里有一个明确的意图:
看起来像是要处理一个名为
Line 3
的工作表,但是Range
函数不是 * qualified *,所以它的行为会根据代码在项目中的编写位置而有所不同:Range
指的是该工作表 * 上的单元格 * 区域。Range
指的是 * 无论活动工作表是什么 *。因此,如果宏是在
Line 3
工作表的代码隐藏中编写的,则With
块是多余的,因为未限定的Range
调用总是将引用正确的工作表。通过使用Me
进行限定,可以使隐式包含workhseet引用更加明确。也就是说,使用Me.Range(...)
而不仅仅是Range
。如果它是在另一个工作表的代码隐藏中编写的,那么代码就会产生误导,因为它 * 不是 * 在Line 3
工作表上工作(相反,它引用了编写宏的任何工作表模块)。如果宏是在任何其他模块中编写的,那么就有一个隐含的要求,即当宏运行时,
Line 3
也是ActiveSheet
,否则就不会产生预期的结果。错误的解决方法是在访问
Range
之前激活该特定工作表:这是错误的,因为
With
块仍然是无用的。* 正确 * 的修复方法是使用With
块变量作为限定符-那么哪个工作表是活动的就不重要了:类似地,
Sheets
隐式地引用了活动 * 工作簿 *,除非代码是在ThisWorkbook
模块中编写的--在这种情况下,Sheets
隐式地是Me.Sheets
,如果我们知道我们在寻找Worksheet
类型的工作表,我们应该使用Worksheets
集合。Sheets
(或Worksheets
)不带限定符,表示 * 当前活动的任何工作簿 *-它可能是也可能不是包含宏的工作簿。使用ThisWorkbook.Worksheets("...")
可从包含宏的工作簿中检索Worksheet
。有关更多详细信息,请参见以下Rubberduck * 检查:
3qpi33ja2#
@freeflow和@vbasic2008说的都是正确的。由于您首先使用“With”语句选择了“第3行”工作表,因此下面的Range需要以句点开头,以便与所选工作表关联。
看起来好像您试图在运行PrintOut函数的同时设置范围“LROW”。由于PrintOut方法返回变量而不是Excel抛出的范围和错误。
如果你需要将lRow设置为一个范围,最好先设置lRow,然后在设置好之后再使用它。
也可以完全避免设置lRow,而只调用打印输出函数
bmvo0sr53#
在@Mathiedu_Guindon的基础上,我可以建议如下减少代码