问题
I am new to the forum, so please indulge me if my post is incomplete.
I have a very simple pivot table with one row field, one column field, one data field and one filter field. Row fields are displayed based on the filter setting. Using VBA, my intent is to loop through all row pivotitems and column pivotitems and get the corresponding field names and data values and display them as a sanity check. This is a start of a bigger project.
here is the main loop (showstring is displayed on the screen):
showstring = ""
For rowFldNo = 1 To pvt.RowFields.Count
For colFldNo = 1 To pvt.ColumnFields.Count
For rowItemNo = 1 To pvt.RowFields(rowFldNo).PivotItems.Count
For colItemNo = 1 To pvt.ColumnFields(colFldNo).PivotItems.Count
If pvt.RowFields(rowFldNo).PivotItems(rowItemNo).Visible And _
pvt.ColumnFields(colFldNo).PivotItems(colItemNo).Visible Then
showstring = showstring & _
pvt.RowFields(rowFldNo).PivotItems(rowItemNo).Name & ": " & _
pvt.ColumnFields(colFldNo).PivotItems(colItemNo).Name & _
"= " & MyGetPivotData(pvt, rowFldNo, rowItemNo, colFldNo, _
colItemNo) & vbCrLf
End If
Next colItemNo
Next rowItemNo
Next colFldNo
Next rowFldNo
MsgBox showstring
MyGetPivotData is a simple sub that hides the complexity of using the VBA native GetPivotData function. Here is the code:
Function MyGetPivotData(ByRef thisPvt As PivotTable, _
ByVal rowFld As Integer, _
ByVal rowItem As Integer, _
ByVal colFld As Integer, _
ByVal colItem As Integer) As Integer
On Error Resume Next
MyGetPivotData =
thisPvt.GetPivotData(thisPvt.DataFields(thisPvt.DataFields.Count), _
thisPvt.RowFields(rowFld).Name, _
thisPvt.RowFields(rowFld).PivotItems(rowItem).Name, _
thisPvt.ColumnFields(colFld).Name, _
thisPvt.ColumnFields(colFld).PivotItems(colItem).Name).Value
End Function
The code runs fine but does not accomplish my intention. My problem is in the first code segment. I am using the Visible property before I call MyGetPivotData. The problem is that Visible does not change with filter setting - I verified it by checking manually in pivot table fields. Filter setting impacts what is visible on screen, but the pivotitem Visible property does not change and is always True. Consequently, I am looping through all available fields and GetPivotData return value 0 for non-visible fields. This is not acceptable to me becase my pivot data my contain actual 0 values.
My question is if there are other properties I could use to determine if pivotitem is filtered out (invisible and hence irrelevant) or not (visible and relevant). I tried the Object Browser in VBA but did not get any wiser. Any tips will be greatly appreciated.
Thank you
回答1:
As you already found out about the visibility of PivotItems:
If you filter a PivotTable
, then some of the PivotItems
of your RowFields
or ColumnFields
are optically visible or not,
but VBA still returns each PivotField.PivotItem
as Visible
.
Also PivotField.VisibleItems.Count
always remains the maximum.
The remaining "really" visible PivotItems
can be addressed by PivotLine.PivotLineCell.PivotItem
of each pivot-axis.
LineType
distingushes between regular, blank, subtotal and grandtotal lines.
showstring = ""
For rowItemNo = 1 To pvt.PivotRowAxis.PivotLines.Count
If pvt.PivotRowAxis.PivotLines(rowItemNo).LineType = xlPivotLineRegular Then
For colItemNo = 1 To pvt.PivotColumnAxis.PivotLines.Count
If pvt.PivotColumnAxis.PivotLines(colItemNo).LineType = xlPivotLineRegular Then
showstring = showstring & _
pvt.PivotRowAxis.PivotLines(rowItemNo).PivotLineCells(1).PivotItem.Name & ":" & _
pvt.PivotColumnAxis.PivotLines(colItemNo).PivotLineCells(1).PivotItem.Name & _
" = " & pvt.DataBodyRange.Cells(rowItemNo, colItemNo).Value & vbCrLf
End If
Next colItemNo
End If
Next rowItemNo
MsgBox showstring
If you have more than one column or row field, then PivotLineCells()
can distinguish them.
... or you loop over the DataRange
of each PivotField
to catch the items in visible cells of a simple pivot table:
For rowFldNo = 1 To pvt.RowFields.Count
For colFldNo = 1 To pvt.ColumnFields.Count
For rowItemNo = 1 To pvt.RowFields(rowFldNo).DataRange.Rows.Count
For colItemNo = 1 To pvt.ColumnFields(colFldNo).DataRange.Columns.Count
showstring = showstring & ...
Next colItemNo
Next rowItemNo
Next colFldNo
Next rowFldNo
来源:https://stackoverflow.com/questions/54636850/excel-vba-loop-through-pivotitems-that-are-filtered