unable to update slicer value using VBA - vba

The following is the code i am using to update the value of my slicer.
Sub country_select()
Application.ScreenUpdating = False
country_selected = ActiveSheet.Shapes(Application.Caller).Name
ActiveWorkbook.SlicerCaches("Slicer_Country").ClearManualFilter
For Count = 1 To 13 'countries
country = Sheet5.Range("E2").Offset(Count, 0).Value
If country = country_selected Then
ActiveWorkbook.SlicerCaches("Slicer_Country").SlicerItems(country).Selected = True
Else
ActiveWorkbook.SlicerCaches("Slicer_Country").SlicerItems(country).Selected =
False
End If
Next Count
Application.ScreenUpdating = True
End Sub
The country variable is not updating its value(only taking empty value).
I don't understand the reason for this.
I am trying to link a map to a macro hence the input.

I'm not sure why you need to interate through the range E3:E14. If all you want to do is to set the Slicer to show the item corresponding to the shape the user has selected, I would just use something like this:
Option Explicit
Sub country_select()
Dim si As SlicerItem
Dim Country As String
Dim sc As SlicerCache
Application.ScreenUpdating = False
Country = ActiveSheet.Shapes(Application.Caller).Name
Set sc = ActiveWorkbook.SlicerCaches("Slicer_Country")
With sc
.ClearAllFilters
For Each si In sc.SlicerItems
If si.Name <> Country Then si.Selected = False
Next si
End With
Application.ScreenUpdating = True
End Sub
Note that if the slicer was for a PivotTable (and not for a Table) I would set the .ManualUpdate propery of the PivotTable to TRUE before the loop, and to FALSE after, so that the PivotTable didn't try to update after each and every SlicerItem is selected.
And if this was for a PivotTable (and not for a Table) there is no need to iterate over a Slicer at all (which is inefficient/slow). Instead, just put the Country field in the Pivot as a PageField, and just set the .CurrentPage of the PageField directly, like so:
Sub FilterPivot()
Dim pf As PivotField
Set pf = ActiveSheet.PivotTables("PivotTable1").PivotFields("Country")
pf.CurrentPage = Application.Caller
End Sub

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

How to select one slicer = true and remaining = false in VBA

Trying to narrow down this VBA script w/o having to list out . I'm a basic Macro user. How can I get one selected = True and the rest = False without having to list all 160?
With ActiveWorkbook.SlicerCaches("Slicer_Organization")
.SlicerItems("900110 - Danish Bemidji ").Selected = True
.SlicerItems("900101 - Arabic Bemidji").Selected = False
.SlicerItems("900105 - Chinese Callaway 1st Half").Selected = False
.SlicerItems("900106 - Chinese Callaway 2nd Half").Selected = False
.SlicerItems("900115 - Finnish Bemidji ").Selected = False
.SlicerItems("900120 - French Bemidji 1st Half ").Selected = False
.SlicerItems("900121 - French Bemidji 2nd Half ").Selected = False
Filtering SlicerItems can be tricky, because at least one item must remain visible at all times.
This code shows how to filter a Slicer on an array called vSelection. To amend to your needs, just change the vSelection = Array("B", "C", "E") line so that it contains the item(s) of interest.
Option Explicit
Sub FilterSlicer()
Dim slr As Slicer
Dim sc As SlicerCache
Dim si As SlicerItem
Dim i As Long
Dim vItem As Variant
Dim vSelection As Variant
Set sc = ActiveWorkbook.SlicerCaches("Slicer_ID")
vSelection = Array("B", "C", "E")
For Each pt In sc.PivotTables
pt.ManualUpdate = True 'Stops PivotTable from refreshing after each PivotItem is changed
Next pt
With sc
'At least one item must remain visible in the Slicer at all times, so make the first
'item visible, and at the end of the routine, check if it actually *should* be visible
.SlicerItems(1).Selected = 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 .SlicerItems.Count
If .SlicerItems(i).Selected Then .SlicerItems(i).Selected = 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 vSelection
.SlicerItems(vItem).Selected = 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(vSelection, "|")), UCase(.SlicerItems(1).Name)) = 0 Then .SlicerItems(1).Selected = False
If Err.Number <> 0 Then
.ClearAllFilters
MsgBox Title:="No Items Found", Prompt:="None of the desired items was found in the Slicer, so I have cleared the filter"
End If
On Error GoTo 0
End With
For Each pt In sc.PivotTables
pt.ManualUpdate = False
Next pt
End Sub
You can loop through all SlicerItems in your SlicerCache using a For Each loop:
Dim si as SlicerItem
For Each si In ActiveWorkbook.SlicerCaches("Slicer_Organization").SlicerItems
si.Selected = (si.Name = "900110 - Danish Bemidji")
Next si
That (si.Name = "900110 - Danish Bemidji") will return a True or False and set the Selected property of the SlicerItem you are iterating appropriately.
Sub ExcelGuruVG()
Dim myval As String
myval = "VG"
Dim sli as SlicerItem
with Activeworkbook.slicercaches("Slicer_SLICERNAME")
for Each sli in SlicerItems
if sli.Name = myval then
sli.select = true
Else
sli.selected = False
End if
Next sli
End with
End Sub
I tried the code that was shared by Venugopal and combined it with JNevill's code, and it worked!
Thanks a bunch to both of you!
The adjustment I made is as below:
Sub ExcelGuruVG()
Dim myval As String
myval = ThisWorkbook.Worksheets("Sheet1").Range("A2").Value 'Taking the value from Sheet1 in Cell A2
Dim sli As SlicerItem
With ActiveWorkbook.SlicerCaches("Slicer_SlicerName1")
For Each sli In ActiveWorkbook.SlicerCaches("Slicer_SlicerName1").SlicerItems
If sli.Name = myval Then
sli.Selected = True
Else
sli.Selected = False
End If
Next sli
End With
End Sub

How to update slicer cache with VBA

I'm using Excel VBA to hide/show elements on slicer depending upon user selection.
I have the following code :
Private Sub removeFilterWithSlicer()
Dim slicerCache As slicerCache
Set slicerCache = ThisWorkbook.SlicerCaches("Slicer_Channel1")
slicerCache.SlicerItems("A").Selected = False
slicerCache.SlicerItems("B").Selected = False
slicerCache.SlicerItems("C").Selected = False
slicerCache.SlicerItems("D").Selected = False
slicerCache.SlicerItems("E").Selected = False
slicerCache.SlicerItems("F").Selected = False
End Sub
where A, B etc. are names of elements in slicer. I've cross checked the name of slicer cache ("Slicer_Channel1"). The issue is that the elements don't get deselected as they are supposed to. When I'm debugging the code, I found that each element gets deselected one by one but as soon as I reach the end of procedure i.e. End Sub, they all get back to being in selected state.
Any pointers ?
This code shows how to filter a Slicer on an array called vSelection.
Option Explicit
Sub FilterSlicer()
Dim slr As Slicer
Dim sc As SlicerCache
Dim si As SlicerItem
Dim i As Long
Dim vItem As Variant
Dim vSelection As Variant
Set sc = ActiveWorkbook.SlicerCaches("Slicer_ID")
'Set sc = slr.SlicerCache
vSelection = Array("B", "C", "E")
For Each pt In sc.PivotTables
pt.ManualUpdate = True 'Stops PivotTable from refreshing after each PivotItem is changed
Next pt
With sc
'At least one item must remain visible in the Slicer at all times, so make the first
'item visible, and at the end of the routine, check if it actually *should* be visible
.SlicerItems(1).Selected = 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 .SlicerItems.Count
If .SlicerItems(i).Selected Then .SlicerItems(i).Selected = 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 vSelection
.SlicerItems(vItem).Selected = 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(vSelection, "|")), UCase(.SlicerItems(1).Name)) = 0 Then .SlicerItems(1).Selected = False
If Err.Number <> 0 Then
.ClearAllFilters
MsgBox Title:="No Items Found", Prompt:="None of the desired items was found in the Slicer, so I have cleared the filter"
End If
On Error GoTo 0
End With
For Each pt In sc.PivotTables
pt.ManualUpdate = False
Next pt
End Sub
at least one has to be selected. works the same way when selecting with a mouse. you cannot un-select all

Trying to get multiple name values from a slicer

So I would like to retrieve the selected items from my "Department" slicer and store them in a string. However When I test this I only get the last item and its not even one selected. This works great for setting the DepartmentX slicer with the same items from Department however I would like to store only the selected items in a string. Any help would be greatly appreciated
here is what I have so far
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim PT1 As PivotTable, PT2 As PivotTable
Dim slc1 As Slicer, slc2 As Slicer
Dim slcCache1 As SlicerCache, slcCache2 As SlicerCache
Dim slcItem1 As SlicerItem, slcItem2 As SlicerItem
Dim slicer_data As String
If Sh.Name = "GP YTD - Tooling (FYE 2016)" Then
Set PT1 = Sheets("Sheet1").PivotTables
("PivotTable2") '(1)
Set slc1 = PT1.Slicers("Department") '(1)
Set slcCache1 = slc1.SlicerCache
Set PT2 = Sheets("Sheet2").PivotTables
("PivotTable3") '(2)
Set slc2 = PT2.Slicers("DepartmentX") '(2)
Set slcCache2 = slc2.SlicerCache
slcCache2.ClearManualFilter
For Each slcItem1 In slcCache1.SlicerItems
slcCache2.SlicerItems(slcItem1.Name).Selected = slcItem1.Selected
slicer_data = slcItem1.Name
Application.EnableEvents = True
Next slcItem1
MsgBox "Selected" & slicer_data
End If
End Sub
Modify the last part to this:
For Each slcItem1 In slcCache1.SlicerItems
slcCache2.SlicerItems(slcItem1.Name).Selected = slcItem1.Selected
If slcItem1.Selected Then slicer_data = slicer_data & "," & slcItem1.Name
Application.EnableEvents = True
Next slcItem1
MsgBox "Selected" & Mid$(slicer_data, 2)

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