Excel VBA loop through pivotitems that are filtered

六月ゝ 毕业季﹏ 提交于 2020-01-11 12:04:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!