代码之家  ›  专栏  ›  技术社区  ›  PeterT

数据透视表:检测数据透视字段何时折叠

  •  3
  • PeterT  · 技术社区  · 7 年前

    Worksheet_PivotTableUpdate 事件,以便每当用户更改数据透视表字段时,条件格式都会相应更新。

    Colorized Pivot Table

    当某些截面塌陷时,此方法继续工作:

    Colorized Pivot Table Partially Collapsed

    我的运行时错误发生在所有顶级部分都折叠时,因此第二级行数据(位置=2)未显示。

    Colorized Pivot Table All Collapsed

    我得到以下错误:

    enter image description here

    我一直在寻找一种方法来检测是否所有第二位置行字段都已折叠/隐藏/不可见/未钻取,以便识别该条件并跳过格式化部分。然而,我还没有发现 PivotField , PivotItem PivotTable 我会给我那个信息。

    Private Sub Worksheet_PivotTableUpdate(ByVal Target As PivotTable)
        ColorizeData
    End Sub
    

    所以在一个单独的模块中 ColorizeData

    Option Explicit
    
    Sub ColorizeData()
        Dim staffingTable As PivotTable
        Dim data As Range
        Set staffingTable = ActiveSheet.PivotTables(PIVOT_TABLE_NAME)
        Set data = staffingTable.DataBodyRange
        '--- don't select the bottom TOTALS row, we don't want it colored
        Set data = data.Resize(data.rows.count - 1)
    
        '--- ALWAYS clear all the conditional formatting before adding
        '    or changing it. otherwise you end up with lots of repeated
        '    formats and conflicting rules
        ThisWorkbook.Sheets(PIVOT_SHEET_NAME).Cells.FormatConditions.Delete
        ThisWorkbook.Sheets(PIVOT_SHEET_NAME).Cells.ClearFormats
        staffingTable.DataBodyRange.Cells.NumberFormat = "#0.00"
        staffingTable.ColumnRange.NumberFormat = "mmm-yyyy"
    
        '--- the cell linked to the checkbox on the pivot sheet is
        '    supposed to be covered (and hidden) by the checkbox itself
        If Not ThisWorkbook.Sheets(PIVOT_SHEET_NAME).Range("D2") Then
            '--- we've already cleared it, so we're done
            Exit Sub
        End If
    
        '--- capture the active cell so we can re-select it after we're done
        Dim previouslySelected As Range
        Set previouslySelected = ActiveCell
    
        '--- colorizing will be based on the type of data being shown.
        '    Many times there will be multiple data sets shown as sums in
        '    the data area. the conditional formatting by FTEs only makes
        '    sense if we colorize the Resource or TaskName fields
        '    most of the other fields will be shown as summary lines
        '    (subtotals) so those will just get a simple and consistent
        '    color scheme
    
        Dim field As PivotField
        For Each field In staffingTable.PivotFields
            Select Case field.Caption
            Case "Project"
                If field.Orientation = xlRowField Then
                    If field.Position = 1 Then
                        staffingTable.PivotSelect field.Caption, xlFirstRow, True
                        ColorizeDataRange Selection, RGB(47, 117, 181), RGB(255, 255, 255)
                    End If
                End If
            Case "WorkCenter"
                If field.Orientation = xlRowField Then
                    If field.Position = 1 Then
                        staffingTable.PivotSelect field.Caption, xlFirstRow, True
                        ColorizeDataRange Selection, RGB(155, 194, 230), RGB(0, 0, 0)
                    End If
                End If
            Case "Resource"
                If field.Orientation = xlRowField Then
                    If field.Position = 1 Then
                        staffingTable.PivotSelect field.Caption, xlFirstRow, True
                    Else
    ===> ERROR HERE-->  staffingTable.PivotSelect field.Caption, xlDataOnly, True
                    End If
                    ColorizeConditionally Selection
                End If
            Case "TaskName"
                If field.Orientation = xlRowField Then
                    If field.Position = 1 Then
                        staffingTable.PivotSelect field.Caption, xlFirstRow, True
                    Else
                        staffingTable.PivotSelect field.Caption, xlDataOnly, True
                    End If
                    ColorizeConditionally Selection
                End If
            End Select
        Next field
    
        '--- re-select the original cell so it looks the same as before
        previouslySelected.Select
    End Sub
    

    当用户选择行数据作为

    enter image description here

    以防万一,为了完整性起见,我在这里包括了两个私人子调用:

    Private Sub ColorizeDataRange(ByRef data As Range, _
                                  ByRef interiorColor As Variant, _
                                  ByRef fontColor As Variant)
        data.interior.Color = interiorColor
        data.Font.Color = fontColor
    End Sub
    
    Private Sub ColorizeConditionally(ByRef data As Range)
        '--- light green for part time FTEs
        Dim dataCondition As FormatCondition
        Set dataCondition = data.FormatConditions.Add(Type:=xlCellValue, _
                                                      Operator:=xlBetween, _
                                                      Formula1:="=0.1", _
                                                      Formula2:="=0.5")
        With dataCondition
            .Font.ThemeColor = xlThemeColorLight1
            .Font.TintAndShade = 0
            .interior.PatternColorIndex = xlAutomatic
            .interior.ThemeColor = xlThemeColorAccent6
            .interior.TintAndShade = 0.799981688894314
            .SetFirstPriority
            .StopIfTrue = False
        End With
    
        '--- solid green for full time FTEs
        Set dataCondition = data.FormatConditions.Add(Type:=xlCellValue, _
                                                      Operator:=xlBetween, _
                                                      Formula1:="=0.51", _
                                                      Formula2:="=1.2")
        With dataCondition
            .Font.ThemeColor = xlThemeColorLight1
            .Font.TintAndShade = 0
            .Font.Color = RGB(0, 0, 0)
            .interior.PatternColorIndex = xlAutomatic
            .interior.Color = 5296274
            .SetFirstPriority
            .StopIfTrue = False
        End With
    
        '--- orange for slightly over full time FTEs
        Set dataCondition = data.FormatConditions.Add(Type:=xlCellValue, _
                                                      Operator:=xlBetween, _
                                                      Formula1:="=1.2", _
                                                      Formula2:="=1.85")
        With dataCondition
            .Font.Color = RGB(0, 0, 0)
            .Font.TintAndShade = 0
            .interior.PatternColorIndex = xlAutomatic
            .interior.Color = RGB(255, 192, 0)
            .SetFirstPriority
            .StopIfTrue = False
        End With
    
        '--- red for way over full time FTEs
        Set dataCondition = data.FormatConditions.Add(Type:=xlCellValue, _
                                                      Operator:=xlGreater, _
                                                      Formula1:="=1.85")
        With dataCondition
            .Font.Color = RGB(255, 255, 255)
            .Font.TintAndShade = 0
            .interior.PatternColorIndex = xlAutomatic
            .interior.Color = RGB(255, 0, 0)
            .SetFirstPriority
            .StopIfTrue = False
        End With
    End Sub
    

    多亏了@ScottHoltzman,我将他的检查与下面的逻辑结合起来,得出了一个解决方案

        Case "Resource"
            If field.Orientation = xlRowField Then
                If (field.Position = 2) And PivotItemsShown(staffingTable.PivotFields("Project")) Then
                    staffingTable.PivotSelect field.Caption, xlDataOnly, True
                    ColorizeConditionally Selection
                ElseIf field.Position = 1 Then
                    staffingTable.PivotSelect field.Caption, xlFirstRow, True
                    ColorizeConditionally Selection
                End If
            End If
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Scott Holtzman    7 年前

    使用 ShowDetail 方法 PivotItems

    测试代码:

    If field.Orientation = xlRowField Then
        If PivotItemsShown(field) Then
            If field.Position = 1 Then
                staffingTable.PivotSelect field.Caption, xlFirstRow, True
            Else
                staffingTable.PivotSelect field.Caption, xlDataOnly, True
            End If
            ColorizeConditionally Selection
        End If
    End If
    
    Function PivotItemShown(pf as PivotField) as Boolean
    
        Dim pi as PivotItem
    
        For each pi in pf.PivotItems
            If pi.ShowDetail Then 
                PivotItemsShown = True
                Exit For
            End If
        Next
    
    End Function
    

    更新:下面是两种破解方法

    If Len(Range("A10") Then ... `skip this section
    

    或者,如果您可能随时有动态项目列表,请使用以下选项:

    For each rng in Range(Range("A6"),Range("A6").End(xlDown))
        If Instr(rng.Value,"Project") = 0 and rng.Value <> "Grand Total" Then 
            '.... select the row range as needed
            Exit For
        End If
    Next 
    
    推荐文章