Loop through PivotItems: runtime error 91 - vba

I have a dataset in a worksheet that can be different every time. I am creating a pivottable from that data, but it is possible that one of the PivotItems is not there. For example:
.PivotItems("Administratie").Visible = False
If that specific value is not in my dataset, the VBA script fails, saying that it can't define the item in the specified Field. (error 1004)
So I thought a loop might work.
I have the following:
Dim pvtField As PivotField
Dim pvtItem As PivotItem
Dim pvtItems As PivotItems
For Each pvtItem In pvtField.pvtItems
pvtItem.Visible = False
Next
But that gives me an 91 error at the For Each pvtItem line:
Object variable or With block variable not set
I thought I declared the variables well enough, but I am most likely missing something obvious...

I've got it! :D
Dim Table As PivotTable
Dim FoundCell As Object
Dim All As Range
Dim PvI As PivotItem
Set All = Worksheets("Analyse").Range("A7:AZ10000")
Set Table = Worksheets("Analyse").PivotTables("tablename")
For Each PvI In Table.PivotFields("fieldname").PivotItems
Set FoundCell = All.Find(PvI.Name)
If FoundCell <> "itemname" Then
PvI.Visible = False
End If
Next
woohoo
Thanks to MrExcel, the answer was there after all, though deeply buried.

For Each pvtField In Worksheets("my_sheet").PivotTables("my_table").PivotFields
For Each pvtItem In pvtField.PivotItems
Debug.Print vbTab & pvtItem.Name & ".Visible = " & pvtItem.Visible
/*.PivotItems(pvtItem).Visible = False*/
Next
Next
.PivotItems("certain_Item").Visible = True
That doesn't work still... all the variables are still visible. No error is shown, it compiles yet the values are still there.
The commented line I added there was my own "invention" but it's is not valid.
Edit: Quicky question: Can I use an IF statement to check if a certain PivotItem is actually in the PivotTable Data? Something like
If PivotItem("name_of_the_thing") = present Then {
do_something()
}

When I implement the code posted by Patrick, an -
Unable to set the visible property of the PivotItem class
- error is thrown.
Microsoft admits there's a bug: M$ help
But just hiding the line... is not an option ofcourse.

Try something like this:
Public Function Test()
On Error GoTo Test_EH
Dim pvtField As PivotField
Dim pvtItem As PivotItem
Dim pvtItems As PivotItems
' Change "Pivot" to the name of the worksheet that has the pivot table.
' Change "PivotTable1" to the name of the pivot table; right-click on the
' pivot table, and select Table Options... from the context menu to get the name.
For Each pvtField In Worksheets("Pivot").PivotTables("PivotTable1").PivotFields
Debug.Print "Pivot Field: " & pvtField.Name
For Each pvtItem In pvtField.VisibleItems
pvtItem.Visible = False
Next
Next
Exit Function
Test_EH:
Debug.Print pvtItem.Name & " error(" & Err.Number & "): " & Err.Description
Resume Next
End Function
If you want a function to just test for the existence of a pivot item, you can use something like this:
Public Function PivotItemPresent(sName As String) As Boolean
On Error GoTo PivotItemPresent_EH
PivotItemPresent = False
For Each pvtField In Worksheets("Pivot").PivotTables("PivotTable1").PivotFields
For Each pvtItem In pvtField.VisibleItems
If pvtItem.Name = sName Then
PivotItemPresent = True
Exit Function
End If
Next
Next
Exit Function
PivotItemPresent_EH:
Debug.Print "Error(" & Err.Number & "): " & Err.Description
Exit Function
End Function
You can call this from your code like this:
If PivotItemPresent("name_of_the_thing") Then
' Do something
End If

