【问题标题】:How can I loop through a subset of worksheets?如何循环浏览工作表的子集?
【发布时间】:2009-10-19 22:17:12
【问题描述】:

我知道如何遍历工作簿中的所有工作表,以及在到达“结束标志”工作表后如何退出:

For Each ThisWorkSheet In Worksheets
   If ThisWorkSheet.Name = "FlagEnd" Then Exit For
   MsgBox "This worksheet name is: " & ThisWorkSheet.Name
Next

但是,我无法在“开始标志”工作表上开始循环(甚至在开始标志工作表之后的工作表上更好。例如,标记的开始/结束工作表位于一堆中间其他工作表,所以开始或结束遍历是不可行的。

在“FlagStart”工作表之前可能有数百个工作表,所以我真的需要从正确的工作表开始。

试过了:

Set ThisWorkSheet = Sheets("FlagNew")

和

For Each Sheets("FlagNew") In Worksheets

想法?

解决方案: Mathias 非常接近,但 dendarii 离自定义结尾索引更近了一小步。我实际上自己想出了我的最终解决方案,但想表扬一下。这是我的最终解决方案:

Private Sub CommandButtonLoopThruFlaggedSheets_Click()
    ' determine current bounds
    Dim StartIndex, EndIndex, LoopIndex As Integer
    StartIndex = Sheets("FlagNew").Index + 1
    EndIndex = Sheets("FlagEnd").Index - 1

    For LoopIndex = StartIndex To EndIndex
        MsgBox "this worksheet is: " & Sheets(LoopIndex).Name
        ' code here
    Next LoopIndex
End Sub

【问题讨论】:

  • Kirk,你可能没有意识到这一点,但如果你在同一行声明 3 个变量,最后一个类型,只有最后一个变量实际上采用该类型,其他变量最终成为变体.如果要将所有声明放在一行上,则需要指定“Dim StartIndex as Integer, EndIndex as Integer, LoopIndex as Integer”。
  • 呵呵,又被快捷方式烫伤了!谢谢,我不知道,我会改变它。

标签: excel vba worksheet


【解决方案1】:

如果这不是一个特别多变的工作簿(即没有一直添加和删除工作表),您可以将工作表的名称存储在隐藏工作表的某个范围内,并按名称循环访问它们。

但是,它们听起来像是连续存储在工作簿中,因此,基于 Mathias 的解决方案,您可以使用函数返回开始和结束工作表的索引,然后循环:

Public Function GetStartIndex() As Integer
    On Error Resume Next
    GetStartIndex = ThisWorkbook.Worksheets("MyStartingWorksheet").Index + 1
End Function

Public Function GetEndIndex() As Integer
    On Error Resume Next
    GetEndIndex = ThisWorkbook.Worksheets("MyEndingWorksheet").Index - 1
End Function

Sub LoopThrough()

    Dim wks As Worksheet
    Dim i As Integer
    Dim iStart As Integer
    Dim iEnd As Integer

    iStart = GetStartIndex()
    iEnd = GetEndIndex()

    If iStart > 0 And iEnd > 0 And iEnd > iStart Then
        For i = iStart To iEnd
            Set wks = ThisWorkbook.Worksheets(i)
            MsgBox wks.Name
        Next i
    End If

End Sub

【讨论】:

  • Mathias 非常接近,但这只是与自定义结束索引接近的一小步。我实际上自己想出了我的最终解决方案,但想在这里表扬一下。 Private Sub CommandButtonLoopThruFlaggedSheets_Click() ' 确定当前边界 Dim StartIndex, EndIndex, LoopIndex As Integer StartIndex = Sheets("FlagNew").Index + 1 EndIndex = Sheets("FlagEnd").Index - 1 For LoopIndex = StartIndex To EndIndex MsgBox "this工作表是:“ & Sheets(LoopIndex).Name ' 代码在这里 Next LoopIndex End Sub
  • (解决方案编辑成上面的原始问题,代码格式)
  • 我看到你已经设置了一个很好的功能。不过,我想提出一些建议。我建议您将要为其查找索引的工作表的名称作为函数中的参数。通过不带参数,您使函数成为静态的;您不妨在主子目录中写下这两行。然后,使用 sheet 集合获取索引,因为当工作簿具有图表工作表时,代码可能无法按预期工作。
【解决方案2】:

我相信如果您使用“foreach”,您将无法控制起始表。就此而言,我什至不确定您是否能保证迭代发生的顺序。
我认为您应该首先获取您感兴趣的工作表的索引(按名称获取工作表,并获取其索引),然后使用 for 循环遍历从标志开始的工作表索引工作表索引。
[编辑:我通过一个简单的例子破解]

Sub Iterate()

Dim book As Workbook
Dim flagIndex As Integer
Dim flagSheet As Worksheet

Set book = ActiveWorkbook
Set flagSheet = book.Worksheets("Sheet3")
flagIndex = flagSheet.Index

Dim sheetIndex As Integer
Dim currentSheet As Worksheet

For sheetIndex = flagIndex To book.Worksheets.Count
    Set currentSheet = book.Worksheets(sheetIndex)
Next

End Sub

【讨论】:

  • 你是对的。工作表是工作表的集合。你不知道它在哪里。
【解决方案3】:

怎么样?

For Each ThisWorkSheet In Worksheets  
    If ThisWorkSheet.Name = "FlagStart" Then output = true 
    If ThisWorkSheet.Name = "FlagEnd" Then Exit For   
    If output = true Then MsgBox "This worksheet name is: " & ThisWorkSheet.Name
Next

这段代码可能不太正确。我在 SO 编辑器而不是 VBA 中编写它,但你明白了。

【讨论】:

  • 我应该提到我想到了这一点,但它不够有效。 FlagStart 工作表前面可能有数百个工作表。我真的宁愿从正确的工作表开始。不过谢谢!
  • @Kirk Hings - 过早的优化会咬你!我建议先找到一个可行的解决方案,然后再考虑优化它的方法。我也会担心有数百张纸。 Excel 是最好的工具吗?
  • 好点,我实际上正在优化他们已经在使用的解决方案。目前他们复制粘贴了一堆这样的东西,我们正在尝试为他们自动化。我想我夸大了数百张,但可能有几十张,不幸的是它们的数量和纸张名称各不相同。我现在正在尝试这些解决方案。昨天发布这个问题后,我开始使用索引。
【解决方案4】:

您迭代的工作表是否具有通用名称格式?

例如)

