【问题标题】:For loop preserving previous iterationFor 循环保留先前的迭代
【发布时间】:2026-02-06 17:30:01
【问题描述】:

我对 VBA 没有太多经验,因此很难解决这个问题。运行代码时,它输出Array(i<=i)而不是Array(i)

我测试了 for 条件,发现Array(0) 正确返回了结果。但是Array(1) 将打印Array(1)Array(0) 等等。

此代码的目标是根据工作表的名称对工作表进行分组,并根据分组将它们打印为 pdf,即将所有以 I1 开头的工作表打印为单个 pdf。

Sub Test()
    FolderPath = "C:\Example"

    Dim aWS()
    Dim n As Integer
    Dim ws As Worksheet
    Dim DocTypes()

    DocTypes = Array("I1","I2","I3")

    For i = LBound(DocTypes) To UBound(DocTypes)
        For Each ws In Worksheets
            If Left(ws.Name, 2) = DocTypes(i) Then
                n = n + 1
                ReDim Preserve aWS(1 To n) 'Add 1 to to array length
                aWS(n) = ws.Name 'Add worksheet name meeting If condition 
            End If
        Next ws  

        Sheets(aWS).Select
        ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=FolderPath & 
            DocTypes(i), _
            openafterpublish:=True, ignoreprintareas:=False
    Next i
End Sub

我的期望是:

i = 0 to 2

首先Array(i) = "I1" 将所有以“I1”开头的工作表输出为pdf

然后转到i = 1

这里是Array(i) = "I2",所以将所有以“I2”开头的工作表输出为pdf

但是,当我向前迈进时,它似乎并没有遵循这个逻辑,我不明白为什么。我认为这与选择有关,如果选择了i=0,则将i=1 添加到选择中,这个问题将是有意义的。我曾尝试在Next i 之前重新选择一张纸以强制过去,但它没有用。这让我认为我在 for 循环中犯了一个逻辑错误。

【问题讨论】:

  • 您需要在i 循环的每次迭代中使用Erase aWSn = 0
  • @VBasic2008 为什么?
  • 哦,这很有道理,谢谢。 AWS 一直存在,因此下一个 i 被添加到上一个中。打印修复后擦除并将 n 重置为 0。
  • @Aida 但是请注意*.com/a/54059685/11683ActiveSheet 确实只是一张纸,您似乎想将多张纸导出到一个 pdf 中。
  • 据我所知,Sheets() 不能将数组作为参数,您只能使用 1 张表,例如表 (1) 或表 (2)。在阅读this 之后,您似乎无法以这种方式做您想做的事。一种解决方法可能是将组中每个工作表的内容复制到一个新工作表并将其导出。

标签: excel vba


【解决方案1】:

您可能不知道,但您可以在 for each 中使用变体作为控制变量来迭代变体数组。您使用 redim 将数组扩展 1 项表明您应该使用脚本字典作为数组的中间步骤。脚本字典的 .Items 方法返回一个项目数组,因此很容易获得您随后使用的数组。这是您的代码修改为使用 scripting.dictionary 和变体控制变量。在您的特定情况下,我们基本上将 scripting.dictionary 用作列表,方法是使键和项目相同。

Option Explicit

Sub Test()

    Const FolderPath                        As String = "C:\Example"

    Dim aWS                                 As Scripting.Dictionary
    Dim ws                                  As excel.Worksheet
    Dim DocTypes()                          As Variant
    Dim DocType                             As Variant

    DocTypes = Array("I1", "I2", "I3")

    For Each DocType In DocTypes

        Set aWS = New Scripting.Dictionary

        For Each ws In Worksheets

            If DocType = left(ws.Name, 2) Then

                aWS.Add Key:=ws.Name, Item:=ws.Name

            End If

        Next ws

        Sheets(aWS.Items).Select
        ActiveSheet.ExportAsFixedFormat _
            Type:=xlTypePDF, _
            FileName:=FolderPath & DocType, _
            openafterpublish:=True, _
            ignoreprintareas:=False
    Next

End Sub

【讨论】:

  • 谢谢你,我不知道字典。我一整天都在测试这个方法,这种方法对于大工作表范围的工作速度更快,并且输出与修改我的数组方法相同的结果。
【解决方案2】:

使用 Selection.ExportAsFixedFormat 等代替 ActiveSheet。 ActiveSheet 始终只有一张,而您的选择包含许多。 经过进一步研究,我发现您可能必须为每个工作表进行选择,例如 Ws.UsedRange.Select。看看this thread

【讨论】:

  • 我对此进行了测试,并遇到了与线程中其他人相同的问题。整合 GSerg 的建议使 sub 功能达到预期,而由于某种原因,Selection 会打印空白的 pdf 页面。
  • @barkare Selection 始终指的是单元格,而不是工作表,就像linked question 中显示的那样,您需要选择所有相关工作表上的所有使用范围,然后导出选择。如果您的子程序按原样工作,则意味着您永远不会有超过一张以I1I2 等开头的工作表。
最近更新 更多