繁体   English   中英

Excel vba:在数据透视表中隐藏计算字段时出错

[英]Excel vba: error hiding calculated field in Pivot table

我已经编写了几个 Subs 来显示/隐藏数据透视表中的字段。 现在我正尝试对计算字段执行相同操作,但在隐藏它时出现错误。 我从记录器中取出我的代码,记录器的代码也在最后一行停止。 我用谷歌搜索了错误消息,但没有得到严重的结果。

Sub PrRemove()
    'remove PR
    Dim pt As PivotTable
    Set pt = ActiveSheet.PivotTables("MyPivot")
    pt.PivotFields("MyField").Orientation = xlHidden   '<- here is the error
End Sub

如果 MyField 是普通字段(不是计算字段),则相同的代码可以正常工作。
我正在使用带有 SP2 的 Excel 2007。
有什么线索吗?

2010 年 6 月 17 日编辑:我也尝试使用 pt.DataFields 而不是 pt.PivotFields,具有完全相同的行为。 错误消息显示“无法设置 PivotField 类的方向”。

With ActiveSheet.PivotTables("PivottableName").PivotFields("Values")
    .PivotItems("CalcFieldName").Visible = False
End With

经过多次拉头发后,我找到了解决方法。 如果您添加多个数据透视字段(计算或其他),excel 会创建一个名为值的分组字段。 您可以将 PivotField("Values") 的 orientation 属性设置为 xlHidden,它会突出显示两个字段。 所以如果你想删除计算字段,只需添加一个非计算字段,将 PivotField("Values").orientation 设置为 xlHidden 即可。

没有人说它会很漂亮......

我想轻松删除数据字段(计算字段或不),就像手动完成一样。

我终于找到了这个解决方案(Excel 2010):

Set pt = ActiveSheet.PivotTables("mypivottable")
For Each pi In pt.DataPivotField.PivotItems
    pi.Visible = False
Next

好吧,我会给你你需要的确认。 似乎在“计算字段”上使用Orientation属性是行不通的,我不得不承认这是一个错误,而不是常见的“使用”错误。 我能够复制“隐藏/显示”该字段,而不必删除(“删除”)计算字段。 这允许用户在您以编程方式“隐藏”字段后从字段列表中物理拖动计算字段。 这不是一个糟糕的解决方案,因为它复制了用户界面。 (使用 Excel 2003。)

'2009.09.25 AMJ
'work around for
'   1004, Unable to set the Orientation property of the PivotField class
'when setting orientation property to hidden of calculated field, as in
'   ActiveSheet.PivotTables("PivotTable1").PivotFields("Sum of Field1").Orientation = xlHidden

Public Sub Hide()
'hide the data without removing the calculated field
'   this allows the user to physically drag the
'       calculated field from the field list once we
'       have "hidden" it programmatically.
'   if we use the "delete" method, the field is removed
'       from the pivot table and the field list

    Dim oWS As Worksheet
    Dim oPT As PivotTable
    Dim oPF As PivotField
    Dim oPI As PivotItem

    Set oWS = ActiveSheet
    Set oPT = oWS.PivotTables(1)

    For Each oPF In oPT.DataFields
        If oPF.SourceName = "Field1" Then
            'Stop
            Exit For
        End If
    Next

    Set oPI = oPF.DataRange.Cells(1, 1).PivotItem
    'oPI.DataRange.Select
    oPI.Visible = False

End Sub

Public Sub Show()
'show just reads the pivot field to the data fields

    Dim oWS As Worksheet
    Dim oPT As PivotTable
    Dim oPF As PivotField

    Set oWS = ActiveSheet
    Set oPT = oWS.PivotTables(1)

    For Each oPF In oPT.PivotFields
        If oPF.SourceName = "Field1" Then
            'Stop
            Exit For
        End If
    Next

    oPT.AddDataField oPF

End Sub

[原始答案] 很可能您无法隐藏此项目,因为它是最后一个可见的项目。 相反,请尝试将其删除。

这是我今天发现的一个小解决方法,同样不是很优雅,但至少它不需要太多代码,它会隐藏所有字段,您需要在之后重新显示您想要的字段:

objTable.DataPivotField.Orientation = xlHidden

如果 excel 出于某种原因认为数据透视字段为空,您可能会遇到错误,但要解决此问题,只需在上述语句之前添加另一个字段作为数据字段即可。 还要确保它的字母 l 而不是 xlHidden vba 默认字体中的数字 1 让它们看起来非常相似。

快乐编码

似乎要隐藏计算字段,您需要先隐藏一个名为“值”的数据透视字段。

