VBA multiple checkboxes to control multiple pivot tables - vba

again I need little help which I will greatly appreciate.
Basically, on my dashboard page I have couple of checkboxes that control numerous of pivot tables in the background.
I have checkboxes that are called "definite", "tentative", "pending,", ... and also corresponds to values in pivot fields.
and I have numerous of pivot tables called: "Hidden_1" or "Hidden_2" in different sheets but all with the same structure.
My idea was that If someone checked "definite", it will be selected in all pivot pivot tables in fields called "Status". If someone "unchecked" this checkbox, the pivots will react.
To do so I used a code that I create before and it was working well:
Sub checkbox1()
Application.ScreenUpdating = False
On Error Resume Next
Dim pt As PivotTable, wks As Worksheet
For Each wks In ActiveWorkbook.Worksheets
For Each pt In wks.PivotTables
With pt
If .Name = "Hidden_1" Or .Name = "Hidden_2" Then
.PivotFields("Status").CurrentPage = "definite"
End If
End With
Next pt
Next wks
Application.ScreenUpdating = True
End Sub
However, this code selects only one value, so I can't have selected both "definite" and "pending" if someone checked those boxes. Right now all checkboxes has a separate code assigned where only .CurrentPage = "checkboxname" was changed..
I have two questions:
1) what is the best way to select multiple values. E.g. if checked boxes "definite" and "pending" are checked, pivot tables should have selected two values "definite" and "pending" selected in the "Status" field
2) what is the best way to "dis-select" the value? Right now, my procedure checkbox1 is running everytime that the checkbox is clicked. And I want it to run only when I am "checking" it.
Right now I am trying to link the checkbox with cell, e.g. "definite" has H10, so my code starts with the line:
If Range("H10").Value = True Then
'code to select the value in "Status" field
Else
'code to unselect the value in "Status" field
End If
I should also noted that I couldn't use ActiveX Checkbox because I had error: "cannot insert object" and I used form controls. I read that this error is somehow connected with a patch that I have installed.
Thank you all for your help,
Matt

I worked on it and found such a solution:
Sub checkbox1()
Dim choice1, choice2, choice3, choice4, choice5, choice6, choice7
Dim oPI As PivotItem
Dim pt As PivotTable, wks As Worksheet
If Sheets("Hidden").Range("B6").Value = "True" Then
choice1 = "Definite"
End If
If Sheets("Hidden").Range("B7").Value = "True" Then
choice2 = "Tentative"
End If
If Sheets("Hidden").Range("B8").Value = "True" Then
choice3 = "Hold/Option"
End If
If Sheets("Hidden").Range("B9").Value = "True" Then
choice4 = "Pending"
End If
If Sheets("Hidden").Range("B10").Value = "True" Then
choice5 = "Waitlist"
If Sheets("Hidden").Range("B11").Value = "True" Then
choice6 = "Lost"
End If
If Sheets("Hidden").Range("B12").Value = "True" Then
choice7 = "Cancelled"
End If
Sheets("Hidden_pivot1").PivotTables("Hidden_1").PivotFields("SalesStatus").ClearAllFilters
Sheets("Hidden_pivot1").PivotTables("Hidden_3").PivotFields("SalesStatus").ClearAllFilters
Sheets("Hidden_pivot2").PivotTables("Hidden_2").PivotFields("SalesStatus").ClearAllFilters
Sheets("Hidden_pivot2").PivotTables("Hidden_4").PivotFields("SalesStatus").ClearAllFilters
For Each wks In ActiveWorkbook.Worksheets
For Each pt In wks.PivotTables
With pt
If .Name = "Hidden_1" Or .Name = "Hidden_2" Or .Name = "Hidden_3" Or .Name = "Hidden_4" Then
For Each oPI In pt.PivotFields("SalesStatus").PivotItems
Select Case oPI.Name
Case choice1, choice2, choice3, choice4, choice5, choice6, choice7
Case Else
oPI.Visible = False
End Select
Next
End If
End With
Next pt
Next wks
End Sub
This work but is so slow. It would be better if the macro could add and delete those items, instead of re-creating the entire choice.

Related

Switch pivot table filter using VBA macro (button)

I need help with some rather easy macro, but I can't do that. So all I want is to switch between filters - I have two possibilities, by example two colours - black and white, and I only want to have one of them in the moment (I want to add button, so it will work as switch). Here is the situation
I've tried did it with conditional, of course it doesn't work, but hope it will helps you to understand my idea. If one filter is enable, the other one is disabled (so the objects connected with that obviously too).
Sub Makro5()
ActiveSheet.PivotTables("PivotTable3").PivotFields("colour"). _
CurrentPage = "(All)"
If ActiveSheet.PivotTables("PivotTable3").PivotFields("colour")
.PivotItems("black").Visible = False
.PivotItems("white").Visible = True
Then ActiveSheet.PivotTables("PivotTable3").PivotFields ("colour")
.PivotItems("black").Visible = True
.PivotItems("white").Visible = False
Else: ActiveSheet.PivotTables("PivotTable3").PivotFields ("colour")
.PivotItems("black").Visible = False
.PivotItems("white").Visible = True
End Sub
Something is wrong with If, because it's on red and I get "Complie error: Syntax error" info
This is what slicers are built for.
Put your cursor inside the the pivottable data area. Then goto insert > slicer > and choose colour. You will then have a slicer which will allow you to select either or. I don't know if you can disable multiselect in current excel version so user could press ctrl and select both. But this seems a simple way.
Or you could run code such as the following and then user just types in Black or White in to field and filter is applied:
Sub Test()
Dim wb As Workbook
Dim ws As Worksheet
Dim pvt As PivotTable
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet3")
Set pvt = ws.PivotTables("PivotTable3")
Dim pvtField As PivotField
Dim item As Long
Dim item2 As Long
Set pvtField = pvt.PivotFields("Colour")
pvtField.EnableItemSelection = False
End Sub
You need to have the Then on the same line as the If. (You can use _ to tell VBA that "code continues on next line")
You also don't have your And set up correctly, and you are making both "Black" and "White" visible before you check if they are visible?
Try this:
Sub ToggleColour()
With ActiveSheet.PivotTables("PivotTable3").PivotFields("colour")
If .PivotItems("white").Visible=True Then
.CurrentPage = "black"
Else
.CurrentPage = "white"
End If
End With
End Sub

Excel VBA Hide different columns depending on different cell values in another sheet, in real time

I've got a workbook with 5 sheets: Sheet1, Sheet2, Sheet3, Sheet4, Sheet5. The first sheet: "Sheet" has a cell: "C3" with a drop down menu with 4 different options: Opt1, Opt2, Opt3, Opt4.
Depending on what is selected in this drop down menu, I'd like different columns to be hidden in the various sheets - in real time. And if nothing is entered, I'd like no columns hidden.
I've entered the below code which partly works but I think there's an issue because I've selected overlapping columns to hide - not completely sure.
Additionally, I'd like to work in hiding particular rows as well as the column below, depending on what different option you select in the drop down menu.
Also, I'll replicate hiding the same columns across all Sheets1-5.
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("C3").Value = "Opt1" Then
Sheets("Sheet1").Columns("G:L").EntireColumn.Hidden = True
Sheets("Sheet1").Columns("N:T").EntireColumn.Hidden = True
Else
Sheets("Sheet1").Columns("G:L").EntireColumn.Hidden = False
Sheets("Sheet1").Columns("N:T").EntireColumn.Hidden = False
End If
If Range("C3").Value = "Opt2" Then
Sheets("Sheet1").Columns("B:F").EntireColumn.Hidden = True
Sheets("Sheet1").Columns("N:T").EntireColumn.Hidden = True
Else
Sheets("Sheet1").Columns("B:F").EntireColumn.Hidden = False
Sheets("Sheet1").Columns("N:T").EntireColumn.Hidden = False
End If
If Range("C3").Value = "Opt3" Then
Sheets("Sheet1").Columns("B:M").EntireColumn.Hidden = True
Else
Sheets("Sheet1").Columns("B:M").EntireColumn.Hidden = False
End If
If Range("C3").Value = "Opt4" Then
Sheets("Sheet1").Columns("B:AB").EntireColumn.Hidden = True
Else
Sheets("Sheet1").Columns("B:AB").EntireColumn.Hidden = False
End If
End Sub
Following on from my comment. You can define the entire range of columns as a variable e.g. entireRange and set this to unhidden at the start of each worksheet change.
Add fully qualified references to the ranges i.e. ThisWorkbook.Sheets("Sheet1") or ws (as a variable shown below).
As everything is unhidden at start Else is not needed for each If statement. This is probably where confusion arises.
Change to a Select case statement as you are testing the value of a single cell against different expected values.
Combine your separate line column ranges that you are hiding into one line statements e.g.
Sheets("Sheet1").Columns("G:L").EntireColumn.Hidden = True
Sheets("Sheet1").Columns("N:T").EntireColumn.Hidden = True
Becomes:
ws.Range("G:L,N:T").EntireColumn.Hidden = True
You code would then look like the following:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wb As Workbook
Dim ws As Worksheet
Dim entireRange As Range
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
Set entireRange = ws.Columns("B:AB")
entireRange.EntireColumn.Hidden = False
Select Case ws.Range("C3") 'Test the value of C3
Case "Opt1"
ws.Range("G:L,N:T").EntireColumn.Hidden = True
Case "Opt2"
ws.Range("B:F,N:T").EntireColumn.Hidden = True
Case "Opt3"
ws.Range("B:M").EntireColumn.Hidden = True
Case "Opt4"
entireRange.Hidden = True
End Select
End Sub
This will be easier to debug in terms of where things are being hidden or unhidden.
I have rewritten your code to make it easy to read and edit. My goal was to make the code as short as possible. I changed your if statement into a Select Case. It's more elegant and I think it's faster, but don't take my word for it.
The problem that had to be tackled was that if I select Opt1 and then select Opt2, the columns from Opt1 would still be hidden. So before the code hides anything, it automatically unhides all the columns in the range B:AB.
I added the Case Else to unhide all columns if you entered anything but Opt1, Opt2, Opt3 or Opt4. This could easily be changed into a MsgBox that warns the user that the entered value is incorrect. You can remove this line if you have limited the choice for the users already.
The Code:
Private Sub Worksheet_Change(ByVal Target As Range)
' Unhide Columns
Worksheets("Sheet1").Range("B:AB").EntireColumn.Hidden = False
Select Case Worksheets("Sheet1").Range("C3").Value
Case "Opt1"
Worksheets("Sheet1").Range("G:L,N:T").EntireColumn.Hidden = True
Case "Opt2"
Worksheets("Sheet1").Range("B:F,N:T").EntireColumn.Hidden = True
Case "Opt3"
Worksheets("Sheet1").Range("B:M").EntireColumn.Hidden = True
Case "Opt4"
Worksheets("Sheet1").Range("B:AB").EntireColumn.Hidden = True
' If anything else is entered, the columns will be unhidden.
Case Else
Worksheets("Sheet1").Range("B:AB").EntireColumn.Hidden = False
End Select
End Sub

Excel VBA combobox doesn't allow to select specific items from list

I have a combobox in my worksheet with a dynamic search, the dynamic search is done by searching the typed letters in a list that is on another worksheet. The search is done by excel formulas. The list is a defined range and then the combobox listfillrange is set to the named range.
When I type the dropdown list opens, for certain items the combobox allows me to select from the list and for others the selection disappear as I select. I tried figure why do these items disappear. The list is long (10,000 items) so it kind of works slow, but I am not sure if this is the problem.
How can I fix such a problem? Is there a way to define a variable for the mouseclick selection from dropdown list?
Thanks in advance,
Tali
This is my code:
Private Sub ComboBox1_Change()
Sheets("PS").EnableCalculation = True
ComboBox1.ListFillRange = "DropDownList"
ComboBox1.DropDown
End Sub
Private Sub CommandButton21_Click()
Dim PS As Worksheet
Application.ScreenUpdating = False
Application.ErrorCheckingOptions.BackgroundChecking = False
Sheets("PharmaSoft").Select
Set PS = Sheets("PS")
SelectionA = PS.Range("J2").Value
If ComboBox1.Value = SelectionA Then
Range("J19") = "Pharmacy purchase price"
Range("N19") = PS.Range("K2")
Range("O19") = "ILS"
Range("J21") = "Pharmacy selling price Incl.VAT"
Range("N21") = PS.Range("L2")
Range("O21") = "ILS"
Range("J23") = "Package size"
Range("N23") = PS.Range("M2")
Range("J19:O23").Select
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
Selection.Font.Bold = True
Application.ScreenUpdating = True
Range("N19").Errors.Item(1).Ignore = True
Range("N21").Errors.Item(1).Ignore = True
Range("N23").Errors.Item(1).Ignore = True
Else
MsgBox "Please select a product", vbCritical, "Error"
End If
Sheets("PS").EnableCalculation = False
End Sub
Private Sub CommandButton22_Click()
Application.ScreenUpdating = False
Sheets("PharmaSoft").Select
ComboBox1.Value = Null
Range("J19:O23").Value = Null
Application.ScreenUpdating = True
End Sub
Also the code for the workbook:
Private Sub Workbook_Open()
Sheets("PharmaSoft").Select
Application.ScreenUpdating = False
Sheets("PharmaSoft").ComboBox1.Value = Null
Range("J19:O23").Value = Null
Application.ScreenUpdating = True
End Sub
Although I can't comment on what you're doing given that your search is done as you mention with excel formulas. I do know that using data validation via a combo box can be pretty quick. The method I use is as per this page and is extremely fast. It's pretty much instantaneous on a validation range that is about 15k rows long. The best part about it is that it provides auto completion. So when you type in the combo box and that value isn't in the list, the entry that matched one character ago disappears. It's a good visual cue whether you're selection is valid or not. And of course, you can still use the drop down box in the usual way. The only down side is that, as coded at the link provided, you have to double-click to enter the auto-completion mode.

Deselect all items in a pivot table using vba

Can some quicly explain the way to deselect all items in a newly created pivot table so that I can go back and select only one or two items? I tried the following:
.PivotItems("(Select All)").Visible = False
Thanks.
This is probably the closest you can get to what you want:
Dim i As Long
.PivotItems(1).Visible = True
For i = 2 To .PivotItems.Count
.PivotItems(i).Visible = False
Next
This will make the very first option the only selected option (assuming this is within a with that points to the pivotfield). If you know what you want before hand... modify accordingly.
I've found that looping through each data item takes a lot of time, what you can do if you want to filter on a single item in a pivot without looping through all items is use the following code:
ActiveSheet.PivotTables("Your Pivot Name").PivotFields("Your Field Name").ClearAllFilters
ActiveSheet.PivotTables("Your Pivot Name").PivotFields("Your Field Name").PivotFilters.Add _
Type:=xlCaptionEquals, Value1:="Your string here"
this is basically a label filter but it worked for me.
Check the following out. Select data for specific field name. Please do note that you have to at least select one item by default. And also do not forget that if you want to hide items, Only contiguous items in a PivotTable Field can be hidden. Perhaps at page load, or worksheet open or any of your other sub trigger, you could select a particular items to be selected based on a specific field. Then allow your code to proceed with anything else.
Sub specificItemsField()
Dim pf As PivotField
Dim pi As PivotItem
Dim strPVField As String
strPVField = "Field Name"
Set pt = ActiveSheet.PivotTables(1)
Set pf = pt.PivotFields(strPVField)
Application.ScreenUpdating = False
Application.DisplayAlerts = False
On Error Resume Next
pf.AutoSort xlManual, pf.SourceName
For Each pi In pf.PivotItems
pi.Visible = True
Next pi
pf.AutoSort xlAscending, pf.SourceName
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
This is how I do for custom filter selection. May be slower due to double looping.
Dim toSelect(1 To 3) As String
toSelect(1) = "item1"
toSelect(2) = "item2"
toSelect(3) = "item3"
For Each pvItem In objField.PivotItems
For Each st In toSelect
If pvItem.Value = st Then
pvItem.Visible = True
Exit For
Else
pvItem.Visible = False
End If
Next
Next
Well.
Because you have not how to hide all, because, always you need to have 1 item visible
I do this:
I start hiding the first field, and before go to the next, i show all fields i need visible, then, i go to the secont item, and hide, and again show all items i want, and so on. Then, always will be visible any field, and wont have error.
After the loop, i again try to show all fields i want.
With ActiveSheet.PivotTables("TablaD2").PivotFields("Entity")
Dim i As Long
For i = 1 To .PivotItems.Count
.PivotItems(i).Visible = False
.PivotItems("ARG").Visible = True
.PivotItems("BRL").Visible = True
.PivotItems("GCB").Visible = True
.PivotItems("MEX").Visible = True
Next
.PivotItems("ARG").Visible = True
.PivotItems("BRL").Visible = True
.PivotItems("GCB").Visible = True
.PivotItems("MEX").Visible = True
End With

Excel vba: error hiding calculated field in Pivot table

I have written several Subs to show/hide fields in a PivotTable.
Now I am trying to do the same with a calculated field, but I get an error when hiding it.
I took my code from the recorder and the recorder's code also halts on the last line.
I googled the error message, without serious result.
Sub PrRemove()
'remove PR
Dim pt As PivotTable
Set pt = ActiveSheet.PivotTables("MyPivot")
pt.PivotFields("MyField").Orientation = xlHidden '<- here is the error
End Sub
The same code works fine if MyField is a normal field (not a calculated one).
I am using Excel 2007 with SP2.
Any clue ?
EDIT on 17 June 2010: I also tried using pt.DataFields instead of pt.PivotFields, with exactly the same behaviour. The error message says "Unable to set the orientation of the PivotField class".
after much hair pulling i have found a workaround.
if you add more than one pivot field (calculated or otherwise) excel creates a grouped field called Values. you can set the orientation property of PivotField("Values") to xlHidden and it bullets both fields. So if you want to remove a calculated field, just add a non-calculated field, set PivotField("Values").orientation to xlHidden and you're done.
nobody said it would be pretty...
With ActiveSheet.PivotTables("PivottableName").PivotFields("Values")
.PivotItems("CalcFieldName").Visible = False
End With
I wanted to easily remove data fields (calculated fields or not), like it would be done manually.
And I finally found this solution (Excel 2010) :
Set pt = ActiveSheet.PivotTables("mypivottable")
For Each pi In pt.DataPivotField.PivotItems
pi.Visible = False
Next
Well, I will give you the confirmation you need. It seems using the Orientation property on a "Calulated Field" just does not work, and I would have to agree this is a bug and not a common "usage" error. I was able to duplicate "hiding/showing" the field without having to remove ("Delete") the calculated field. This allows the user to physically drag the calculated field from the field list after you have progammatically "hidden" the field. This is not a bad solution because it duplicates the user-interface. (Using 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
[original answer]
Most likely you cannot hide this item because it is the last visible item. Instead, try removing it.
Here is a little workaround I discovered today, again not very elegant but at least it doesn't need much code, it will hide ALL the fields and you will need to reshow the ones you want after:
objTable.DataPivotField.Orientation = xlHidden
You may run into an error if excel for some reason thinks the datapivotfield is empty, but to fix this just add in another field as a datafield right before the above statement. Also make sure its the letter l not the number 1 in xlHidden vba's default font has them looking very very similar.
Happy Coding
It seems that to hide a calculated field you need to first hide a pivot field called "Values".
PivotTable(1).PivotFields("Values").Orientation = xlHidden
For Each PF In PT.DataFields
PF.Orientation = xlHidden
Next PF
I'm assuming that field only seem to exist if you've got two or more fields in your xlDataField position.
Thanks Alinboss for pointing me in the right direction. I was sure I tried your method before and failed - turns out the order is important!
P.s. Your code still does not work with only one calculated data field
Laurent Bosc's code checks out so I voted it up. My full code includes adding data after hiding it all. The code is placed on 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
I don't think this is an excel bug, I think it's a 'feature'. ;-)
Re: #AMissico, there is no problem in excel hiding all of the fields in a pivot table, but he may be talking about items - you can't hide the last item in a pivot field.
This is the code I routinely use to do what you are trying to do. These macros were developed on Excel 2002 & 2003. I don't hide CalculatedFields, I delete them.
' 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
I am having the exact same problem as you.
It looks like I'm going to have to delete the calculated field and readd it rather than hiding/showing it.
I accidentally discovered a workaround to this the first time I attempted to hide a calculated field, so thought I would share it here:
Instead of modifying the orientation property, you can instead instruct the code to select the cell in the pivot table that contains the title of the calculated field you want to hide, and then delete the selection. This works as long as you have another datafield already in the table. Example below:
Scenario: Pivot table covers the range A1:G10. Calculated field "Margin" is already in the table, and you want to add the data field "Sales" and remove the "Margin" calc field.
Code to execute:
'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
Not sure why this works, but I'm glad we at least have this to work with!
Fortunately there is a very easy way to hide a datafield. You were all wrong mistakeing pivotfields with datafields. I'm presenting a piece of code that empties a pivot table no matter how many pivot fields/data fields were initially in the pivot :
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
Have you changed the name of the calculated field? Was it originally 'Sum of MyField'? Try looking at the SourceName property and if it's different using that.
Have you tried pt.CalculatedFields("MyField").Orientation = xlHidden ?
I know it is kind of late, but i see that this problem has not been answered confidently yet and i was facing the same problem having hard time to find useful info. So, i hope this post may help somebody...
If you have your data stored in data model, then instead of PivotFields, use CubeFields .
I had the same problem and i experimented with a simple workbook which did not had a data model and my code worked perfectly (using PivotFields).
It only returned error in the workbook with the data model.
So, i made this change and boom! it worked!
My suggestion is to use the following code:
Sub PrRemove()
'remove PR
Dim pt As PivotTable
Set pt = ActiveSheet.PivotTables("MyPivot")
pt.CubeFields("MyField").Orientation = xlHidden '<- here is the error
End Sub
Thanks to #user4709164 answer i got this code, its working perfectly for me:
my pivot columns all ends with X or Y to indicate axis so i use the last char for field caption.
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