The error is thrown at the end of the loop.
I combined both answers from Patrick into the following:
With ActiveSheet.PivotTables("Table").PivotFields("Field")
Dim pvtField As Excel.PivotField
Dim pvtItem As Excel.PivotItem
Dim pvtItems As Excel.PivotItems
For Each pvtField In Worksheets("Sheet").PivotTables("Table").PivotFields
For Each pvtItem In pvtField.PivotItems
If pvtItem.Name = "ItemTitle" Then
pvtField.PivotItems("ItemTitle").Visible = True
Else
pvtField.PivotItems(pvtItem.Name).Visible = False
End If
Next
Next
End With
If the Item matches a particular string, that Item is set True. Else; Item set False. At the False condition the error is thrown.
I know there is exactly one match for the True condition. Though when I 'F8' my way through the macro, the True condition is never entered...
And that explains the error, everything is set False. (thanks Patrick!)
Leads me to the question... what exactly IS a PivotItem?
Idea of the thing:
It solves (or should solve) the following: a set of Data with a variable size where, for this specific table, one column is of interest. From that column I need the count of a value and have that put in a table. There are some conditions to the table, and a combination with another column is needed as well, so PivotTable is the best solution.
The problem is: in some datasets that one specific value does not appear. The values that DO appear are different every time.

The PivotItems are the individual values in a field (column, row, data). I think of them as the "buckets" that hold all the individual data items you want to aggregate.
Rather than go through all the pivot table fields (column, row, and data), you can just go through the fields you're interested in. For example, this code will show only the specified pivot items for the specified field:
Public Sub ShowInPivot(Field As String, Item As String)
On Error GoTo ShowInPivot_EH
Dim pvtField As PivotField
Dim pvtItem As PivotItem
Dim pvtItems As PivotItems
For Each pvtItem In Worksheets("Pivot").PivotTables("PivotTable1").PivotFields(Field).PivotItems
If pvtItem.Name = Item Then
pvtItem.Visible = True
Else
pvtItem.Visible = False
End If
Next
Exit Sub
ShowInPivot_EH:
Debug.Print "Error(" & Err.Number & "): " & Err.Description
Exit Sub
End Sub
Suppose I have a pivot table showing the count of issues per customer release and where they were detected in our SDLC. "Customer" and "Release" are column fields and "Phase" is a row field. If I wanted to limit the pivot table to counting issues for CustomerA, Release 1.2 during QA I could use the sub above like this:
ShowInPivot "Customer", "CustomerA"
ShowInPivot "Release", "1.2"
ShowInPivot "Phase", "QA"

You can't say ".PivotItems(pvtItem).Visible" outside a "With" block. Say "pvtField.PivotItems(pvtItem.Name).Visible = False" instead.
I also edited my original answer to include error handling for when Excel can't set the Visible property. This happens because the Pivot table needs at least one row field, one column field and one data item, so the last of each of these can't be made invisible.
You 'll also get the 1004 errror when trying to access a pivot item that is already invisible; I think you can ignore those.

I had same error message too when trying to set pivotitem visible true and false .. this had worked previously, but wasn't working any more ... i was comparing two values, and had not explicitly changed string to integer for comparison .. doing this made error disappear..
.. so if you get this message, check if any values being compared to make the item visible or not are being compared properly .. otherwise pivotitem is null and it can't make that visible or not.

I had an error that said "unable to set the visible property of the pivot item class"
at this line:
For Each pi In pt.PivotFields("Fecha").PivotItems
If pi.Name = ffan Then
pi.Visible = True
Else
pi.Visible = False '<------------------------
End If
Next pi
Then i read on internet that I had to sort manual and then clear the cache. i did that but the error still appeared..... then i read that it was because i had date on that pivot field so i change it firs my colum to general number then the date i wanted to set visible i change it to general number too. then no problem!!!!!!!!!!!!!!.... here it is.... i hope this can be helpfull because i was desperate!!!
Dim an As Variant
an = UserForm8.Label1.Caption 'this label contains the date i want to see its the pivot item i want to see of my pivot fiel that is "Date"
Dim fan
fan = Format(an, "d m yyyy")
Dim ffan
ffan = Format(fan, "general number")
Sheets("Datos refrigerante").Activate 'this is the sheet that has the data of the pivottable
Dim rango1 As Range
Range("B1").Select
Range(Selection, Selection.End(xlDown)).Select
Set rango1 = Selection
ActiveSheet.Cells(1, 1).Select
rango1.Select
Selection.NumberFormat = "General" 'I change the format of the column that has all my dates
'clear the cache
Dim pt As PivotTable
Dim ws As Worksheet
Dim pc As PivotCache
'change the settings
For Each ws In ActiveWorkbook.Worksheets
For Each pt In ws.PivotTables
pt.PivotCache.MissingItemsLimit = xlMissingItemsNone
Next pt
Next ws
'refresh all the pivot caches
For Each pc In ActiveWorkbook.PivotCaches
On Error Resume Next
pc.Refresh
Next pc
'now select the pivot item i want
Dim pi As PivotItem
Set pt = Sheets("TD Refrigerante").PivotTables("PivotTable2")
'Sets Pivot Table to Manual Sort so you can manipulate PivotItems in PivotField
pt.PivotFields("Fecha").AutoSort xlManual, "Fecha"
'Speeds up code dramatically
pt.ManualUpdate = True
For Each pi In pt.PivotFields("Fecha").PivotItems
If pi.Name = ffan Then
pi.Visible = True
Else
pi.Visible = False
End If
Next pi
pt.ManualUpdate = False
pt.PivotFields("Fecha").AutoSort xlAscending, "Fecha"