Sheets(0).name > "Reports"
Sheets(1).name > "Start Here"
Sheets(2).name > "emp.0001"
Sheets(3).name > "emp.0002"
Sheets(4).name > "emp.0003"
Sheets(5).name > "emp.0004"
Sheets(6).name > "End Here"

如果是这样,在您的 for each 循环中,只需执行 Left(ThisWorkSheet.name, 4) = "emp" 以验证它是否是您要引用的工作表。

【讨论】:

    【解决方案5】:

    在 Excel VBA 2013 中,如果您有要在“Blankfirst”和“Blanklast”选项卡之间更新的工作表,则此方法有效。

    使用下面的代码进行测试,它会恢复您的选项卡名称,然后替换您的操作代码以代替 MsgBox wks.Name 部分。

    Sub Macro2()
    
        On Error Resume Next
        GetStartIndex = ThisWorkbook.Worksheets("Blankfirst").Index + 1
    
        On Error Resume Next
        GetEndIndex = ThisWorkbook.Worksheets("Blanklast").Index - 1
    
        Dim wks As Worksheet
        Dim i As Integer
        Dim iStart As Integer
        Dim iEnd As Integer
    
        iStart = GetStartIndex
        iEnd = GetEndIndex
    
    
        If iStart > 0 And iEnd > 0 And iEnd > iStart Then
            For i = iStart To iEnd
                Set wks = ThisWorkbook.Worksheets(i)
                MsgBox wks.Name
            Next i
        End If
    
    End Sub
    

    【讨论】:

      【解决方案6】:
       Public Sub ITERATE_WORKSHEETS()  
         On Error Resume Next    
         Dim x As Long  
               For x = 0 To 100  
                    MsgBox Worksheets(x).Name  
               Next x   
         On Error GoTo 0  
         MsgBox "all done"  
       End Sub  
      

      【讨论】:

        猜你喜欢
        • 2016-05-26
        • 1970-01-01
        • 2019-08-30
        • 1970-01-01
        • 2014-12-23
        • 2014-09-15
        • 1970-01-01
        • 1970-01-01
        • 2018-05-27
        相关资源
        最近更新 更多