如何使用VBA检索在数据透视表值区域中正在求和的字段?

huangapple go评论57阅读模式
英文:

How can I retrieve the field that is being summed in Pivot Table Values area using VBA

问题

我有一个数据透视表。我可以通过迭代PivotFields集合并检查行和列的方向来读取行和列的值。但我找不到有关DataField的信息。

如果我想要使用VBA创建一个DataField,我可以使用类似以下代码将字段放置在数据透视表的值区域中。

    With ActiveSheet.PivotTables("PivotTable1")
        Call .AddDataField( .PivotFields("Sales"), _
                            "Sum of Sales", _
                            xlSum _
                          )
    End With

上面的代码是创建一个DataField的示例,显示了我需要从给定的数据透视表中读取的三个信息片段,但我不知道它是如何构建的。

在上面的示例代码中,如果我事先不知道如何检索来自数据透视表属性的Sales字段,我该如何做?方向被标记为Hidden,就像来自数据透视表源数据的所有其他未使用但可用的字段一样。

数据透视表有一个DataPivotField属性,但我无法找到其字段的列表。

英文:

I have a Pivot Table. I can read the Row and Column values by iterating the PivotFields collection and checking the Orientation for Row and Column. What I can't find is the information pertaining to the DataField.

If I wanted to create a DataField using VBA, I could use code similar to the following to place a Field in the Values area of the PivotTable.

    With ActiveSheet.PivotTables("PivotTable1")
        Call .AddDataField( .PivotFields("Sales"), _
                            "Sum of Sales", _
                            xlSum _
                          )
    End With

The above code is an example of creating a DataField only, showing the 3 pieces of information I need to be able to read out of a given PivotTable when I do not know how it was constructed.

In the example code above, how would I retrieve the Sales field from the PivotTable properties when I don't know it before hand? The Orientation is flagged as Hidden like all of the other unused but available Fields from the PivotTable Source Data.

The PivotTable has a DataPivotField property but I cannot find a list of its Fields anywhere.

答案1

得分: 1

如果您想在一个未知的工作簿中探索 PivotFields,您可以使用以下代码:

Public Sub PrintPivotTablesOfThisWorkbook()
    Dim WS As Worksheet: For Each WS In ThisWorkbook.Worksheets
        PrintPivotTablesOfWorksheet WS
    Next
End Sub

Public Sub PrintPivotTablesOfWorksheet(WS As Worksheet)
    Debug.Print "工作表名为 '" & WS.Name & "' 有 " & WS.PivotTables.Count & " 个 PivotTables"
    Dim PT As PivotTable: For Each PT In WS.PivotTables
        Debug.Print "  名为 '" & PT.Name & "' 位于 " & PT.TableRange2.Address(False, False, xlA1, True)
        Debug.Print "    有 " & PT.PageFields.Count & " 个 PageFields:"
        Dim PF As PivotField: For Each PF In PT.PageFields
            Debug.Print "      名为 '" & PF.Name & "' " & GetSourceNameClause(PF)
        Next
        Debug.Print "    有 " & PT.RowFields.Count & " 个 RowFields:"
        Dim RF As PivotField: For Each RF In PT.RowFields
            Debug.Print "      名为 '" & RF.Name & "' " & GetSourceNameClause(RF)
        Next
        Debug.Print "    有 " & PT.ColumnFields.Count & " 个 ColumnFields:"
        Dim CF As PivotField: For Each CF In PT.ColumnFields
            Debug.Print "      名为 '" & CF.Name & "' " & GetSourceNameClause(CF)
        Next
        Debug.Print "    有 " & PT.DataFields.Count & " 个 DataFields:"
        Dim DF As PivotField: For Each DF In PT.DataFields
            Debug.Print "      名为 '" & DF.Name & "' " & GetSourceNameClause(DF) & " " & GetConsolidateFunctionClause(DF)
        Next
    Next
End Sub

Public Function GetSourceNameClause(Target As PivotField) As String
    Dim Result As String: Result = ""
    Dim SN As Variant: SN = GetSourceNameSafely(Target)
    If IsNull(SN) Then
        Result = "没有 SourceName"
    Else
        Result = "有 SourceName '" & SN & "'"
    End If
    GetSourceNameClause = Result
End Function

Public Function GetSourceNameSafely(Target As PivotField) As Variant
    Dim Result As Variant: Result = Null
    On Error Resume Next
        Result = Target.SourceName
    On Error GoTo 0
    GetSourceNameSafely = Result
End Function

Public Function GetConsolidateFunctionClause(Target As PivotField) As String
    Dim Result As String: Result = ""
    Dim FN As String: FN = GetConsolidationFunctionAsString(Target.Function)
    If FN = "Invalid" Then
        Result = "没有任何函数"
    Else
        Result = "带有函数 " & FN
    End If
    GetConsolidateFunctionClause = Result
End Function

Public Function GetConsolidationFunctionAsString(ConsolidationFunction As XlConsolidationFunction) As String
    Dim Result As String: Result = "无效"
    On Error Resume Next
        Select Case ConsolidationFunction
        Case xlAverage
            Result = "xlAverage"
        Case xlCount
            Result = "xlCount"
        Case xlCountNums
            Result = "xlCountNums"
        Case xlDistinctCount
            Result = "xlDistinctCount"
        Case xlMax
            Result = "xlMax"
        Case xlMin
            Result = "xlMin"
        Case xlProduct
            Result = "xlProduct"
        Case xlStDev
            Result = "xlStDev"
        Case xlStDevP
            Result = "xlStDevP"
        Case xlSum
            Result = "xlSum"
        Case xlUnknown
            Result = "xlUnknown"
        Case xlVar
            Result = "xlVar"
        Case xlVarP
            Result = "xlVarP"
        End Select
    On Error GoTo 0
    GetConsolidationFunctionAsString = Result
End Function

将上述代码插入到一个模块后,只需在即时窗口中键入 PrintPivotTablesOfThisWorkbook,它将列出工作簿中的所有 PivotTables;或者键入 PrintPivotTablesOfWorksheet ActiveSheet 以仅列出活动工作表上的 PivotTables。

英文:

If you want to explore PivotFields in an unknown Workbook, you can use the code below:

Public Sub PrintPivotTablesOfThisWorkbook()
    Dim WS As Worksheet: For Each WS In ThisWorkbook.Worksheets
        PrintPivotTablesOfWorksheet WS
    Next
End Sub

Public Sub PrintPivotTablesOfWorksheet(WS As Worksheet)
    Debug.Print "Worksheet named '" & WS.Name & "' has " & WS.PivotTables.Count & " PivotTables"
    Dim PT As PivotTable: For Each PT In WS.PivotTables
        Debug.Print "  PivotTable named '" & PT.Name & "' at " & PT.TableRange2.Address(False, False, xlA1, True)
        Debug.Print "    has " & PT.PageFields.Count & " PageFields:"
        Dim PF As PivotField: For Each PF In PT.PageFields
            Debug.Print "      PivotField named '" & PF.Name & "' " & GetSourceNameClause(PF)
        Next
        Debug.Print "    has " & PT.RowFields.Count & " RowFields:"
        Dim RF As PivotField: For Each RF In PT.RowFields
            Debug.Print "      PivotField named '" & RF.Name & "' " & GetSourceNameClause(RF)
        Next
        Debug.Print "    has " & PT.ColumnFields.Count & " ColumnFields:"
        Dim CF As PivotField: For Each CF In PT.ColumnFields
            Debug.Print "      PivotField named '" & CF.Name & "' " & GetSourceNameClause(CF)
        Next
        Debug.Print "    has " & PT.DataFields.Count & " DataFields:"
        Dim DF As PivotField: For Each DF In PT.DataFields
            Debug.Print "      PivotField named '" & DF.Name & "' " & GetSourceNameClause(DF) & " " & GetConsolidateFunctionClause(DF)
        Next
    Next
End Sub

Public Function GetSourceNameClause(Target As PivotField) As String
    Dim Result As String: Result = ""
    Dim SN As Variant: SN = GetSourceNameSafely(Target)
    If IsNull(SN) Then
        Result = "without a SourceName"
    Else
        Result = "with SourceName '" & SN & "'"
    End If
    GetSourceNameClause = Result
End Function

Public Function GetSourceNameSafely(Target As PivotField) As Variant
    Dim Result As Variant: Result = Null
    On Error Resume Next
        Result = Target.SourceName
    On Error GoTo 0
    GetSourceNameSafely = Result
End Function

Public Function GetConsolidateFunctionClause(Target As PivotField) As String
    Dim Result As String: Result = ""
    Dim FN As String: FN = GetConsolidationFunctionAsSring(Target.Function)
    If FN = "Invalid" Then
        Result = "without any Function"
    Else
        Result = "with Function " & FN
    End If
    GetConsolidateFunctionClause = Result
End Function

Public Function GetConsolidationFunctionAsSring(ConsolidationFunction As XlConsolidationFunction) As String
    Dim Result As String: Result = "Invalid"
    On Error Resume Next
        Select Case ConsolidationFunction
        Case xlAverage
            Result = "xlAverage"
        Case xlCount
            Result = "xlCount"
        Case xlCountNums
            Result = "xlCountNums"
        Case xlDistinctCount
            Result = "xlDistinctCount"
        Case xlMax
            Result = "xlMax"
        Case xlMin
            Result = "xlMin"
        Case xlProduct
            Result = "xlProduct"
        Case xlStDev
            Result = "xlStDev"
        Case xlStDevP
            Result = "xlStDevP"
        Case xlSum
            Result = "xlSum"
        Case xlUnknown
            Result = "xlUnknown"
        Case xlVar
            Result = "xlVar"
        Case xlVarP
            Result = "xlVarP"
        End Select
    On Error GoTo 0
    GetConsolidationFunctionAsSring = Result
End Function

After inserting the above into a Module; simply type PrintPivotTablesOfThisWorkbook in the Immediate Window, and it will enumerate all PivotTables in the workbook; or type PrintPivotTablesOfWorksheet ActiveSheet to list only PivotTables on the ActiveSheet.

答案2

得分: -1

如果您提前知道名称,就很容易找到对象。但我希望通过阅读数据透视表属性来找到它。

如下所示,我已经取得了一些进展。但无论是数据透视表项还是数据透视表字段对象都没有正确公开“Function”属性,它应该是“xlSum”。在这两个对象中,“Function”属性都是一个错误。

为了简化下面的代码,我在每种情况下都使用了“Item(1)” 。在实际生产代码中,我会根据需要使用某种迭代逻辑。

Dim oPivotTable As PivotTable
Dim oPivotField As PivotField
Dim oPivotItem As PivotItem

    Set oPivotTable = ActiveSheet.PivotTables.Item(1)
    With oPivotTable
        With .DataPivotField.PivotItems
            Set oPivotItem = .Item(1)
            With oPivotItem
                Set oPivotField = oPivotTable.PivotFields.Item(oPivotItem.Name)
            End With
        End With
    End With

我终于找到了它!oPivotItem.DataRange.PivotField.Function返回了正确的值。此外,oPivotItem.DataRange.PivotField.SourceName返回字段名称。

因此,从原帖子中,这三个相关的值是:

  1. oPivotItem.DataRange.PivotField.SourceName
  2. oPivotItem.Name
  3. oPivotItem.DataRange.PivotField.Function
英文:

It is easy to find the object if you know the name before hand. But I want to be able to find it by reading the PivotTable properties.

I have made a little progress as shown by the code below. But neither the PivotItem or PivotField objects expose the Function correctly, which should be xlSum. In either object, the Function property is an error.

To simplify the code below, I used Item(1) in every case. In production code, I would have some kind of iteration logic as appropriate.

Dim oPivotTable As PivotTable
Dim oPivotField As PivotField
Dim oPivotItem As PivotItem

    Set oPivotTable = ActiveSheet.PivotTables.Item(1)
    With oPivotTable
        With .DataPivotField.PivotItems
            Set oPivotItem = .Item(1)
            With oPivotItem
                Set oPivotField = oPivotTable.PivotFields.Item(oPivotItem.Name)
            End With
        End With
    End With

I finally found it! oPivotItem.DataRange.PivotField.Function returns the correct value. Also, oPivotItem.DataRange.PivotField.SourceName returns the Field name.

So, from the original post, the 3 associated values are

    1. oPivotItem.DataRange.PivotField.SourceName, 
    2. oPivotItem.Name and
    3. oPivotItem.DataRange.PivotField.Function

huangapple
  • 本文由 发表于 2023年6月15日 19:34:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76482060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定