【问题标题】:Select single slicer item from Table VBA从表 VBA 中选择单个切片器项目
【发布时间】:2017-12-04 12:53:15
【问题描述】:

我正在尝试打印选定预算持有人的报告(从预算持有人表中选择),使用预算持有人名称输入切片器,然后更新各种数据透视表。 问题是代码选择切片器中的所有预算持有人,而不是选择我从表中选择的单个选定的预算持有人。

Sub PrintPDFsSO()

    Dim Lobj As ListObject
    Dim Budholder As String
    Dim Path As String
    Dim x As Long, y As Long, Number_of_rows As Long
    Dim SourceBk As Workbook
    Dim SlicItem As SlicerItem, SlicDummy As SlicerItem, SlicCache As SlicerCache
    Dim pt As PivotTable, wb As Workbook, ws As Worksheet

    Set SourceBk = ThisWorkbook
    Set Lobj = SourceBk.Sheets("BudHolders").ListObjects("BudHolderList")
    Set SlicCache = SourceBk.SlicerCaches("Slicer_Budget_Holder")

    For x = 1 To Lobj.DataBodyRange.Rows.Count   'Budget Holders held in    BudHolderList Table

        Dim BudHolders()
        ReDim BudHolders(1 To Lobj.DataBodyRange.Rows.Count) 'as Budholders will only ever hold one budget hodler name, can this be simpified?
        Dim Counter As Long

        Counter = 1

        If Not Lobj.DataBodyRange.Rows(x).EntireRow.Hidden Then

            Budholder = Lobj.DataBodyRange(x, 3) 'Name of budget holder held in 3rd column of Budget Holder Table

            BudHolders(Counter) = Budholder      'Budholders holds the budget holder name

            Counter = Counter + 1

            ReDim Preserve BudHolders(1 To Counter - 1)

            ' Trying to stop slicers/pivot tables calculating so code setting new filter on budget name doesnt get stuck - but not working
            Application.Calculation = xlCalculationManual

            For Each ws In SourceBk.Sheets

                For Each pt In ws.PivotTables

                    pt.ManualUpdate = True

                Next pt

            Next ws

            'Code to change budget holder in slicer to next budget holder in selection from Table
            For y = LBound(BudHolders) To UBound(BudHolders)

                With SlicCache

                    .ClearManualFilter           'clears all filters and shows all items in budget holder slicer

                    For Each SlicItem In .SlicerItems

                        If BudHolders(y) <> SlicItem.Value Then 'Tests if the slicer item matches the current a value of budholder

                            SlicItem.Selected = False 'Grinding to a virtual halt on this line as it 'calculates and populates pivot table report'

                        End If

                    Next SlicItem

                End With

            Next y

            Application.Calculation = xlCalculationAutomatic

            For Each ws In SourceBk.Sheets

                For Each pt In ws.PivotTables

                    pt.ManualUpdate = False

                Next pt

            Next ws

            'Use budholder name which will populate some graphs etc in workbook with new figures
            SourceBk.Sheets("Graphs - Summary").Range("BudHolder_SG").Value = Budholder

            'Do Printing, saving etc
        End If

    Next

End Sub

【问题讨论】:

    标签: excel vba select slicers


    【解决方案1】:

    你能颠倒逻辑并隐藏那些不想要的吗?以下代码基于从表中提取过滤器并应用于数据透视表。

    注意:它将所有表格过滤器存储在一个数组中,然后循环该数组以将过滤器一次一个地应用于与数据透视关联的切片器。

    您当然希望使代码更加模块化,并分离成单独的函数/子过滤器的存储、数组的循环和任何单独的操作,例如循环数组时生成报告 在移动设备上,缩进可能有点不对。

    Option Explicit
    
    Sub PrintPDFs()
    
        Dim Lobj As ListObject
        Dim BudHolder As String
        Dim SlicItem As SlicerItem, SlicCache As SlicerCache
        Dim SourceBk As Workbook
        Dim x As Long
    
        Set SourceBk = ThisWorkbook
    
        'Picks up Table with budget holder details
        Set Lobj = SourceBk.Sheets("BudHolders").ListObjects("BudHolderList")
    
        'Picks up slicer which drives pivot tables in workbook
        Set SlicCache = SourceBk.SlicerCaches("Slicer_Budget_Holder")
    
        Dim BudHolders()
        ReDim BudHolders(1 To Lobj.DataBodyRange.Rows.Count)
        Dim counter As Long
        counter = 1
    
    
        For x = 1 To Lobj.DataBodyRange.Rows.Count
    
            If Not Lobj.DataBodyRange.Rows(x).EntireRow.Hidden Then ''Applies to items selected (ie visible) in the Budget Holder Table
    
                BudHolder = Lobj.DataBodyRange(x, 3)
    
                BudHolders(counter) = BudHolder
    
                counter = counter + 1
    
            End If
    
        Next x
    
        ReDim Preserve BudHolders(1 To counter - 1)
    
    
        For x = LBound(BudHolders) To UBound(BudHolders)
    
           With SlicCache
    
               .ClearManualFilter
    
               For Each SlicItem In .SlicerItems
    
                   If BudHolders(x) <> SlicItem.Value Then
    
                       SlicItem.Selected = False
    
                   End If
    
               Next SlicItem
    
           End With
    
           ‘Rest of code to do print PDF reports etc
    
        End Sub
    

    这里的表称为 BudHolderList,pivottable 是 pivottable 1,切片器称为 Slicer_Budget_Holder。

    表:

    枢轴:

    【讨论】:

    • 嗨 QHarr,我认为这不适用于我正在做的事情,因为我正在从表格(预算持有人列表)中的过滤列表中获取预算持有人,一次一个并使用该预算持有人的姓名来驱动工作簿中的各种其他报告(不使用数据透视表),然后将其复制到新书中,保存并打印。所以.. 我想使用同一个预算持有人来过滤和创建数据透视报告,创建所有非数据透视报告,并将它们导出,所有这些都在同一个 for/next 循环中,然后再转到下一个预算持有人源表。希望这是有道理的!
    • 嗨 QHarr - 我不知道 If UBound(Filter(BudHolders, SlicItem.Value)) = -1 行是如何工作的。你能解释一下吗?
    • BudHolders 是一个数组,其中包含在表中选择的项目名称。过滤器 =-1 是在该数组中找不到当前切片器项目的位置,即是隐藏行。
    • 但是,我对您对还需要发生什么的描述感到有些困惑。 BudHolders 是一个数组,用于保存从表中选择的预算持有人,您可以循环此数组以执行您为每个预算持有人描述的所有步骤。
    • 没有。您提出问题并确保示例完整,即包含代码。用 VBA 标签查看已经存在的问题,看看您认为哪些易于理解且布局合理。
    【解决方案2】:

    我通过使用其中一个数据透视表而不是切片器找到了一种解决方法。因为这些表都是连接的(即,所有表都将预算持有人作为过滤字段并通过切片器连接),所以当我在数据透视表的数据透视字段中更新预算持有人时,它将使用相同的 PivotField 值。

    所以替换原始问题中切片器代码的代码很简单:

    With sheets ("BudgetHolder").PivotTables("PivotTable1").PivotFields("BudgetHolder")
    .ClearAllFilters
    .CurrentPage=Budholder
    End With
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多