Передача листов в виде переменных из одной подпроцедуры в другую в VBA - PullRequest
0 голосов
/ 01 ноября 2018

Это мой первый пост на 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 голосов
/ 01 ноября 2018

VBA не так прост и прост, как думают многие люди (в основном те, кто считает его забавным языком сценариев, написанным wanna-be-developers). Иногда он позволяет писать ByVal, но он следует своим собственным правилам и принимает аргумент ByRef, просто чтобы успокоить вас и убедиться, что вы не допустите ошибки.

Увидел ответ от @tigeravatar здесь, и я решил не писать под ним комментарий, а объяснить в другом посте, почему он неправильный и опасный, поскольку объяснять его как комментарий было бы сложно.

Если вы попытаетесь написать 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, то, если кто-то меняет имя 8-го рабочего листа, в то время как Stop горит, тогда оно все равно должно принять старое имя. Это ByVal, помнишь? Ну, давай и смени имя. Затем продолжите с F5 . Какое имя ты получаешь? Зачем?

Ответ из-за способа вызова Sub с круглыми скобками в аргументах. Эти силы ByVal и игнорируют все, что написано явно.

0 голосов
/ 01 ноября 2018

Это минимальный способ прохождения рабочих листов. Поскольку они являются объектами, по умолчанию они передаются по ссылке:

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
0 голосов
/ 01 ноября 2018

Простой пример того, как передать объекты листа в другую подпрограмму:

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
0 голосов
/ 01 ноября 2018

Я заметил в ваших примерах, что ваши переменные объявлены внутри функции. Обычно любые переменные, которые вы хотите использовать, лучше реализуются с помощью option explicit. Также при идентификации листов у вас будет меньше проблем при адресации листа по номеру листа, а не по имени листа. Таким образом, если вам нужно использовать переменную, вы также можете использовать только целое число.

Option Explicit
Dim h as Long, i as Long, l as Long, j as Long, k as Long, lr as Long
Dim x as Integer

Sub IAR_macro()
    On Error GoTo Canceled
    i = (Range("B1").End(xlDown).Row) - 1

    Sheets(x).Activate

    Do While l < (i - l)

Идентификаторы листов можно найти в инструменте разработки Вот пример:

enter image description here

0 голосов
/ 01 ноября 2018

Вам нужно передать две переменные, которые вы создали, второму подпрограмме при вызове процедуры:

Sub IAR_part_2()

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

    Call IAR_macro (sheetname1,sheetname2)

End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...