简体   繁体   English

运行VBA宏以触发不同工作表中的宏

[英]Run a VBA macro to trigger macros in different sheets

The situation is like this: I have 40 worksheets embedded with same Macros called RetrieveNumbers . 情况是这样的:我有40个工作表,其中嵌入了称为RetrieveNumbers的相同宏 The end results in 40 sheets will be different based upon various parameters in each worksheet. 40张纸的最终结果将因每个工作表中的各种参数而有所不同。

To update the numbers, I manually click the macro buttons to retrieve numbers in the 40 worksheets. 要更新数字,我手动单击宏按钮以检索40个工作表中的数字。 As a result of that, I'm sick of it. 结果,我对此感到厌烦。 To simplify the testing, I only use two sheets(Sheet1, Sheet2) to test if, by clicking a Macro named RunAll, it would run through the two Macros. 为了简化测试,我仅使用两个工作表(Sheet1,Sheet2)来测试是否通过单击名为RunAll的宏来运行两个宏。

Surely, I have FAILED. 当然,我失败了。

I have tried : 我努力了 :

  1. application.run 应用程序运行

  2. call 呼叫

Two scenarios I tried: 我尝试了两种情况:

  1. I hit F5 as I was in the RunAll window and my other screen on the Sheet1 worksheet . 我就像在RunAll窗口中以及在Sheet1工作表其他屏幕中一样,按 F5。 It runs perfectly and yet it runs twice in Sheet1 rather than going to Sheet2. 它运行完美,但是在Sheet1中运行了两次,而不是进入Sheet2。

  2. I hit F5 as I was in the RunAll window and my another screen on the RunAll worksheet . 我在RunAll窗口中看到了F5, 在RunAll工作表中又看到了另一个屏幕。 After clicking it, I went back to see if there were any numbers. 单击它之后,我返回查看是否有数字。 And surely, there weren't. 当然,没有。

I thought the Macro would go to Sheet2 and then run Macro Retrivenumbers2. 我以为宏会转到Sheet2,然后运行Macro Retrivenumbers2。 But it didn't. 但事实并非如此。 It stayed at the current worksheet. 它停留在当前的工作表上。 Please give me some guidance on how to run the next sheets I want. 请给我一些有关如何运行我想要的下一张纸的指导。 Let me know if I need to clarify more on this question. 让我知道是否需要进一步澄清这个问题。

