VBA中的重构-将部分代码移动到函数中不起作用
我对VBA Excel相当陌生。我试图重构一些VBA宏,方法是将代码块插入函数中,然后调用函数而不是块。在宏中多次复制粘贴代码块(仅更改一个常量)。但是,旧的解决方案有效,而新的具有函数的解决方案无效。它甚至不会抛出错误消息,只是冻结了整个Excel应用程序。你知道我可能做错了什么吗 编辑:从SAP调用宏,如果有任何不同 旧版:VBA中的重构-将部分代码移动到函数中不起作用,vba,excel,refactoring,Vba,Excel,Refactoring,我对VBA Excel相当陌生。我试图重构一些VBA宏,方法是将代码块插入函数中,然后调用函数而不是块。在宏中多次复制粘贴代码块(仅更改一个常量)。但是,旧的解决方案有效,而新的具有函数的解决方案无效。它甚至不会抛出错误消息,只是冻结了整个Excel应用程序。你知道我可能做错了什么吗 编辑:从SAP调用宏,如果有任何不同 旧版: Dim tbl As Object If ThisWorkbook.Container.LinkServer.Items("ITEMS").Table Is Nothi
Dim tbl As Object
If ThisWorkbook.Container.LinkServer.Items("ITEMS").Table Is Nothing Then
Exit Sub
Else
Set tbl = ThisWorkbook.Container.LinkServer.Items("ITEMS").Table
maxNumRow = ThisWorkbook.Container.LinkServer.Items("ITEMS").Table.rowCount
'... (do stuff)
Dim tbl As Object
If LinkServer_Table("ITEMS", tbl, maxNumRow) = True Then
'... (do stuff)
...
Function LinkServer_Table( _
ByVal name As String, _
ByRef tbl As Object, _
Optional ByRef rowCount As Long)
If ThisWorkbook.Container.LinkServer.Items(name).Table Is Nothing Then
LinkServer_Table = False
Else
Set tbl = ThisWorkbook.Container.LinkServer.Items(name).Table
rowCount = ThisWorkbook.Container.LinkServer.Items(name).Table.rowCount
LinkServer_Table = True
End If
End Function
新建:
Dim tbl As Object
If ThisWorkbook.Container.LinkServer.Items("ITEMS").Table Is Nothing Then
Exit Sub
Else
Set tbl = ThisWorkbook.Container.LinkServer.Items("ITEMS").Table
maxNumRow = ThisWorkbook.Container.LinkServer.Items("ITEMS").Table.rowCount
'... (do stuff)
Dim tbl As Object
If LinkServer_Table("ITEMS", tbl, maxNumRow) = True Then
'... (do stuff)
...
Function LinkServer_Table( _
ByVal name As String, _
ByRef tbl As Object, _
Optional ByRef rowCount As Long)
If ThisWorkbook.Container.LinkServer.Items(name).Table Is Nothing Then
LinkServer_Table = False
Else
Set tbl = ThisWorkbook.Container.LinkServer.Items(name).Table
rowCount = ThisWorkbook.Container.LinkServer.Items(name).Table.rowCount
LinkServer_Table = True
End If
End Function
您需要定义函数的返回类型:
Function LinkServer_Table( _
ByVal name As String, _
ByRef tbl As Object, _
Optional ByRef rowCount As Long) As Boolean
在Treb指出“name”参数中存在问题后,我将重点放在它上,在尝试了一些错误后,我得到了下面的工作版本。我仍然不太明白发生了什么,但它正在起作用
Function LinkServer_Table( _
ByVal name As String, _
ByRef tbl As Object, _
Optional ByRef maxRows As Long)
If ThisWorkbook.Container.LinkServer.Items(CVar(name)).Table Is Nothing Then
LinkServer_Table = False
Else
Set tbl = ThisWorkbook.Container.LinkServer.Items(CVar(name)).Table
maxRows = ThisWorkbook.Container.LinkServer.Items(CVar(name)).Table.RowCount
LinkServer_Table = True
End If
End Function
然而,我也高度重视Jean-François Corbett的输入,并试图以更干净的方式重构代码。最后,我意识到代码可以直接就地重写为非常短且可读的块:
Dim tbl As Object
Set tbl = ThisWorkbook.Container.LinkServer.Items("ITEMS").Table
If Not tbl Is Nothing Then
maxNumRow = tbl.RowCount
'...(do stuff)
谢谢你们两位的意见。谢谢你们的快速建议。我试过了,但没用;它仍然冻结。好的,它冻结在哪一行?我不知道那一行,从SAP启动时,我似乎无法调试它。独立调试时,它会在函数中的第一个If处停止,并显示“应用程序定义或对象定义错误”(1004)。当我试图剖析If并单独处理每个对象时(If用于ThisWorkbook,If用于ThisWorkbook.Container,If用于ThisWorkbook.Container.LinkServer等),它抱怨没有定义容器。但是容器可能是由SAP提供的,因此在独立调试时这种行为是有意义的。好的,让我们回到原始代码,将
dim Container添加为Object
set Container=thisgoolk.Container
MsgBox Container
。如果您需要在从SAP启动时对其进行调试,最好的办法是在代码中添加MsgBox
语句…另一个想法是,当您在函数中使用ThisWorkbook.Container.LinkServer.Items(“Items”)
而不是ThisWorkbook.Container.LinkServer.Items(name)
时,它是否有效?通常,重构使代码更具可读性。然而,我发现你的旧代码比你的新代码更清晰。您的LinkServer_表
函数执行三件事并返回三个独立的输出;一个作为返回值,两个作为ByRef
参数。这让我觉得相当混乱。此外,您还必须添加Else Exit Sub
,因此您没有保存那么多行代码。IF语句包含整个Sub,因此不需要Else部分。因此,我将代码中的许多地方从5行减少到1行。但是我理解你的反对意见。你删除了Else:Exit Sub
功能,所以实际上,要比较苹果和苹果,我们也应该从你的旧代码中删除它,从3行到1行。