无法获得pivotitem类的可见属性

我有两套代码。 出于某种原因,在第一个我得到一个错误 ,而在第二个我不知道

1:

Dim pi As PivotItem Dim pf As PivotField Set pf = Sheets("Afname per school").PivotTables("Draaitabel3").PivotFields("school") For Each pi In pf.PivotItems If pi = "(leeg)" Then pi.Visible = False Else pi.Visible = True 'ERROR HERE End If Next pi 

2:

 Dim pi As PivotItem Dim pf As PivotField Set pf = Sheets("Afname per school").PivotTables("Draaitabel3").PivotFields("naam locatie") For Each pi In pf.PivotItems If InStr(pi, "BSO") Then pi.Visible = True Else pi.Visible = False End If Next pi 

我得到错误:“无法获得pivotitem类的可见属性”

我读了我应该解决以下几点:

这是由于数据透视表使用caching的数据透视表而不是当前数据透视表。 确保桌子不保留任何旧物品。 为此,请右键点击数据透视表,点击“数据”选项卡,并将“保留每个字段的数量”设置为“无”。 在VBA中这样做的代码是:

Dim pt As PivotTable

pt.PivotCache.MissingItemsLimit = xlMissingItemsNone

我试图用两种方法添加这一行代码:

 Dim pi As PivotItem Dim pf As PivotField Set pf = Sheets("Afname per school").PivotTables("Draaitabel3").PivotFields("school") pt.PivotCache.MissingItemsLimit = xlMissingItemsNone '1st TRY For Each pi In pf.PivotItems pt.PivotCache.MissingItemsLimit = xlMissingItemsNone '2nd TRY If pi = "(leeg)" Then pi.Visible = False Else pi.Visible = True End If Next pi 

这似乎并没有解决我的问题。

1.您的行/列字段中是否有多个字段?

因为这个问题可能是由此而来的。

数据透视字段中的所有数据透视项不总是显示/可显示的,因为它们在第二级中,这取决于第一级。 为了避免由于错误导致的代码中断,您必须使用 error handling程序

只有与第一级相应的PivotItem一起find的PivotItems是可以显示的(IE不能显示在你的数据中没有发生的情况)。

例如,您不能在第二级显示PivotItem“Car”

当第一级的PivotItem是“飞行模式的运输”。


2.刷新PivotCache

也就是说,您可以在使用MissingItemsLimit设置后MissingItemsLimit刷新数据透视表caching(检查您是否将Pt定义为数据透视表),以确保您拥有最新的数据:

 Set Pt = Sheets("Afname per school").PivotTables("Draaitabel3") Set pf = Pt.PivotFields("school") Pt.PivotCache.MissingItemsLimit = xlMissingItemsNone Pt.PivotCache.Refresh 

3.代码逻辑

之后查看你的代码,我有点困惑,因为你正在做的是隐藏一个特定的PivotItem,他的名字find,但你也试图显示每隔一个PivotItem!

我认为这是主要的问题,我会build议一个例程,只有很less的参数和error handling,像这样:

 Sub Hide_PivotItem(PivotTable_Object As PivotTable, _ PivotField_Name As String, _ ByVal PivotItem_Name As String, _ ByVal UnHide_All As Boolean) Dim Pt As PivotTable, _ Pi As PivotItem, _ Pf As PivotField Set Pt = PivotTable_Object Set Pf = Pt.PivotFields(PivotField_Name) Pt.PivotCache.MissingItemsLimit = xlMissingItemsNone Pt.PivotCache.Refresh If UnHide_All Then On Error Resume Next For Each Pi In Pf.PivotItems Pi.Visible = True Next Pi On Error GoTo 0 Else 'Don't unhide other items End If For Each Pi In Pf.PivotItems If Pi.Name <> PivotItem_Name Then Else Pi.Visible = False End If Next Pi End Sub 

Grafit:你发布的两个代码片段做了非常不同的事情。 第一个除了“(leeg)”的值之外,所有的东西都是可见的。 第二个使任何带有“BSO”的项目都可见,并隐藏其他一切。 这两个代码都有问题。

关于你的第一个代码片段,如果你想显示除了名为“(leeg)”之外的每个项目,那么不需要迭代PivotItems集合(这对于大型枢轴来说非常慢)。 相反,只要做到这一点:

pf.ClearAllFilters pf.PivotItems(“leeg”)。visible = false

至于你的第二个代码,那么是的错误可能是由MissingItemsLimit问题造成的,但是如果代码试图隐藏一个PivotItem,而在循环过程中当前没有其他PivotItems可见,也会发生。 例如,如果您的数据透视表过滤了只说一个项目,如“Aardvark”,那么因为“Aardvark”没有“BSO”,代码将试图隐藏它,然后将出错,因为在至less有一个PiovtItem必须始终保持可见。

所以你要做的就是在循环之前添加一行,使得PivotItems集合中的最后一个项目可见,这样你几乎可以保证一个项目在循环结束时保持可见。

