Vba 透视表:检测透视字段何时折叠
对于透视表中显示的数据,我选择对数据表的某些部分应用条件格式,以突出显示特定范围内的值。找出如何突出显示第二级行数据与小计数据的不同是很有趣的,但我能够解决这个问题。My VBA使用Vba 透视表:检测透视字段何时折叠,vba,excel,pivot-table,Vba,Excel,Pivot Table,对于透视表中显示的数据,我选择对数据表的某些部分应用条件格式,以突出显示特定范围内的值。找出如何突出显示第二级行数据与小计数据的不同是很有趣的,但我能够解决这个问题。My VBA使用工作表_PivotTableUpdate事件触发,这样每当用户更改数据透视表字段时,条件格式都会相应更新 当某些截面塌陷时,此方法将继续工作: 我的运行时错误发生在所有顶级部分折叠时,因此第二级行数据(位置=2)未显示 我得到以下错误: 我一直在寻找一种方法来检测是否所有的第二位置行字段都已折叠/隐藏/不可见
工作表_PivotTableUpdate
事件触发,这样每当用户更改数据透视表字段时,条件格式都会相应更新
当某些截面塌陷时,此方法将继续工作:
我的运行时错误发生在所有顶级部分折叠时,因此第二级行数据(位置=2)未显示
我得到以下错误:
我一直在寻找一种方法来检测是否所有的第二位置行字段都已折叠/隐藏/不可见/未钻取,以便识别该条件并跳过格式化部分。但是,我还没有发现数据透视字段
、数据透视项
或数据透视表
的哪个方法或属性会提供这些信息
直接附加到工作表的事件代码为
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
表的特定设置是在用户选择行数据作为
以防万一,为了完整性起见,我在这里加入了两个私人子呼叫:
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,我将他的支票与下面的逻辑结合起来,得出了一个解决方案
使用
PivotItems
对象的showdeail
方法。我将其包装到一个函数中,以便更清晰地集成到代码中。所有这些都是因为您必须测试字段的每个项目
测试代码:
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
更新:下面的两种破解方法
因为您知道,在您的示例中,如果所有3个项目都折叠,单元A10将为空,您可以这样检查:
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
适用于范围内的每个rng(范围(“A6”)、范围(“A6”)。结束(xlDown))
如果仪表(rng.Value,“项目”)=0,rng.Value“总计”,则
'.... 根据需要选择行范围
退出
如果结束
下一个
这是一种有趣的方法,但这是不可能的。奇怪的是,“资源”字段pi.showdeail
即使在所有二级行都折叠时也是正确的。@彼得,问题不在于showdeail
,而在于pivottItems
。它返回与字段无关的项。即使在尝试了一个官方的方法之后,我也无法理解返回的值。“我想这个方法是错误的。”彼得-好的。是的,我明白你在说什么,第二关返回真(奇怪)。但是,仍然可以通过传递Project
字段来使用该函数。传递staffingTable.PivotFields(“项目”)
(或者不管实际名称是什么,看看它是否有效。如果第一层没有可见的项目,你知道它在高层都崩溃了。我最初也提出了这些可能有用的黑客方法。我现在正在编辑答案。这是一个困难的问题。上面显示了更新的解决方案。谢谢!
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