The Macro RetrieveNumbers 宏检索编号
(Since the Macro RetrieveNumbers2 is as same as RetrieveNumbers1, I don't include it) (由于宏RetrieveNumbers2与RetrieveNumbers1相同,因此我不包含它)

Sub RetrieveNumbers1()

Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
Let NumberFiles = ActiveSheet.Cells("2", "A").Value
Let FilesVisited = 0                            'start from 0
Let RowNumber = 4                            'start from column B


If NumberFiles > 30 Then
    MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
    For FilesVisited = 1 To NumberFiles

    'Open files, get path, file, tab name and cells
    Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
    Let PathFileOpen = ActiveSheet.Cells(RowNumber, "A").Text
    Let NameFileOpen = ActiveSheet.Cells(RowNumber, "B").Text
    Let NameTab = ActiveSheet.Cells(RowNumber, "C").Text

    Dim N As Integer, Cell As String, NumberYears As String, FullLink As String
    NumberYears = ActiveSheet.Cells("2", "B").Value
    For N = 4 To NumberYears + 3
        Cell = ActiveSheet.Cells(RowNumber, N).Text
        FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
        ActiveSheet.Cells(RowNumber, N + 13).Value = FullLink
    Next N
    RowNumber = RowNumber + 1
Next FilesVisited
End If

ActiveSheet.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, 
SearchFormat:=False, ReplaceFormat:=False

End Sub

The Macro RunAll 宏RunAll

Sub runall()

Call Sheet1.RetrieveNumbers1
Call Sheet2.RetrieveNumbers2

End Sub

Clear Example of the file Working file example 清除 文件示例工作文件示例

There's a fair amount wrong with your code. 您的代码有很多错误。 As @PGCodeRider said in his answer - have one procedure that runs on all sheets. 正如@PGCodeRider在回答中所说的-在所有工作表上运行一个过程。 His code has the loop within the procedure. 他的代码在过程中具有循环。

This code uses a separate procedure to cycle through the sheets and passes a reference to the sheet to the RetrieveNumbers procedure. 该代码使用一个单独的过程来循环工作表,并将对工作表的引用传递给RetrieveNumbers过程。
I've replaced all instances of ActiveSheet (reference to the ActiveSheet) with wrkSht (reference to the sheet that the RunAllSheets procedure passes). 我已用wrkSht (对RunAllSheets过程通过的工作表的引用)替换了ActiveSheet所有实例(对ActiveSheet的引用)。
All Dims have been moved to the top of the code as they only need declaring once and not on each loop (you change the value the variables hold on each loop, but no need to declare them again). 所有Dims已移至代码顶部,因为它们只需要声明一次,而不是在每个循环中声明(您可以更改变量在每个循环中保留的值,而无需再次声明它们)。

Sub RunOnAllSheets()

    Dim wrkSht As Worksheet

    For Each wrkSht In ThisWorkbook.Worksheets
        Select Case wrkSht.Name
            Case "Sheet1", "Sheet2"
                'Do nothing.
            Case Else
                'For all other sheets execute the RetrieveNumbers procedure
                'and pass the wrkSht variable to it.
                RetrieveNumbers wrkSht
        End Select
    Next wrkSht

End Sub

Sub RetrieveNumbers(wrkSht As Worksheet)

    Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
    'You only need to declare these once.
    Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
    Dim N As Integer, Cell As String, NumberYears As String, FullLink As String

    'No need to use 'LET' it's a left-over from the days of Sinclair Basic
    'ok, maybe not.... but it's an old way of doing it.
    NumberFiles = wrkSht.Cells("2", "A").Value
    FilesVisited = 0                         'start from 0
    RowNumber = 4                            'start from column B


    If NumberFiles > 30 Then
        MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
    Else
        For FilesVisited = 1 To NumberFiles

            'Open files, get path, file, tab name and cells

            PathFileOpen = wrkSht.Cells(RowNumber, "A").Text
            NameFileOpen = wrkSht.Cells(RowNumber, "B").Text
            NameTab = wrkSht.Cells(RowNumber, "C").Text


            NumberYears = wrkSht.Cells("2", "B").Value
            For N = 4 To NumberYears + 3
                Cell = wrkSht.Cells(RowNumber, N).Text
                FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
                wrkSht.Cells(RowNumber, N + 13).Value = FullLink
            Next N
            RowNumber = RowNumber + 1
        Next FilesVisited
    End If

    wrkSht.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
        LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
        SearchFormat:=False, ReplaceFormat:=False

End Sub

Edit, after accepted as answer: 接受答案后进行编辑:

This method only references the sheet twice. 此方法仅引用工作表两次。 Once to pull the link info, and once more to put the final formula back on the sheet. 一次提取链接信息,再一次将最终公式放回工作表。

Sub RunOnAllSheets()

    Dim wrkSht As Worksheet

    For Each wrkSht In ThisWorkbook.Worksheets
        'Have removed the Select Case statement so it looks at all sheets.
        RetrieveNumbers wrkSht
    Next wrkSht

End Sub

Sub RetrieveNumbers(wrkSht As Worksheet)

    Dim NumberFiles As Long, FilesVisited As Long
    Dim vCellValues As Variant, vLinkValues() As Variant
    Dim FullPath As String
    Dim x As Long

    With wrkSht
        'Get the last row number that contains data in column N.
        NumberFiles = .Cells(.Rows.Count, "N").End(xlUp).Row

        If NumberFiles - 3 > 30 Then
            MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
        Else
            'Pass the cell values to an array.
            vCellValues = .Range("A4:C4")

            'Create the full path excluding the cell reference.
            FullPath = "='" & vCellValues(1, 1) & "[" & vCellValues(1, 2) & "]" & vCellValues(1, 3) & "'!"

            'Create an array of full path & cell references.
            ReDim vLinkValues(1 To NumberFiles - 3) 'Set the array size.
            For x = 1 To NumberFiles - 3
                vLinkValues(x) = FullPath & .Cells(x + 3, "N")
            Next x

            'Paste the array back to the sheet.
            .Range(.Cells(4, "N"), .Cells(NumberFiles, "N")).Formula = vLinkValues
        End If

    End With

End Sub  

Note: This assumes your path is just in cell A4:C4, as indicated by the code vCellValues = .Range("A4:C4") (I'm not sure this is the case now). 注意:这假定您的路径仅在单元格A4:C4中,如代码vCellValues = .Range("A4:C4") (我现在不确定是这种情况)。
If your paths are on each row matching the cell values you'll need to: 如果您的路径在与单元格值匹配的每一行上,则需要:

  • Change vCellValues = .Range("A4:C4") to vCellValues = .Range("A4:C4")更改为
    vCellValues = .Range(.Cells(4, 1), .Cells(NumberFiles, 3))
  • Remove the FullPath='.... line. 删除FullPath='....行。
  • Change vLinkValues(x) = FullPath & .Cells(x + 3, "N") to vLinkValues(x) = FullPath & .Cells(x + 3, "N")更改为
    vLinkValues(x) = "='" & vCellValues(x, 1) & "[" & vCellValues(x, 2) & "]" & vCellValues(x, 3) & "'!" & .Cells(x + 3, "N")

Try running a loop through all of the sheets in the workbook? 尝试遍历工作簿中的所有工作表吗? Also make sure you run this in a module in your vba editor. 还要确保在vba编辑器的模块中运行此命令。 Not your sheet code. 不是您的工作表代码。

Sub RetrieveNumbers1()

Dim WS As Worksheet
'loop that goes through all sheets in your workbook. Where you used to have
'activesheet, I changed to ws
For Each WS In ThisWorkbook.Sheets


Dim NumberFiles As Integer, FilesVisited As Integer, RowNumber As Integer
Let NumberFiles = WS.Cells("2", "A").Value
Let FilesVisited = 0                            'start from 0
Let RowNumber = 4                            'start from column B


If NumberFiles > 30 Then
    MsgBox "Don't try to retrieve numbers from more than 30 files at a time!"
Else
    For FilesVisited = 1 To NumberFiles

    'Open files, get path, file, tab name and cells
    Dim PathFileOpen As String, NameFileOpen As String, NameTab As String, FileDir As String
    Let PathFileOpen = WS.Cells(RowNumber, "A").Text
    Let NameFileOpen = WS.Cells(RowNumber, "B").Text
    Let NameTab = WS.Cells(RowNumber, "C").Text

    Dim N As Integer, Cell As String, NumberYears As String, FullLink As String
    NumberYears = WS.Cells("2", "B").Value
    For N = 4 To NumberYears + 3
        Cell = WS.Cells(RowNumber, N).Text
        FullLink = "(=)'" & PathFileOpen & "\[" & NameFileOpen & ".xlsm]" & NameTab & "'!" & Cell
        WS.Cells(RowNumber, N + 13).Value = FullLink
    Next N
    RowNumber = RowNumber + 1
Next FilesVisited
End If


ws.Range("A1").CurrentRegion.Replace What:="(=)", Replacement:="=", _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False,
SearchFormat:=False, ReplaceFormat:=False

'restarts on the next ws
Next WS

End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM