I'm trying to create a macro that will expand certain details in a pivot table. The pivot table is grouped, where Response is the parent of AnswerOrder. The condition I want to create is that Response should only expand if AnswerOrder is not blank.
The current macro will loop through, and expand all responses, because Im unsure how I can specify that it should only expand the parent of the pivotItem and not all.
Sub Macro8()
Dim pi As PivotItem
Dim ps As PivotTable
Dim res As PivotField
Dim ans As PivotField
Set ps = ActiveSheet.PivotTables("PivotSurvey")
Set res = ps.PivotFields("Response")
Set ans = ps.PivotFields("AnswerOrder")
For Each pi In ans.PivotItems
If pi = (blank) Then
res.ShowDetail = False
Else
res.ShowDetail = True
End If
Next pi
End Sub
Related
I'm trying to set a Page filter in a Pivot Table, using string "Test" as base of search, so that it returns anything that contains that piece of String on it. I tried using * as wildcard for the string, but it returns an error.
I have been able to do this for Pivot Filters (columns/rows), but seems that Page filters (the ones on top/outside of the pivot table) use a different method or syntax.
I've tried searching in other threads and did not find an answer that fits my needs. Here is part of the code:
Dim pt As PivotTable
Dim pf As PivotField
Dim TextFilter As String
Set pt = ActiveSheet.PivotTables("PivotTable3")
Set pf = pt.PivotFields("Title")
TextFilter = "Test"
pt.PivotCache.Refresh
pf.ClearAllFilters
The below line works for exact string match:
ActiveSheet.PivotTables("PivotTable3").PivotFields("Title").CurrentPage = TextFilter
The below line doesn't work for partial string match (or contains):
ActiveSheet.PivotTables("PivotTable3").PivotFields("Title"). _
PivotFilters.Add Type:=xlCaptionContains, Value1:="Test"
How can I set the Page filter for strings like Test ?
Additionally, what would be the best solution for looping the final (correct) code for other Pivot Tables within the same Worksheet and/or within the Workbook ?
It would be useful to see documentation to explain why PivotFilters.Add does not work for page filters e.g. see here and here.
However, a simple loop does work, as shown in this post that you may have seen already, but does not specify page filters.
So you can do something like this:
Option Explicit
Sub Test()
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim strLike As String
Set pt = ThisWorkbook.Worksheets("Sheet1").PivotTables(1)
Set pf = pt.PivotFields("name")
strLike = "b*"
pt.PivotCache.Refresh
pf.EnableMultiplePageItems = True ' make sure the filter accepts multiple items
pf.ClearManualFilter ' make sure to reset to avoid an error for no active filter
For Each pi In pf.PivotItems
pi.Visible = (pi.Name Like strLike)
Next pi
End Sub
To use this in a loop of all worksheets in a workbook, you can extend like this:
Option Explicit
Sub Test()
Dim wb As Workbook
Dim ws As Worksheet
Dim pt As PivotTable
Set wb = ThisWorkbook
For Each ws In wb.Worksheets
For Each pt In ws.PivotTables
PivotPageByWildcard pt, "name", "b*"
Next pt
Next ws
End Sub
Sub PivotPageByWildcard(pt As PivotTable, strField As String, strLike As String)
Dim pf As PivotField
Dim pi As PivotItem
Set pf = pt.PivotFields(strField)
pt.PivotCache.Refresh
pf.EnableMultiplePageItems = True
pf.ClearManualFilter
For Each pi In pf.PivotItems
pi.Visible = (pi.Name Like strLike)
Next pi
End Sub
Simple test case:
I am setting up a dynamic report and would like to filter multiple pivot tables at the same time as I change one cell value. I have no experience in VBA and cannot find anyone within my company that can help.
Since the pivot tables are separate objects, I define them all as different dimensions and point these dimensions to the different pivot tables but the cell that is meant to dictate the pivot table filter stays the same. Below are modified from my google search. Original codes worked fine updating 1 pivot table. After my ignorant attempt at modifying the codes, I ended up with application-defined or object-defined error.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, Range("D1:D2")) Is Nothing Then Exit Sub
Dim pt As PivotTable
Dim Field As PivotField
Dim NewCat As String
Dim pt1 As PivotTable
Dim Field1 As PivotField
Dim NewCat1 As String
Set pt = Worksheets("Sheet1").PivotTables("PivotTable1")
Set Field = pt.PivotFields("Code")
NewCat = Worksheets("Sheet1").Range("D1").Value
Set pt1 = Worksheets("Sheet1").PivotTables("Pivotable2")
Set Field1 = pt1.PivotFields("Code")
NewCat1 = Worksheets("Sheet1").Range("D1").Value
With pt
Field.ClearAllFilters
Field.CurrentPage = NewCat
pt.RefreshTable
End With
With pt1
Field1.ClearAllFilters
Field1.CurrentPage = NewCat1
pt1.RefreshTable
End With
End Sub
I am having some problems in linking an Active X combobox to a Pivot table filter. Basically I will need to have the users to select from the combobox an ID that needs to be linked to the Pivot table filter. I am using the following code:
Private Sub ComboBox1_Change()
Dim sheet As Worksheet
Dim pt As PivotTable
Dim ptField As PivotField
Set sheet = ThisWorkbook.Worksheets("Overview")
Set pt = sheet.PivotTables("Main")
Set ptField = pt.PivotFields("CustomersId")
ptField.ClearAllFilters
ptField.CurrentPage = Me.ComboBox1.Value
End Sub
The error I get is: "Unable to get the PivotFields property of the PivotTable Class".
Any idea of what is wrong with the above code? Something that I m missing?
Thank you in advance
My objective is to filter a pivot table using a range in another sheet. This range pulls data from a 3rd sheet, which is the data dump that kicks off a whole hosts of formulas and changes every time it is used.
I have the below code but what I can see it doing is running through each Pivot Table field, comparing it to the range, and then removing the filter. I have 32,000 fields that need to be checked so the current macro is too slow to use.
Could anyone help me fix the code so that it only filters based on values in the range that are Not Blank?
Sub PT()
Dim PT As PivotTable
Dim PI As PivotItem
Set PT = Sheets("Pivot_Sheet").PivotTables("PivotTable2")
With Sheets("Pivot_Sheet").PivotTables("PivotTable2").PivotFields("Product")
.ClearAllFilters
End With
For Each PI In PT.PivotFields("Product").PivotItems
PI.Visible = WorksheetFunction.CountIf(Sheets("Sheet1").Range("J2:J100"),
PI.Name) > 0
Next PI
Set PT = Nothing
End Sub
Your code is going to be slow on many, many counts. Have a read of my blogpost on this subject if you're interested in learning about the bottlenecks to avoid when filtering PivotTables.
The below code should get you started. If you have any questions, just holler.
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 vList As Variant
Set pt = ActiveSheet.PivotTables("PivotTable2")
Set pf = pt.PivotFields("Product")
vList = Application.Transpose(ActiveWorkbook.Worksheets("Sheet1").Range("J2:J100"))
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 vList
.PivotItems(vItem).Visible = True
Next vItem
On Error GoTo 0
'Hide the first PivotItem, unless it is one of the items of interest
On Error Resume Next
If InStr(UCase(Join(vList, "|")), 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
I have a filter field called week_of_year (1,2,3,4,5,6,7,8....), another pivot field year(2012,2013,2014), the vba code belows filter on the current week and year of 2014/2015 and hide everything else. But the problem is the code loops each record and runs slow when it comes to big pivot table. Im trying on a new code but encountering some error.
Sub datefilter()
Dim PvtTbl As PivotTable
Set PvtTbl = Worksheets("LO").PivotTables("PivotTable3")
Dim dd As Integer
dd = Format(Date, "ww")
Dim pf As PivotField
Dim pf1 As PivotField
Dim PI As PivotItem
Set pf =
Worksheets("LO").PivotTables("PivotTable3").PivotFields("week_of_year")
Set pf1 =
Worksheets("LO").PivotTables("PivotTable3").PivotFields("year")
PvtTbl.ClearAllFilters
For Each PI In pf.PivotItems
If PI.Name = CStr(dd) Then
PI.Visible = True
Else
PI.Visible = False
End If
Next
For Each PI In pf1.PivotItems
If PI.Name = "2014" Or PI.Name = "2015" Then
PI.Visible = True
Else
PI.Visible = False
End If
Next
End Sub
New code that I develop is:
Sub datefilter1()
Dim PvtTbl As PivotTable
Set PvtTbl = Worksheets("LO").PivotTables("PivotTable3")
Dim dd As Integer
dd = Format(Date, "ww")
Dim pf As PivotField
Set pf =
Worksheets("LO").PivotTables("PivotTable3").PivotFields("week_of_year")
pf.PivotFilters.Add2 xlValueEquals, 3
End Sub
The code failed at
pf.PivotFilters.Add2 xlValueEquals, CStr(dd)
I also tried:
pf.PivotFilters.Add2 Type:= xlValueEquals, Value1 := CStr(dd)
The error is Invalid procedure call or argument.Any idea How I can fix this error?????
Any faster way to filter on multiple filter criteria? Thanks!
If you only want to filter on one value, drag the field of interest to the Report Filter pane, then you can do this very quickly without looping using the following code:
Sub FilterOnWeek()
Dim pt As PivotTable
Dim pf As PivotField
Set pt = Worksheets("LO").PivotTables("PivotTable3")
Set pf = pt.PivotFields("week_of_year")
pf.CurrentPage = Format(Date, "ww")
End Sub
If for some reason this field absolutely must stay in the PivotTable as a row field, you can still filter without looping by the following method if you have Excel 2010 or later
Make a copy of the PivotTable, and drag the 'week_of_year' field
in the copy to the Report Filter area
Set up a slicer on the week_of_year field on one PivotTable, and
connect it to the other PivotTable via the Report Connections
dialog. (Right click on the Slicer, select 'Report Connections')
Amend the above code so it runs on the 2nd PivotTable.
The Slicer will then sync the two PivotTables.
If you want to filter on more than one value, drag the field to the ROWS area, and use this:
Sub FilterOnWeek2()
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim lStart As Long
Dim lEnd As Long
lEnd = Format(Date, "ww")
lStart = Val(Format(Date, "ww")) - 1
Set pt = Worksheets("LO").PivotTables("PivotTable3")
Set pf = pt.PivotFields("week_of_year")
With pf
.ClearAllFilters
.PivotFilters.Add Type:=xlCaptionIsBetween, Value1:=lStart, Value2:=lEnd
End With
End Sub
If for some reason you don't want this field in the PivotTable as a row field, follow the same general approach as above: make a copy of the PivotTable, put the field that you want to filter on in the copy as a ROWS field, connect the fields of interest together as a slicer, hide the slicer somewhere, and amend the code so it runs on the copy of the PivotTable with the rowfield in it.
I recommend you read my article at http://dailydoseofexcel.com/archives/2013/11/14/filtering-pivots-based-on-external-ranges/ if you want to learn more about efficiently filtering PivotTables.