在VBA中将工作表作为变量从一个子过程传递到另一个子过程

时间:2018-11-01 14:59:18

标签: excel vba excel-vba

这是我关于stackoverflow的第一篇文章。我在Excel VBA中有两个子过程。第一个名为Sub IAR_part_2(),用于将两个工作表(按索引位置)分配给两个名为sheetname1和sheetname2的变量。分配变量后,我试图将它们传递给我的第二个子过程,称为IAR_macro,以进行处理。这两个工作表相互依赖,因此工作表4和8通过IAR宏运行,工作表5和9,工作表6和10等。我的问题是我无法弄清楚如何将工作表名称变量从IAR_part_2传递到IAR_macro。我在做什么错了?

Sub IAR_part_2()

    sheetname1 = Worksheets(4)
    sheetname2 = Worksheets(8)

    Call IAR_macro

End Sub

Sub IAR_macro(sheetname1 As Worksheet, sheetname2 As Worksheet)

    Dim h As Long
    Dim i As Long
    Dim l As Long
    Dim j As Long
    Dim k As Long
    Dim lr As Long

    Worksheets(sheetname1).Activate

    ' Find the number of the last cell with data in column A and subtract 1 to populate variable i
    On Error GoTo Canceled
    i = (Range("B1").End(xlDown).Row) - 1

    'Switch over to the Code sheet
    Worksheets(sheetname2).Activate

    'While the number of loops is less than variable i minus 1, copy the contents of cells A2 through A29 over and over down the worksheet
    Do While l < (i - 1)

        Range("A2:A29").Select
        Selection.Copy
        lr = Cells(Rows.Count, "A").End(xlUp).Row
        Range("A" & lr + 1).Select
        ActiveSheet.Paste

        l = l + 1

        'rest of macro follows from here...

5 个答案:

答案 0 :(得分:5)

如何将工作表对象传递到另一个子的简单示例:

Sub Macro1()

    'Declare variables
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet

    'Assign variables to worksheet objects
    Set ws1 = Worksheets(4)
    Set ws2 = Worksheets(8)

    'Call the second sub and pass the worksheet variables to it
    Call Macro2(ws1, ws2)

End Sub

Sub Macro2(ByVal arg_ws1 As Worksheet, ByVal arg_ws2 As Worksheet)

    'Reference the accepted arguments (in this case worksheet variables) directly:
    MsgBox arg_ws1.Name
    MsgBox arg_ws2.Name

    'This will result in an error because you're using the passed argument incorrectly:
    MsgBox ActiveWorkbook.Sheets(arg_ws1).Name    '<-- Results in error

End Sub

必须直接引用传递的参数。如果要使用代码中显示的结构,则传递的参数必须为字符串(但不建议使用此方法):

Sub Macro1()

    'Declare variables
    Dim sSheet1 As String
    Dim sSheet2 As String

    'Assign variables to worksheet objects
    sSheet1 = Worksheets(4).Name
    sSheet2 = Worksheets(8).Name

    'Call the second sub and pass the worksheet variables to it
    Call Macro2(sSheet1, sSheet2)

End Sub

Sub Macro2(ByVal arg_sSheetName1 As String, ByVal arg_sSheetName2 As String)

    'Because the arguments are strings, you can reference the worksheets this way
    'This method is NOT recommended
    MsgBox Worksheets(arg_sSheetName1).Name
    MsgBox Worksheets(arg_sSheetName2).Name

End Sub

答案 1 :(得分:0)

调用该过程时,需要将创建的两个变量传递给第二个子变量:

Sub IAR_part_2()

    Set sheetname1 = Worksheets(4)
    Set sheetname2 = Worksheets(8)

    Call IAR_macro (sheetname1,sheetname2)

End Sub

答案 2 :(得分:0)

我在您的示例中注意到,您在函数内部声明了变量。通常,使用ThreadPoolExecutor可以更好地实现您希望使用的任何变量。同样,在识别工作表时,用工作表编号而不是工作表名称寻址工作表时,您会遇到的问题更少。这样,如果您需要使用变量,则也可以只使用整数。

option explicit

Sheet ID可以位于开发工具中。这是一个示例:

enter image description here

答案 3 :(得分:0)

这是传递工作表的最小方式。至于它们是对象,默认情况下通过引用传递它们:

Sub TestMe()

    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Set ws1 = Worksheets(1)
    Set ws2 = Worksheets(2)
    Passing ws1, ws2

End Sub

Sub Passing(arg_ws1 As Worksheet, arg_ws2 As Worksheet)

    Debug.Print arg_ws1.Name
    Debug.Print arg_ws2.Name

End Sub

答案 4 :(得分:0)

VBA并不像许多人(主要是那些想成为开发人员的人认为它是一种有趣的脚本语言)的人想的那样简单。有时它允许编写ByVal,但是它遵循自己的规则并接受参数ByRef,只是为了安慰您并确保您不会出错。

在这里看到了@tigeravatar的答案,我决定不写评论,而是在不同的帖子中解释它为什么是错误和危险的,就其解释为评论很难。 / p>

如果您尝试从答案中在此处写一个Stop行:

Sub Macro1()

    'Declare variables
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet

    'Assign variables to worksheet objects
    Set ws1 = Worksheets(4)
    Set ws2 = Worksheets(8)

    'Call the second sub and pass the worksheet variables to it
    Call Macro2(ws1, ws2)

End Sub

Sub Macro2(ByVal arg_ws1 As Worksheet, ByVal arg_ws2 As Worksheet)

    'Reference the accepted arguments (in this case worksheet variables) directly:
    MsgBox arg_ws1.Name
    Stop
    MsgBox arg_ws2.Name

    'This will result in an error because you're using the passed argument incorrectly:
    MsgBox ActiveWorkbook.Sheets(arg_ws1).Name    '<-- Results in error

End Sub

运行答案并等待停止行:

enter image description here

如果arg_ws1是由Val取的,那么如果Stop亮着时有人更改了第8个工作表的名称,则它仍应采用旧名称。是ByVal,记得吗?好吧,继续并更改名称。然后继续 F5 。你叫什么名字?为什么?

答案是因为在参数中用括号将Sub调用的方式。这些强制ByVal并忽略任何明确编写的内容。