Use Caption instead of Name.
For Each pvtItem In ActiveSheet.PivotTables("PivotTable1").PivotFields("Something").PivotItems
If Not pvtItem.Caption = "Example" Then
pvtItem.Visible = False
End If
Next

Related

VBA filtering dates

This is my function, the code stops on the line "If pitem.visible=True" on the first iteration (line 17). While the code is running, I always have visible items int the field.
The code is not even setting any property to visible and it's working very well if I filter anything other than a date.
Function tableau()
Dim fld As PivotField
Dim pitem As PivotItem
Dim i As Long
Dim arr() As Variant
Dim a As String
Dim pvt As String
pvt = "PivotTable"
Sheets("Données").ListObjects("table1").AutoFilter.ShowAllData
Sheets("PivotTableSheet").Activate
Sheets("PivotTableSheet").PivotTables(pvt).ManualUpdate = True
Sheets("PivotTableSheet").PivotTables(pvt).PivotFields("Date").EnableMultiplePageItems = True
For Each fld In Sheets("PivotTableSheet").PivotTables(pvt).PivotFields
If fld.Orientation <> xlHidden And (fld.Orientation = xlPageField) Then 'loop through filtered pivot fields
i = 1
For Each pitem In fld.PivotItems 'loop through visible items in filtered pivot fields
If pitem.Visible = True Then
ReDim Preserve arr(1 To i) As Variant
arr(i) = pitem
i = i + 1
End If
Next pitem
Sheets("Données").ListObjects("table1").Range.AutoFilter Field:=TRVFILTRE(fld.Name), Criteria1:=arr, Operator:=xlFilterValues
End If
Next fld
Sheets("PivotTableSheet").PivotTables(pvt).ManualUpdate = False
End Function
When iterating over PivotItems, there's a couple of bottlenecks and gotchas that you want to avoid. See my post at http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/ for more on this.
Among other things, you want to set the PivotTable's ManualUpdate property to TRUE while you do the iteration and then back to FALSE when you're done. Otherwise Excel will try to update the PivotTable each time you change the visibility of a PivotItem. And you also want to ensure that at least one item remains visible at all times. I use something like this:
Option Explicit
Sub FilterPivot()
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim i As Long
Dim vItem As Variant
Dim vItems As Variant
Set pt = ActiveSheet.PivotTables("PivotTable1") '<= Change to match your PivotTable
Set pf = pt.PivotFields("CountryName") '<= Change to match your PivotField
vItems = Array("FRANCE", "BELGIUM", "LUXEMBOURG") '<= Change to match the list of items you want to remain visible
pt.ManualUpdate = True 'Stops PivotTable from refreshing after each PivotItem is changed
With pf
'At least one item must remain visible in the PivotTable at all times, so make the first
'item visible, and at the end of the routine, check if it actually *should* be visible
.PivotItems(1).Visible = True
'Hide any other items that aren't already hidden.
'Note that it is far quicker to check the status than to change it.
' So only hide each item if it isn't already hidden
For i = 2 To .PivotItems.Count
If .PivotItems(i).Visible Then .PivotItems(i).Visible = False
Next i
'Make the PivotItems of interest visible
On Error Resume Next 'In case one of the items isn't found
For Each vItem In vItems
.PivotItems(vItem).Visible = True
Next vItem
On Error GoTo 0
'Hide the first PivotItem, unless it is one of the countries of interest
On Error Resume Next
If InStr(UCase(Join(vItems, "|")), UCase(.PivotItems(1))) = 0 Then .PivotItems(1).Visible = False
If Err.Number <> 0 Then
.ClearAllFilters
MsgBox Title:="No Items Found", Prompt:="None of the desired items was found in the Pivot, so I have cleared the filter"
End If
On Error GoTo 0
End With
pt.ManualUpdate = False
End Sub
You don't have to iterate through PivotItems if all you want to do is make each PivotItem visible. Instead, just use the .ClearAllFilters method.
Something like:
With Sheets("PivotTableSheet").PivotTable("PivotTable").PivotFields("Date")
.ClearAllFilters
.CurrentPage = "(All)"
End With

