首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >遍历切片器设置并打印到PDF

遍历切片器设置并打印到PDF
EN

Code Review用户
提问于 2017-02-16 22:26:33
回答 1查看 1.7K关注 0票数 3

我有一个包含七个表的电子表格,(tbl_1, tbl_2, ..., tbl_7)每个表都由自己的切片机控制。每个切片器都有六个(10, 20, 30, 40, 50, 60)按钮,它们引用了团队代码。我使用下面的代码在每个切片机上选择一个团队,然后为每个团队/切片器设置创建一个PDF。

到目前为止,代码运行所需的时间从5-7分钟不等。

代码语言:javascript
复制
Sub SlicerTeam()
Dim wb As Workbook
Dim sc As SlicerCache
Dim si As SlicerItem

On Error GoTo errHandler
Application.ScreenUpdating = False
Application.EnableEvents = False

Set wb = ThisWorkbook

For x = 1 To 6
    For i = 1 To 7
    Set sc = wb.SlicerCaches("tbl_" & i)
        sc.ClearAllFilters
        For Each si In sc.VisibleSlicerItems
            Set si = sc.SlicerItems(si.Name)
                If Not si Is Nothing Then
                    If si.Name = x * 10 Then
                        si.Selected = True
                    Else
                        si.Selected = False
                    End If
                Else
                    si.Selected = False
                End If
        Next si

    Next i
Call PDFCreate
Next x

exitHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub

errHandler:
MsgBox ("Error in updating slicer filters.")
Resume exitHandler

End Sub

Sub PDFCreate()
Dim Fname As String
Dim path As String

path = "S:\MyFilePath\"
Fname = path & Sheets("Detail").Range("T1").Value & " - " & [TEXT('Population Detail'!B1,"mmm, yyyy")] & ".pdf"

    Sheets("Detail").ExportAsFixedFormat Type:=xlTypePDF, _
        FileName:=Fname, Quality:=xlQualityStandard, IncludeDocProperties:=True, _
        IgnorePrintAreas:=False, OpenAfterPublish:=False

End Sub
EN

回答 1

Code Review用户

发布于 2017-02-18 21:28:33

变量

让我们稍微讨论一下变量。

  1. 总是打开Option Explicit。您可以通过使用VBE中的Tools ->选项并检查Require声明选项来自动获得它。这样,如果没有定义任何变量,编译器就会通知您。
  2. 当您不定义变量时,VBA将将其声明为可容纳任何类型数据的变量类型。虽然这可能更灵活,但在VBA决定或测试该类型时,它会增加宏的处理时间。此外,由于变体可以是任何类型的数据,您可能会遗漏关于类型不匹配的有价值的故障排除信息
  3. 变量名-给变量有意义的名称。
  4. 个人偏好-我避免像ij这样的变量,因为它们不是描述性的。但是,从技术上讲,使用它们没有什么问题,因为使用i是标准的实践。
  5. 标准VBA命名约定的局部变量有camelCase,其他变量和名称有PascalCase

尽管这么说-

您不能声明xi。但它们并不是不同的描述性的,对吧?尝试:

代码语言:javascript
复制
Dim slicerButtonNumber As Long
Dim tableNumber As Long

对于你声明的变量,你没有很好的名字-

代码语言:javascript
复制
wb - targetWorkbook
sc - targetSlicerCache
si - targetSlicerItem

使用描述性词汇扩展名称,您将不会为此付出任何代价,并且会给您带来麻烦!

此外,在此:

代码语言:javascript
复制
Set targetSlicerCache = targetBook.SlicerCaches("tbl_" & tableNumber)

你用的是常数- "tbl_",所以

代码语言:javascript
复制
Const TABLE_PREFIX as String = "tbl_"
Set targetSlicerCache = targetBook.SlicerCaches(TABLE_PREFIX & tableNumber)

这看起来不太像,但是在最上面声明,如果它曾经改变过,你只需要在一个地方改变它。

PDFCreate也是如此:

代码语言:javascript
复制
Const SHEET_NAME As String = "Detail"
Const POPULATION_SHEET_NAME As String = "Population Detail"
Const SEPARATOR As String = " - "
Dim detailSheet As Worksheet
Set detailSheet = ThisWorkbook.Sheets(SHEET_NAME)
Dim populationSheet As Worksheet
Set populationSheet = ThisWorkbook.Sheets(POPULATION_SHEET_NAME)
Dim file_Name As String
Dim file_Path As String
Dim aPathValue As String

file_Path = "S:\MyFilefilePath\"
aPathValue = detailSheet.Range("T1").Value & SEPARATOR
file_Path = file_Path & aPathValue
file_Name = filePath & [TEXT(populationsheet.range("B1"),"mmm, yyyy")] & ".pdf"

detailSheet.ExportAsFixedFormat Type:=xlTypePDF, _
    filename:=file_Name, Quality:=xlQualityStandard, IncludeDocProperties:=True, _
    IgnorePrintAreas:=False, OpenAfterPublish:=False

你不需要Call潜艇,它已经过时了。相反,只需使用Sub argument, argument

速度

这里的set是多余的

代码语言:javascript
复制
        For Each targetSlicerItem In sc.VisibleSlicerItems
            Set targetSlicerItem = targetSlicerCache.SlicerItems(targetSlicerItem.Name)

For设置项。

这也是不必要的:

代码语言:javascript
复制
If Not targetSlicerItem Is Nothing Then

它不会是Nothing,因为您只处理缓存中存在的项。

你可以压缩

代码语言:javascript
复制
For slicerButtonNumber = 1 To 6
    For tableNumber = 1 To 7
    Set targetSlicerCache = targetBook.SlicerCaches(TABLE_PREFIX & tableNumber)
        targetSlicerCache.ClearAllFilters
        For Each targetSlicerItem In targetSlicerCache.VisibleSlicerItems
            If targetSlicerItem.Name = slicerButtonNumber * 10 Then
                targetSlicerItem.Selected = True
            Else
                targetSlicerItem.Selected = False
        End If
        Next targetSlicerItem
    Next i

但是,您可以删除一个循环,即slicerButtonNumber循环。

代码语言:javascript
复制
Const BUTTON_NUMBERS As String = "10,20,30,40,50,60"
Const DELIMITER As String = ","
Dim slicerButtonNumbers As Variant
slicerButtonNumbers = Split(BUTTON_NUMBERS, DELIMITER)
    

 For tableNumber = 1 To 7
    Set targetSlicerCache = targetBook.SlicerCaches(TABLE_PREFIX & tableNumber)
        targetSlicerCache.ClearAllFilters
        For Each targetSlicerItem In targetSlicerCache.VisibleSlicerItems
            If UBound(Filter(slicerButtonNumbers, targetSlicerItem.Name)) > -1 Then
               targetSlicerItem.Selected = True
            Else
                targetSlicerItem.Selected = False
            End If
        Next targetSlicerItem
    Next tableNumber
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/155550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档