Как перебрать каждый активный (нефильтрованный) элемент в сводной таблице (исключая метки столбцов и общие итоги)? - PullRequest
1 голос
/ 18 июня 2019

Я ожидал, что в полях будет "Сумма регулярных часов", "Сумма регулярных часов", ..., "Сумма SNWH NSD час."

Но я получил MsgBox pf показывает "Значения"

Msgbox pi показывает "Сумма регулярных часов", "Сумма обычных часов", ..., "Сумма SNWH NSD часов".

Но в идеале я хочу, чтобы pi были элементами каждого столбца. Есть ли другой способ сделать это?

Sub test()

Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem

Set pt = ThisWorkbook.Worksheets("N-MR Hours Summary").PivotTables("N-MR Hours Summary")

For Each pf In pt.ColumnFields
    MsgBox pf
    For Each pi In pf.PivotItems
        MsgBox pi
    Next pi
Next pf

End Sub()
* +1012 *enter image description here

Кроме того, он должен включать только активные ячейки (нефильтрованные ячейки), но я понял, что даже отфильтрованные ячейки повторяются.

1 Ответ

1 голос
/ 19 июня 2019

Сводная таблица имеет PivotRowAxis (по вертикали) и PivotColumnAxis (по горизонтали).
Каждый из них состоит из одного или нескольких PivotLines.
На следующем скриншоте показана ось и их PivotLines с PivotLineCells.

PivotLine Explanation

В вашем примере каждый PivotColumnAxis.PivotLine имеет только 1 PivotLineCell.
PivotLine.PivotLineType может использоваться для идентификации строк или столбцов с обычными значениями, подытогами, итоговыми или полностью пустыми строками:

PivotLineType Explanation

Поскольку ваши столбцы состоят только из DataFields (без выделенного ColumnFields), вы можете циклически перебрать PivotColumnAxis.PivotLine(i).PivotLineCells(1).PivotField, чтобы получить вертикальное значение DataRange каждого столбца:

PivotLineCell with PivotField and its DataRange

Вот код для этого:

Private Sub ColumnByColumn()
    Dim pt As PivotTable
    Dim pl As PivotLine
    Dim pf As PivotField
    Dim c As Range

    Set pt = ActiveSheet.PivotTables(1)
    For Each pl In pt.PivotColumnAxis.PivotLines
        If pl.LineType = xlPivotLineRegular Then
            Set pf = pl.PivotLineCells(1).PivotField
            If pf.Orientation = xlDataField Then
                Debug.Print pf.Caption,
                For Each c In pf.DataRange.Cells
                    Debug.Print c.Value,
                Next c
                Debug.Print
            End If
        End If
    Next pl
End Sub

Дополнительные подсказки:

Ваша сводная таблица содержит только DataFields (без явного ColumnFields), поэтому имя сводного поля возвращается как "Значения".

К сожалению, никогда не бывает просто перебрать все видимые сводные элементы, так как простой цикл над всеми из них также возвращает невидимые (отфильтрованные) элементы. Четный PivotField.VisibleItems.Count всегда возвращает то же значение, что и PivotField.PivotItems.Count.

PivotLine.LineType в вашем случае всегда xlPivotLineRegular (это также может быть xlPivotLineBlank, xlPivotLineSubtotal или xlPivotLineGrandTotal, если у вас будут пустые столбцы, промежуточные столбцы или столбцы общего итога).

...