Filter items with certain text in a Pivot Table using VBA

I've been trying to build a code to filter all items within a Pivot Table which contain a specific text fragment. I initially imagined I could use asterisks (*) to indicate any string before or after my text, but VBA reads that as a character instead. This is necessary to display the Pivot Table array in a Userform Listbox. Look what I tried:
Sub FilterCstomers()
Dim f As String: f = InputBox("Type the text you want to filter:")
With Sheets("Customers Pivot").PivotTables("Customers_PivotTable")
.ClearAllFilters
.PivotFields("Concatenation for filtering").CurrentPage = "*f*"
End With
End Sub
Try the code below to filter all items in field "Concatenation for filtering" that are Like wild card * and String f received from InputBox.
Option Explicit
Sub FilterCstomers()
Dim PvtTbl As PivotTable
Dim PvtItm As PivotItem
Dim f As String
f = InputBox("Type the text you want to filter:")
' set the pivot table
Set PvtTbl = Sheets("Customers Pivot").PivotTables("Customers_PivotTable")
With PvtTbl.PivotFields("Concatenation for filtering")
.ClearAllFilters
For Each PvtItm In .PivotItems
If PvtItm.Name Like "*" & f & "*" Then
PvtItm.Visible = True
Else
PvtItm.Visible = False
End If
Next PvtItm
End With
End Sub
Why not just:
.PivotFields("PivotFieldName").PivotFilters.Add2 Type:=xlCaptionContains, Value1:="X"
You can tweak Shai's answer to significantly speed things up, by:
removing the TRUE branch of the IF as it is not needed
setting ManualUpdate to TRUE while the code executes, to stop the
PivotTable from recalculating each time you change the visible
status of any PivotItems.
Turning off screen updating and calculation (in case there are
volatile functions in the workbook) until you are done
You probably also want to put an Option CompareText in there if you want your comparisons to be case insensitive.
And you probably want some error handling in case the user types something that doesn't exist in the PivotTable.
You might want to give my blogpost on this stuff a read, because PivotTables are very slow to filter, and it discusses many ways to speed things up
Here's a reworked example of Shai's code:
Option Explicit
Option Compare Text
Sub FilterCstomers()
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim f As String
f = InputBox("Type the text you want to filter:")
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
Set pt = Sheets("Customers Pivot").PivotTables("Customers_PivotTable")
Set pf = pt.PivotFields("Concatenation for filtering")
pt.ManualUpdate = True
With pf
.ClearAllFilters
On Error GoTo ErrHandler
For Each pi In .PivotItems
If Not pi.Name Like "*" & f & "*" Then
pi.Visible = False
End If
Next pi
End With
ErrHandler:
If Err.Number <> 0 Then pf.ClearAllFilters
pt.ManualUpdate = False
On Error GoTo 0
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub

Getting "Unable to set CurrentPage property of PivotField class" error