(当然,如果“BSO”没有出现在任何PivotItems中,那么当你去处理最后一个项目时你仍然会得到这个错误)。

此外,无论何时迭代通过PivotITems集合,通常都要将PT.ManualUpdate设置为True,以便数据透视表不会在每个项目隐藏/取消隐藏之后更新数据透视表中的总计。 然后,在程序结束时,您再次将PT.ManualUpdate设置为False,然后告诉Excel“我已经完成…现在可以更新这些数据透视表总计”。 这通常会使你的日常工作速度产生惊人的差异。 在大型枢轴上,您将节省很多时间。

我写了一篇文章,在http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/上深入讨论这个问题,我build议你退房&#x3002;

– 编辑 – 这是一个例程清除数据透视表,以便只显示一个项目:

 Sub FilterPivot_PivotItem(pfOriginal As PivotField, _ Optional pi As PivotItem, _ Optional pfTemp As PivotField, _ Optional bDelete_wksTemp As Boolean = True, _ Optional bDelete_ptTemp As Boolean = False) ' If pfOriginal is a PageField, we'll simply turn .EnableMultipleItems to FALSE ' and select pi as a PageField ' Otherwise we'll ' * create a temp copy of the PivotTable ' * Make the field of interest a PageField ' * Turn .EnableMultipleItems to FALSE and select pi as a PageField ' * Add a Slicer to that PageField ' * Connect that Slicer to pfOriginal, which will force it instantly to sync. ' to pfTemp, meaning it shows just one item ' This is much faster than Iterating through a large PivotTable and setting all but ' one item to hidden, as outlined at http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/ Const sRoutine = "FilterPivot_PivotItem" Dim sc As SlicerCache Dim bSlicerExists As Boolean Dim ptOriginal As PivotTable Dim ptTemp As PivotTable Dim wksTemp As Worksheet Dim bDisplayAlerts As Boolean Dim lCalculation As Long Dim bEnableEvents As Boolean Dim bScreenUpdating As Boolean Dim TimeTaken As Date TimeTaken = Now() Set ptOriginal = pfOriginal.Parent With Application bScreenUpdating = .ScreenUpdating bEnableEvents = .EnableEvents lCalculation = .Calculation .ScreenUpdating = False .EnableEvents = False .Calculation = xlCalculationManual End With With pfOriginal If pi Is Nothing Then Set pi = .PivotItems(1) If .Orientation = xlPageField Then 'Great: we're dealing with a field in the FILTERS pane, which let us ' select a singe item easily .EnableMultiplePageItems = False .CurrentPage = pi.Name Else ' For non PageFields we'll have to use a temp PivotTable and Slicer to quickly clear ' all but one PivotItem. 'Check if pfOriginal already has a slicer connected ' If so, then we'll want to leave it in place when we're done bSlicerExists = Slicer_Exists(ptOriginal, pfOriginal) ' A temp PivotTable may aleady exist and have been passed in when the function was called ' Otherwise we'll need to create one. If pfTemp Is Nothing Then Set wksTemp = Sheets.Add Set ptTemp = ptOriginal.PivotCache.CreatePivotTable(TableDestination:=wksTemp.Range("A1")) Set pfTemp = ptTemp.PivotFields(.SourceName) 'Set the SaveData state of this new PivotTable the same as the original PivotTable '(By default it is set to True, and is passed on to the original PivotTable when a Slicer is connected) If ptTemp.SaveData <> ptOriginal.SaveData Then ptTemp.SaveData = ptOriginal.SaveData Else Set ptTemp = pfTemp.Parent 'Check if pfTemp already has a slicer conneced. If Not Slicer_Exists(ptTemp, pfTemp, sc) Then Set sc = ActiveWorkbook.SlicerCaches.Add(ptTemp, pfTemp) End If ptTemp.ManualUpdate = True With pfTemp .Orientation = xlPageField .EnableMultiplePageItems = False .CurrentPage = pi.Name End With ptTemp.ManualUpdate = False 'Connect slicer on pfTemp to pfOriginal to pass through settings, then disconnect it sc.PivotTables.AddPivotTable pfOriginal.Parent If Not bSlicerExists Then sc.Delete Else sc.PivotTables.RemovePivotTable pfTemp.Parent End If If bDelete_wksTemp Then bDisplayAlerts = Application.DisplayAlerts Application.DisplayAlerts = False wksTemp.Delete Application.DisplayAlerts = bDisplayAlerts ElseIf bDelete_ptTemp Then ptTemp.TableRange2.ClearContents End If End If End With With Application .ScreenUpdating = bScreenUpdating .EnableEvents = bEnableEvents .Calculation = lCalculation End With TimeTaken = Now() - TimeTaken Debug.Print Now() & vbTab & sRoutine & " took " & Format(TimeTaken, "HH:MM:SS") & " seconds." End Sub 

例如,您可能需要在一开始就设置为true

 .PivotItems(1) = true 

然后你可以使用一个条件循环来设置它应该是这个项目。