VBA中的重构-将部分代码移动到函数中不起作用

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

我对VBA Excel相当陌生。我试图重构一些VBA宏,方法是将代码块插入函数中,然后调用函数而不是块。在宏中多次复制粘贴代码块(仅更改一个常量)。但是,旧的解决方案有效,而新的具有函数的解决方案无效。它甚至不会抛出错误消息,只是冻结了整个Excel应用程序。你知道我可能做错了什么吗

编辑:从SAP调用宏,如果有任何不同

旧版:

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行。