I'm trying to use VBA to automatically update the pivot table filter based off the user's selection from a cell entry. I believe everything is working correctly up to line 11 which says "Field.CurrentPage = NewCat". This is where the issue lies. The code clears my filter as instructed in the previous line but when it gets to the code instructing it to select the new data I get the error that reads "Run-time error 1004. Unable to set CurrentPage property of PivotField class".
Below is the what I have so far and I'm just looking how to revise row 11 so it selects the new input to use in the pivot table filter. I appreciate any help I can get on this. I'm very new to vba & have struggled with this for far too long!
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, Range("C3:C4")) Is Nothing Then Exit Sub
Dim pt As PivotTable
Dim Field As PivotField
Dim NewCat As String
Set pt = Worksheets("Pivot").PivotTables("PivotTable1")
Set Field = pt.PivotFields("[Range].[Site].[Site]")
NewCat = Worksheets("Interface").Range("C3").Value
With pt
Field.ClearAllFilters
Field.CurrentPage = NewCat
pt.RefreshTable
End With
End Sub
Hoping this will be beneficial to someone who is experiencing the same "1004 error" when attempting to set the "CurrentPage" property of the PivotField class.
For me, it finally worked when I replaced the "CurrentPage" property with "CurrentPageName" as such:
With pf
.ClearAllFilters
MsgBox "The PivotField is: " & pf.Value
MsgBox "The current PivotField value is: " & .CurrentPageName
.CurrentPageName = NewCat
End With
My pivot table have what was called "page level filters":
enter image description here
The answer is just a matter of syntax.
If you change:
With pt
Field.ClearAllFilters
Field.CurrentPage = NewCat
pt.RefreshTable
End With
to:
With Field
.ClearAllFilters
.CurrentPage = NewCat
End With
pt.RefreshTable
It will work.
Notice, that I work directly with the Field in the With Block.
To illustrate further, if you change it to the following, it will work as well:
With pt.PivotFields(Field.Name)
.ClearAllFilters
.CurrentPage = NewCat
End With
pt.RefreshTable
So, you basically need to work directly with objects and you need to qualify the objects, properties, methods / etc. with a .
I used the following code and changed the fields name and range value:
With ActiveSheet.PivotTables("pvtTest").PivotFields("Week")
.ClearAllFilters
.PivotFilters.Add Type:=xlCaptionEquals, Value1:=ActiveSheet.Range("K1").Value
End With
[1] http://www.ozgrid.com/forum/showthread.php?t=169855
I had a similar problem and found a solution that worked for me as none of the above seemed to. This is what I would change:
NewCat = Worksheets("Interface").Range("C3").Value
With pt
Field.ClearAllFilters
Field.CurrentPage = NewCat
pt.RefreshTable
End With
To:
NewCat = Array("[Range].[Site].&[" & Worksheets("Interface").Range("C3").Value & "]")
With pt
Field.ClearAllFilters
Field.VisbleItemsList = NewCat
pt.RefreshTable
End With
I tried several answers here with no luck. Then I ran a loop through the PivotItems collection under the PivotField to inspect the PivotItems properties in the Locals window.
If you first set the field to a variable like myField then you can loop through as such:
For Each pItem in myField.PivotItems
debug.print "Item Caption: """ & pItem.Caption """"
debug.print "Item Name: """ & pItem.Name """"
Next
What this showed me is that my field had extra spaces at the end, so the value I was trying to set at the filter was not exactly what I had in my list.
This led to the multiple-values option:
For Each pItem In myField.PivotItems
If Not pItem.Caption Like myFilterValue & "*" Then
pItem.Visible = False
Else
pItem.Visible = True
End If
Next
However, since I really only wanted one value I went back and dealt with the unwanted spaces.
There could be other things, but this may be one thing to check.
Removing the variable declaration of NewCat worked for me. Either delete the line or comment it out
'Dim NewCat As String

Select/Deselect all Pivot Items

I have a pivot table, and I am trying to select certain pivot items based on values in an array. I need this process to go faster, so I have tried using Application.Calculation = xlCalculationManual and PivotTables.ManualUpdate = True, but neither seem to be working; the pivot table still recalculates each time I change a pivot item.
Is there something I can do differently to prevent Excel from recalculating each time?
Or is there a way to deselect all items at once (not individually) to make the process go quicker?
Here is my code:
Application.Calculation = xlCalculationManual
'code to fill array with list of companies goes here
Dim PT As Excel.PivotTable
Set PT = Sheets("LE Pivot Table").PivotTables("PivotTable1")
Sheets("LE Pivot Table").PivotTables("PivotTable1").ManualUpdate = True
Dim pivItem As PivotItem
'compare pivot items to array.
'If pivot item matches an element of the array, make it visible=true,
'otherwise, make it visible=false
For Each pivItem In PT.PivotFields("company").PivotItems
pivItem.Visible = False 'initially make item unchecked
For Each company In ArrayOfCompanies()
If pivItem.Value = company Then
pivItem.Visible = True
End If
Next company
Next pivItem
It seems that you really want to try something different to significantly reduce the time it takes to select the required items in pivotttable.
I propose to use a “MirrorField”, i.e. a copy of the “Company” to be used to set in the sourcedata of the pivottable the items you need to hide\show.
First you need to add manually (or programmatically) the “MirrorField” and named same as the source field with a special character at the beginning like “!Company” the item must be part of the sourcedata and it can be placed in any column of it (as this will a “programmer” field I would place it in the last column and probably hidden as to not creating any issues for\with the users)
Please find below the code to update the pivottable datasource and to refresh the pivottable
I’m also requesting the PivotField to be updated just make it flexible as it then can be used for any field (provided that the “FieldMirror” is already created)
Last: In case you are running any events in the pivottable worksheet they should be disable and enable only to run with the last pivottable update
Hope this is what you are looking for.
Sub Ptb_ShowPivotItems_MirrorField(vPtbFld As Variant, aPtbItmSelection As Variant)
Dim oPtb As PivotTable
Dim rPtbSrc As Range
Dim iCol(2) As Integer
Dim sRC(2) As String
Dim sFmlR1C1 As String
Dim sPtbSrcDta As String
Rem Set PivotTable & SourceData
Set oPtb = ActiveSheet.PivotTables(1)
sPtbSrcDta = Chr(34) & oPtb.SourceData & Chr(34)
Set rPtbSrc = Evaluate("=INDIRECT(" & sPtbSrcDta & ",0)")
Rem Get FieldMirrow Position in Pivottable SourceData (FieldMirrow Already present SourceData)
With rPtbSrc
iCol(1) = -1 + .Column + Application.Match(vPtbFld, .Rows(1), 0)
iCol(2) = Application.Match("!" & vPtbFld, .Rows(1), 0)
End With
Rem Set FieldMirror Items PivotTable SourceData as per User Selection
sRC(1) = """|""&RC" & iCol(1) & "&""|"""
sRC(2) = """|" & Join(aPtbItmSelection, "|") & "|"""
sFmlR1C1 = "=IF(ISERROR(SEARCH(" & sRC(1) & "," & sRC(2) & ")),""N/A"",""Show"")"
With rPtbSrc.Offset(1).Resize(-1 + rPtbSrc.Rows.Count).Columns(iCol(2))
.Value = "N/A"
.FormulaR1C1 = sFmlR1C1
.Value = .Value2
End With
Rem Refresh PivotTable & Select FieldMirror Items
With oPtb
Rem Optional: Disable Events - In case you are running any events in the pivottable worksheet
Application.EnableEvents = False
.ClearAllFilters
.PivotCache.Refresh
With .PivotFields("!" & vPtbFld)
.Orientation = xlPageField
.EnableMultiplePageItems = False
Rem Optional: Enable Events - To triggrer the pivottable worksheet events only with last update
Application.EnableEvents = True
.CurrentPage = "Show"
End With: End With
End Sub
It seems unavoidable to have the pivotable refreshed every time a pivotitem is updated.
However I tried approaching the problem from the opposite angle. i.e.:
1.Validating the “PivotItems to be hidden” before updating the pivottable.
2.Also making make all items visible at once instead of “initially make item unchecked” one by one.
3.Then hiding all the items not selected by the user (PivotItems to be hidden)
I ran a test with 6 companies selected out of a total of 11 and the pivottable was updated 7 times
Ran also your original code with the same situation and the pivottable was updated 16 times
Find below the code
Sub Ptb_ShowPivotItems(aPtbItmSelection As Variant)
Dim oPtb As PivotTable
Dim oPtbItm As PivotItem
Dim aPtbItms() As PivotItem
Dim vPtbItm As Variant
Dim bPtbItm As Boolean
Dim bCnt As Byte
Set oPtb = ActiveSheet.PivotTables(1)
bCnt = 0
With oPtb.PivotFields("Company")
ReDim Preserve aPtbItms(.PivotItems.Count)
For Each oPtbItm In .PivotItems
bPtbItm = False
For Each vPtbItm In aPtbItmSelection
If oPtbItm.Name = vPtbItm Then
bPtbItm = True
Exit For
End If: Next
If Not (bPtbItm) Then
bCnt = 1 + bCnt
Set aPtbItms(bCnt) = oPtbItm
End If
Next
ReDim Preserve aPtbItms(bCnt)
.ClearAllFilters
For Each vPtbItm In aPtbItms
vPtbItm.Visible = False
Next
End With
End Sub

Excel VBA - PivotTable Filter Runtime Error '1004' PivotItems

I have the following code, which opens an excel file, selects the sheet and runs a macro - I have then managed to make it remove the filter for Date, but I am then having trouble getting it to filter to "01/07/2013"
Sub Data()
Dim oExcel As Excel.Application
Dim oWB As Workbook
Dim oSheets As Sheets
Dim oPi As PivotItem
Set oExcel = New Excel.Application
oExcel.Workbooks.Open ("\\A79APBRSFACTD\MDSS\FactivityServer\FactShar\OEE_Daily2.xls")
oExcel.Visible = True
Set oExcel = Excel.Application
Set oWB = oExcel.Workbooks("OEE_Daily2.xls")
oWB.Sheets("OEE Pivot Daily").Select
oExcel.Run ("Update_OEE_Daily")
oWB.Sheets("OEE Pivot Daily").Range("B3").Select
With oWB.Sheets("OEE Pivot Daily").PivotTables("PivotTable2").PivotFields("Date")
.ClearAllFilters
.PivotItems("01/07/2013").Visible = True
End With
Set oExcel = Nothing
Set oWB = Nothing
End Sub
I receive the following error message Run-time error '1004': Unable to get the PivotItems property of the PivotField class
The date "01/07/2013" is available in the source data of the PivotTable, and I am able to select it manually, but not automatically.
This is baffling me, as I only need it to show the one date.
If you're trying to show only 01/07/2013, then once you've cleared the filter, you need to hide everything except 01/07/2013, so try this:
With oWB.Sheets("OEE Pivot Daily").PivotTables("PivotTable2").PivotFields("Date")
.ClearAllFilters
For Each oPi In .PivotItems
If oPi .Value <> "1/7/2013" Then
oPi .Visible = False
End If
Next pi
End With
Make sure you remove the zeros.
If you step through your code, and watch oPi.value, you will see that it is "1/7/2013" instead of "01/07/2013". At least it was for me.
Excel is a nightmare when it comes to regional dates, so if you are using US mm/dd/yyyy format, this should work. If you're using dd/mm/yyyy format, you will need to check oPi.value against an American-formatted date. Annoyingly.
Edited 23/07/2013:
New code to search the data before applying the filter and lots of re-formatting to get around the American date format issue:
Sub RunFilter()
Dim strFilterDate As String
Dim datFilterDate As Date
Dim rngDateRange As Range
Dim c As Range
strFilterDate = InputBox("Enter the filter date in dd/mm/yyyy format.", "Enter date", Format(Now(), "dd/mm/yyyy"))
If IsDate(strFilterDate) And Len(strFilterDate) = 10 Then
datFilterDate = DateSerial(Right(strFilterDate, 4), Mid(strFilterDate, 4, 2), Left(strFilterDate, 2))
Set rngDateRange = ThisWorkbook.Worksheets("Sheet1").Range("B:B").SpecialCells(xlCellTypeConstants)
For Each c In rngDateRange
If c.Value2 = datFilterDate Then
ApplyPTFilter (datFilterDate)
Exit For
End If
Next c
End If
End Sub
Sub ApplyPTFilter(datDate As Date)
Dim pi As PivotItem
Dim strDate As String
strDate = Format(datDate, "m/d/yyyy")
With ThisWorkbook.Sheets("OEE Pivot Daily").PivotTables("PivotTable2").PivotFields("Date")
.ClearAllFilters
For Each pi In .PivotItems
If pi.Value <> strDate Then
pi.Visible = False
End If
Next pi
End With
End Sub
I realize that I bumped on similar issue waaay after the original post, although this thread was very inspiring - what helped me was:
.PivotCache.MissingItemsLimit = xlMissingItemsNone
After clearing the retained items from the pivotfilter list - I managed to execute my code without fail, what went after this was:
FiltrArr = Array("wymagalne", "wymagalne na jutro", "przeterminowane", "puste")
For Each PivotItem In .PivotFields("status").PivotItems
If Not IsError(Application.Match(PivotItem.Caption, FiltrArr, 0)) Then
PivotItem.Visible = True
Else
PivotItem.Visible = False
End If
Next PivotItem