PivotTable(1).PivotFields("Values").Orientation = xlHidden
For Each PF In PT.DataFields
    PF.Orientation = xlHidden
Next PF

我假设只有在 xlDataField 位置有两个或更多字段时,该字段才似乎存在。

感谢 Alinboss 为我指明了正确的方向。 我确定我之前尝试过您的方法但失败了 - 结果证明顺序很重要!

Ps 您的代码仍然不适用于仅一个计算数据字段

Laurent Bosc 的代码已签出,所以我投了赞成票。 我的完整代码包括在隐藏所有数据后添加数据。 代码放在 Sheet1(Sheet1) 上。

Private Sub Refresh_Pivot()

    Dim NewMetric As String
    Dim pt As PivotTable, objDataField As Object
    NewMetric = "your_custom_metric"

'-------update pivot table 1, hide all elements including calculated field----

    Application.EnableEvents = False
    Set pt = Sheet1.PivotTables("PivotTable1")

    For Each Pi In pt.DataPivotField.PivotItems
        Pi.Visible = False
    Next

'--------add a new data field to the pivot table----------------------------

    With pt
        .AddDataField.PivotFields(NewMetric), "Sum of " & NewMetric, xlSum
    End With

    Application.EnableEvents = True

End Sub

您是否更改了计算字段的名称? 它最初是“MyField 的总和”吗? 尝试查看 SourceName 属性,看看使用它是否不同。

您是否尝试过pt.CalculatedFields("MyField").Orientation = xlHidden

我不认为这是一个 excel 错误,我认为这是一个“功能”。 ;-)

回复:@AMissico,在 excel 中隐藏数据透视表中的所有字段没有问题,但他可能在谈论项目 - 你不能隐藏数据透视表中的最后一项。

这是我经常用来做你想做的事情的代码。 这些宏是在 Excel 2002 和 2003 上开发的。我不隐藏 CalculatedFields,而是删除它们。

' Hide all fields.
' @param ThePivotTable to operate upon.
Sub HidePivotFields(ByVal ThePivotTable As PivotTable)
    Dim pField As PivotField
    For Each pField In ThePivotTable.CalculatedFields
        pField.Delete
    Next pField
    For Each pField In ThePivotTable.PivotFields
        pField.Orientation = xlHidden
    Next pField

    Set pField = Nothing
End Sub

' Removes FieldName data from ThePivotTable
Sub HideField(ByVal ThePivotTable As PivotTable, _
              ByVal FieldName As String)
    If FieldExists(ThePivotTable, FieldName) = True And _
       CalculatedFieldExists(ThePivotTable, FieldName) = False Then
        ThePivotTable.PivotFields(FieldName).Orientation = xlHidden
    End If
End Sub

' Returns True if FieldName exists in ThePivotTable
'
' @param ThePivotTable to operate upon.
' @param FieldName the name of the specific pivot field.
Function FieldExists(ByVal ThePivotTable As PivotTable, _
                     ByVal FieldName As String) As Boolean
    Dim pField As PivotField

    For Each pField In ThePivotTable.PivotFields
        If pField.SourceName = FieldName Then
            FieldExists = True
            Exit For
        End If
    Next pField

    Set pField = Nothing
End Function

' Checks if the field FieldName is currently a member of the
' CalculatedFields Collection in ThePivotTable.
' @return True if a CalculatedField has a SourceName matching the FieldName
' @return False otherwise
Function CalculatedFieldExists(ByVal ThePivotTable As PivotTable, _
                               ByVal FieldName As String) As Boolean
    Dim pField As PivotField

    CalculatedFieldExists = False

    For Each pField In ThePivotTable.CalculatedFields
        If pField.SourceName = FieldName Then
            CalculatedFieldExists = True
        End If
    Next pField
    Set pField = Nothing
End Function

' Returns a Pivot Field reference by searching through the source names.
'
' This function is a guard against the user having changed a field name on me.
' @param ThePivotTable to operate upon.
' @param FieldName the name of the specific pivot field.
Function GetField(ByVal ThePivotTable As PivotTable, _
                  ByVal FieldName As String) As PivotField
    Dim pField As PivotField

    For Each pField In ThePivotTable.PivotFields
        If pField.Name <> "Data" Then
            If pField.SourceName = FieldName Then
                Set GetField = pField
                Exit For
            End If
        End If
    Next pField

    Set pField = Nothing
End Function

' Counts the number of currently visible pivot items in a field.
' @param ThePivotItems the collection of pivot itemns in a field.
' @return the count of the visible items.
Function PivotItemCount(ByVal ThePivotItems As PivotItems) As Long
    Dim pItem As PivotItem
    Dim c As Long

    For Each pItem In ThePivotItems
        If pItem.Visible = True Then c = c + 1
    Next pItem
    PivotItemCount = c
    Set pItem = Nothing
End Function

' Hides a single pivot item in a pivot field, unless it's the last one.
' @param FieldName pivot field containing the pivot item.
' @param ItemName pivot item to hide.
Sub HidePivotItem(ByVal ThePivotTable As PivotTable, _
                  ByVal FieldName As String, _
                  ByVal ItemName As String)
    Dim pField As PivotField

    Set pField = GetField(ThePivotTable, FieldName)
    If Not pField Is Nothing Then
        If PivotItemCount(pField.PivotItems) > 1 Then
            pField.PivotItems(ItemName).Visible = False
        End If
    End If

    Set pField = Nothing
End Sub

我和你有完全一样的问题。 看起来我将不得不删除计算字段并重新添加它而不是隐藏/显示它。

我第一次尝试隐藏计算字段时无意中发现了一个解决方法,所以我想在这里分享它:

您可以不修改方向属性,而是指示代码选择数据透视表中包含要隐藏的计算字段标题的单元格,然后删除选择。 只要您在表中已有另一个数据字段,这就有效。 下面的例子:

场景:数据透视表涵盖范围 A1:G10。 计算字段“Margin”已经在表中,您想要添加数据字段“Sales”并删除“Margin”计算字段。

要执行的代码:

'Add Sales data field
 ActiveSheet.PivotTables(Pname).AddDataField ActiveSheet.PivotTables( _
    Pname).PivotFields("SALES"), "Sum of SALES", xlSum

 'At this point, the datafield titles are in vertically adjacent rows, named "Sum
 'of Margin" and "Sum of Sales" at locations B3 and B4 respectively.

 'Remove the "Sum of Margin" calculated field
  Range("B3").Delete

不知道为什么会这样,但我很高兴我们至少可以使用它!

幸运的是,有一种非常简单的方法可以隐藏数据字段。 你们都错误地把数据透视表字段和数据字段混淆了。 我正在展示一段清空数据透视表的代码,无论数据透视表中最初有多少数据透视表字段/数据字段:

Sub Macro1()

Dim p As PivotTable
Dim f As PivotField

Set p = ActiveSheet.PivotTables(1)

For Each f In p.PivotFields

If f.Orientation <> xlHidden Then
    f.Orientation = xlHidden
End If

Next f

For Each f In p.DataFields

If f.Orientation <> xlHidden Then
    f.Orientation = xlHidden
End If

Next f

End Sub

我知道有点晚了,但我发现这个问题还没有得到肯定的回答,我也遇到了同样的问题,很难找到有用的信息。 所以,我希望这篇文章可以帮助某人......

如果您将数据存储在数据模型中,那么请使用 CubeFields 而不是 PivotFields。 我遇到了同样的问题,我尝试了一个没有数据模型的简单工作簿,并且我的代码运行良好(使用 PivotFields)。 它只在带有数据模型的工作簿中返回错误。 所以,我做了这个改变并繁荣:它奏效了! 我的建议是使用以下代码:

Sub PrRemove()
'remove PR
Dim pt As PivotTable
Set pt = ActiveSheet.PivotTables("MyPivot")
pt.CubeFields("MyField").Orientation = xlHidden   '<- here is the error
End Sub

感谢@user4709164 的回答,我得到了这段代码,它对我来说工作得很好:

我的数据透视表列都以 X 或 Y 结尾以指示轴,因此我使用最后一个字符作为字段标题。

Public Sub PivotFieldsChange()
Dim ValType As String, param As String
Dim pf As PivotField
Dim pt As PivotTable

Application.ScreenUpdating = False
Sheet = "mysheet"
'select between % calculated column or normal column
If Range("Z1").Value = 1 Then
    ValType = "%"
Else: ValType = ""
End If
Application.EnableEvents = False
For Each pt In Sheets(Sheet).PivotTables
    Select Case pt.Name
        Case "case1": param = "param1"
        Case "case2": param = "param2"
        Case "case3": param = "param3"
        Case Else: GoTo line1
End Select
pt.PivotFields("Values").PivotItems("X").Visible = False
pt.PivotFields("Values").PivotItems("Y").Visible = False

pt.PivotFields (param & ValType & "_X")
pt.PivotFields(param & ValType & "_X").Orientation = xlDataField
pt.PivotFields (param & ValType & "_Y")
pt.PivotFields(param & ValType & "_Y").Orientation = xlDataField
For Each pf In pt.DataFields
    pf.Function = xlAverage
    pf.Caption = Right(pf.Caption, 1)

Next
line1:
Next pt
Application.EnableEvents = True
End Sub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM