【问题标题】:Excel vba: error hiding calculated field in Pivot tableExcel vba:隐藏数据透视表中的计算字段时出错
【发布时间】:2009-09-07 08:38:58
【问题描述】:

我已经编写了几个 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 类的方向”。

【问题讨论】:

    标签: vba excel pivot-table


    【解决方案1】:

    在拉了很多头发之后,我找到了一种解决方法。 如果您添加多个数据透视字段(计算或其他方式),则 Excel 会创建一个名为“值”的分组字段。您可以将 PivotField("Values") 的方向属性设置为 xlHidden ,它会为这两个字段添加项目符号。所以如果要删除计算字段,只需添加一个非计算字段,将 PivotField("Values").orientation 设置为 xlHidden 即可。

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

    【讨论】:

    • 谢谢!过几天我试试。永远不会太晚:-)
    【解决方案2】:
    With ActiveSheet.PivotTables("PivottableName").PivotFields("Values")
        .PivotItems("CalcFieldName").Visible = False
    End With
    

    【讨论】:

    • 请不要发布仅代码的答案。解释它是如何工作的或为什么它是一个解决方案。否则,一旦您拥有所需的声誉,它更适合成为评论。 stackoverflow.com/help/whats-reputation
    • 看起来很有趣。我会试一试。谢谢
    • 谢谢,这正是我需要的。我有一个代码可以将透视数据字段值从项目切换到计算项目并返回,“.Orientation = xlHidden”的代码在项目上运行良好,但在计算项目上给出了错误消息。现在它的工作完美。
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      好吧,我会给你你需要的确认。似乎在“计算字段”上使用 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
      

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

      【讨论】:

      • 它不是最后一个可见的。我可以用手做,记录下来。它只是不重播。我发现的只是这个线程,表明这是一个已知的错误:social.msdn.microsoft.com/Forums/en-US/isvvba/thread/…
      • 删除有效,但这会删除计算字段,我无法重新添加。
      • 不明白为什么可以重新添加?
      • AMissico:是的,你是对的,我可以重新添加它。但我首先寻找一个“干净”的解决方案,然后再去解决方法。我真的认为这是一个 Excel 错误,事实上,但我想来确认或学习一些东西:-)
      • 如果您认为这是错误,请致电 Microsoft,我们不会收取任何费用。他们甚至可能有修复或经过验证的解决方法。考虑到您提供的链接,它看起来确实像一个错误。
      【解决方案5】:

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

      objTable.DataPivotField.Orientation = xlHidden
      

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

      快乐编码

      【讨论】:

      • 你能解释一下如何使用你的代码行吗?绝对看起来像是从更大的整个代码中获取的。
      • 是的,这个简单的代码行可以很好地隐藏所有以前使用过的Datafields,但它只有在您已经拥有至少 2(!) 个数据字段的情况下才有效。如果你只有一个或没有,那么你会得到一个错误。所以事实上,对所有数据字段进行循环会更好。
      【解决方案6】:

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

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

      我假设该字段似乎仅在您的 xlDataField 位置有两个或多个字段时才存在。

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

      附:您的代码仍然不能仅使用一个计算数据字段

      【讨论】:

        【解决方案7】:

        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
        

        【讨论】:

          【解决方案8】:

          我不认为这是一个 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
          

          【讨论】:

          • "您不能隐藏数据透视字段中的最后一项。"这不是我说的吗?
          • 是的,但问题是关于 PivotField,而不是 PivotItem。所以我认为你提到的“这个项目”是指@Patrick Honorez 的代码,所以我只是想澄清一下。
          • @DaveParillo,知道了。如果我说“您不能隐藏此数据透视字段,因为它必须至少有一个可见项。作为参考,在代码中,此条件会产生错误。在 Excel 的用户界面中,会提示用户“必须选择至少一个项目才能在此字段中显示。”如果他们取消选择字段的所有项目。
          【解决方案9】:

          我遇到了和你一样的问题。 看来我将不得不删除计算字段并读取它而不是隐藏/显示它。

          【讨论】:

          • 很高兴知道。这似乎是 Excel“不一致”的唯一解决方案。
          【解决方案10】:

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

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

          场景:数据透视表覆盖范围 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
          

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

          【讨论】:

          • Jeremy B:这不是一个真正的计算字段。如果您已经有单位字段和成本字段,那么有一个金额字段 = 单位 * 成本,这是一个计算字段。不过还是谢谢你的诡计。
          【解决方案11】:

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

          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
          

          【讨论】:

          • 看起来真的很有趣!我会检查并回来找你。感谢您的信息。
          • 您对数据字段的评论是正确的,但不幸的是,这并不能解决 calculated 字段的问题(请参阅问题编辑)
          • 嗨,我不明白,数据字段是计算字段,我将此代码应用于各种数据透视表,它会清除所有数据字段/数据透视字段/计算字段。注意它不会删除数据透视表,只会清除它。你试过我的代码还是不行?
          【解决方案12】:

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

          你试过pt.CalculatedFields("MyField").Orientation = xlHidden吗?

          【讨论】:

          • 我都试过了。我已经在其他领域做到了这一点,没有问题。它只会对计算字段产生错误。并且奇怪的想法是录制的宏不会重播!
          • 在录制宏时,您是否准确地选择了要在数据透视表中的单元格,还是选择了整个工作表或整个列?我注意到,当您以这种方式选择范围时,宏记录不正确。
          • @DaveParillo:我录好了。我已经成功地为 2 个“真实”字段编码,并且我复制/粘贴了相同的代码。问题只是发生在计算字段上。
          【解决方案13】:

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

          如果您将数据存储在数据模型中,则使用 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
          

          【讨论】:

            【解决方案14】:

            感谢@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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-06-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多