【问题标题】:Combining 3 VBA macros into 1 (2 delete rows on different sheets, and 1 refreshes data)将3个VBA宏组合成1个(2个删除不同工作表上的行,1个刷新数据)
【发布时间】:2017-10-05 20:44:50
【问题描述】:

我有 3 个宏,我想将它们组合成一个按顺序运行的宏。我想运行的第一个刷新excel工作簿中的所有数据,接下来的两个删除工作表上的特定行。我拥有的三个宏单独工作,但我想将这三个宏结合起来,以便最终用户可以一次运行它们。我认为我遇到的问题是我错误地使这些宏在特定工作表上运行,而不是在模块上运行。我坚持将它们组合在一起,因为宏已经在不同的工作表中。

第一个宏:

Sub Macro1()
   ActiveWorkbook.RefreshAll
   Sheets("ManagementDashboard").Select
End Sub

第二个宏(在名为“RawDataPltzr”的工作表中运行)

Sub DeleteRows()
   Last = Cells(Rows.Count, "c").End(xlUp).Row
   For i = Last To 1 Step -1
           'if cell value is less than 100
   If (Cells(i, "c").Value) < 100 Then
           'delete entire row
        Cells(i, "c").EntireRow.Delete
     End If
   Next i
End Sub

第三个宏(在名为“RawDataLoader”的工作表中运行,也与第二个宏相同,只是需要在不同的工作表中运行)

Sub DeleteRows()
  Last = Cells(Rows.Count, "c").End(xlUp).Row
  For i = Last To 1 Step -1
            'if cell value is less than 100
    If (Cells(i, "c").Value) < 100 Then
            'delete entire row
        Cells(i, "c").EntireRow.Delete
    End If
  Next i
End Sub

最后,我希望选择工作表“ManagementDashboard”,就像在第一个宏中一样,但我需要在运行之前运行第二个和第三个宏。任何帮助将不胜感激!

【问题讨论】:

  • 完全限定您的工作表参考。现在的代码方式,它假设 ActiveSheet,这会导致很多问题。

标签: vba excel


【解决方案1】:

只有与工作表事件相关的代码才应该在工作表模块中

  1. 新建一个模块(右键>插入>模块)
  2. 将所有三个子组件移动到新模块中(重命名具有相同名称的那些)
  3. 在您拥有Cells 的任何地方,您都需要首先参考相应的工作表。例如。 Worksheets("RawDataLoader").Cells()
  4. 按照下面添加一个新的子程序,它将为您运行所有 3 个程序

Sub RunAll()
    Macro1
    DeleteRowsPltzr
    DeleteRowsLoader
    ThisWorkbook.Worksheets("ManagementDashboard").Activate    
End Sub

确保您正确理解该方法。此时您可以将所有三个子组合成一个子(无需单独调用它们)

Sub RunAll()
    ThisWorkbook.RefreshAll

    Dim ws As Worksheet
    For Each ws In ThisWorkbook.Worksheets(Array("RawDataPltzr", "RawDataLoader"))
        Last = ws.Cells(ws.Rows.Count, "c").End(xlUp).Row
        For i = Last To 1 Step -1
                  'if cell value is less than 100
          If (ws.Cells(i, "c").Value) < 100 Then
                  'delete entire row
              ws.Cells(i, "c").EntireRow.Delete
          End If
        Next i
    Next ws

    ThisWorkbook.Worksheets("ManagementDashboard").Activate
End Sub

【讨论】:

  • 非常感谢!效果很好!
【解决方案2】:

只要您不引用某个位置,excel 就会获取当时处于活动状态的任何内容并随之运行。例如Cells(i, "C").EntireRow.Delete 被读作ActiveWorkbook.ActiveWorksheet.Cells(i,"C").EntireRow.Delete。通过使用Dim,我们不必选择或激活任何工作表或单元格。参考Here 了解更多信息。我把最后的.Activate 留在了那里,但使用它是非常糟糕的做法。将此代码放入它自己的模块中,它应该可以正常运行。

Sub All_Three()

    Dim wbk As Workbook
    Dim MD As Worksheet, RDP As Worksheet, RDL As Worksheet, ws As Worksheet
    Dim Last As Long, i As Long, myCount As Long

    Set wbk = ActiveWorkbook
    Set MD = wbk.Worksheets("ManagementDashboard")
    Set RDP = wbk.Worksheets("RawDataPltzr")
    Set RDL = wbk.Worksheets("RawDataLoader")

    'Macro1
    wbk.RefreshAll

    For myCount = 1 To 2
        Select Case myCount
            Case 1
                Set ws = RDP
            Case 2
                Set ws = RDL
        End Select

        'Macro 2 and 3
        With ws
            Last = .Range("C" & .Rows.Count).End(xlUp).Row
            For i = Last To 1 Step -1
                If .Cells(i, "C").Value < 100 Then
                    .Cells(i, "C").EntireRow.Delete
                End If
            Next i
        End With
    Next myCount

    MD.Activate

End Sub

【讨论】:

  • 您可能有兴趣使用工作表名称数组来避免使用计数器和选择语句(请参阅我的回答)
  • @CallumDA 我完全同意。当我第一次接触 VBA 阵列时,我的大脑一度崩溃。我想让其他刚开始的人更简单。
猜你喜欢
  • 1970-01-01
  • 2021-12-20
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
相关资源
最近更新 更多