How to divide all values in a pivot table column by a constant - vba

I would like to scale (divide, multiply) a pivot tables value by some constant that I add into the pivot tables sheet, like so:
The problem of automatically updating the pivot tables values as the values in the original data change I already solved with this code:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
ActiveWorkbook.Worksheets("Sheet4").PivotTables(1).PivotCache.Refresh
End Sub
I have tried simply doing it inside a worksheet_change() method, but this gives type mismatch error:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("C4:C5"), Range(Target.Address)) Is Nothing Then
Application.EnableEvents = False
'Target.Value = Target.Value * Range("B1").Value <-- gives error of type mismatch
MsgBox VarType(Target.Value)
MsgBox VarType(Range("B1").Value)
Application.EnableEvents = True
End If
End Sub

Here is one way. When the event WorkSheet_Change fires, check if your scaling value (in B1) has changed. If so, re-write the calculated field:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("B1"), Range(Target.Address)) Is Nothing Then
ActiveWorkbook.Worksheets("Sheet4").PivotTables(1).CalculatedFields("ScaledField"). _
StandardFormula = "=Kaina*" & Range("B1").Value
End If
End Sub
You'll need to create a calculated field called ScaledField (or give it your own name - just change the code too) and you might want to change the formula if you don't want to scale [Kaina], but something else.
PS. If the value isn't [Kaina], but [Kaina Sausis] then the formula would require single quotes to wrap the field name:
StandardFormula = "='Kaina Sausis'*" & Range("B1").Value

Manipulating the value of data fields directly in the pivot table is not possible (try to manually change a value or with VBA and you get an error message).
It's possible to overwrite values of row fields, but that's a bit strange (they will stay like this after and not update anymore unless you by coincidence entered a valid value).
For calculations you can add a calculated field. If the value is constant and the value doesn't need to be taken from a Range just add a calculated field manually (Analyze > Fields ... > Calculated Field...) and enter the constant value in the formula.
Unfortunately calculated fields cannot reference ranges so if you really have to use the value from a Range in the formula of the calculated field you can use this VBA code (it adds a calculated field or updates the formula if the field already exists, that would be of use if the value is not constant):
' You prolly have to call this only once as you are using a constant value.
' If not add to your worksheet change event
' Modify hardcoded values if needed
Sub createOrUpdateField()
Dim fldFormula As String
' Construct the formula to use
fldFormula = "= Kaina Sausis / " & ActiveSheet.Range("B1").Value2
addOrUpdateCalculatedField _
ActiveSheet.PivotTables(1), _
"Kaina Sausis Calc", fldFormula, "0.00"
End Sub
' In case you want to remove the calculated field use this
' Or use the interface (Analyze > Fields ... > Calculated Field...)
Sub deleteField()
pt.PivotFields("Kaina Sausis Calc").Delete
End Sub
' Add a calculated field to pivot table or update formula if it already exists.
' Args:
' pt (PivotTable): The pivot table object
' fldName (String): Name to use for the field
' fldFormula (String): Formula to use for calculation
' fldFormat (String): Number format to use
Sub addOrUpdateCalculatedField(pt As PivotTable, fldname As String, _
fldFormula As String, fldFormat As String)
Dim wks As Worksheet
Dim ptfld As PivotField
' Try to reference the field to check if it already exists
On Error Resume Next
Set ptfld = pt.PivotFields(fldname)
On Error GoTo 0
If ptfld Is Nothing Then
' Field doesn't exist, add it
Set ptfld = pt.CalculatedFields.Add(name:=fldname, formula:=fldFormula)
With ptfld
.Caption = fldname
.NumberFormat = fldFormat
.Orientation = xlDataField
.Function = xlSum
End With
Else
' Field already exists, change the formula only
ptfld.StandardFormula = fldFormula
End If
Set wks = Nothing
Set pt = Nothing
Set ptfld = Nothing
End Sub

Related

VBA Form - Vlookup cell and assign value to that cell

Encountering an issue in a VBA regarding vlookup function.
I have 2 comboboxes and 6 Textboxs for user input.
I want to use a vlookup (or index,Match(),Match()) to look up a cell in a data table and assign the values from the textboxes to these cells.
When I run the code for what I believe should work, it is returning object errors.
Private Sub CommandButton2_Click()
Dim MonthlyTable As Range
Set MonthlyTable = Sheets("DATA Monthly").Range("A6:AE400")
Dim ColumnRef As Range
Set ColumnRef = Sheets("Drivers").Range("N11")
' Assign CB2 value to M11 cell reference so it can be converted to a column ref in N11.
Sheets("Drivers").Range("M11").Value = ComboBox2.Value
Dim CB1Value As String
CB1Value = "Joiners" & ComboBox1.Value
Dim CB2Value As String
CB2Value = ComboBox2.Value
MsgBox CB1Value & " " & CB2Value
Dim tb1value As Range
tb1value = Application.WorksheetFunction.VLookup(CB1Value, MonthlyTable, ColumnRef, False)
tb1value.Value = TextBox1.Value
Unload Me
End Sub
I am at a loss for what to do here as I feel like it should be this simple!
Thanks in advance.
Edit. Further digging indicates that you cannot select a cell you are vlookup'ing as this commands only returns a value it does not actually select the cell for my intents and purposes.
not really clear to me you actual aim, but just following up your desire as stated by:
I want to use a vlookup (or index,Match(),Match()) to look up a cell
in a data table and assign the values from the textboxes to these
cells
you may want to adopt the following technique:
Dim tb1value As Variant '<--| a variant can be assigned the result of Application.Match method and store an error to be properly cheeked for
tb1value = Application.Match(CB1Value, MonthlyTable.Column(1), 0) '<--| try finding an exact match for 'CB1Value' in the first column of your data range
If Not IsError(tblvalue) Then MonthlyTable(tb1value, columnRef.Value).Value = TextBox1.Value '<--| if successful then write 'TextBox1' value in data range cell in the same row of the found match and with `columnRef` range value as its column index
Excel uses worksheet functions to manipulate data, VBA has different tools, and when you find yourself setting cell values on a sheet via VBA so that some worksheet function can refer to them it is time to look for a true VBA solution. I suggest the following which, by the way, you might consider running on the Change event of Cbx2 instead of a command button.
Private Sub Solution_Click()
' 24 Mar 2017
Dim MonthlyTable As Range
Dim Rng As Range
Dim Lookup As String
Dim Done As Boolean
Set MonthlyTable = Sheets("DATA Monthly").Range("A2:AE400")
' take the lookup value from Cbx1
Lookup = ComboBox1.Value
Set Rng = MonthlyTable.Find(Lookup)
If Rng Is Nothing Then
MsgBox Chr(34) & Lookup & """ wasn't found.", vbInformation, "Invalid search"
Else
With ComboBox2
If .ListIndex < 0 Then
MsgBox "Please select a data type.", vbExclamation, "Missing specification"
Else
TextBox1.Value = MonthlyTable.Cells(Rng.Row, .ListIndex + 1)
Done = True
End If
End With
End If
If Done Then Unload Me
End Sub
There are two points that need explanation. First, the form doesn't close after a rejected entry. You would have to add a Cancel button to avoid an unwanted loop where the user can't leave the form until he enters something correct. Note that Done is set to True only when the search criterion was found And a value was returned, and the form isn't closed until Done = True.
Second, observe the use of the ListIndex property of Cbx2. All the items in that Cbx's dropdown are numbered from 0 and up. The ListIndex property tells which item was selected. It is -1 when no selection was made. If you list the captions of your worksheet columns in the dropdown (you might do this automatically when you initialise the form) there will be a direct relationship between the caption selected by the user (such as "Joiners") and the ListIndex. The first column of MonthlyTable will have the ListIndex 0. So you can convert the ListIndex into a column of MonthlyTable by adding 1.
I think it is better to use "find" in excell vba to select a cell instead of using vlookup or other methods.

VBA macro to change filters in pivot table

I'm trying do automate a daily report and therefore I want to create two buttons which change the filters of three pivot tables. In detail the buttons shall change the day which is shown. The first filters on yesterday the second one is a reset button do clear all filters and show all days.
The "Resest"-Button is working but the "Yesterday"-Button not.
At the moment the macro looks like that:
Private Sub CommandButton2_Click()
MsgBox ActiveSheet.Range("B1")
With ActiveSheet.PivotTables("Detail_Digital").PivotFields("Tag").CurrentPage = _
ACtiveSheet.Range("B1").Value
End With
End Sub
I've also tried PivotFilters.Add _ , Type:=xlDateYesterday but that isn't working either.
Any suggestions?
Try the code below, it should work, unless your "Date" is formatted differently between the Pivot's data source and Range("B1").
Note: try to avoid using ActiveSheet, instead use referenced objects. In the case below, replace Worksheets("Sheet1") with your sheet's name.
Code
Option Explicit
Private Sub CommandButton2_Click()
Dim PvtTbl As PivotTable
Dim PvtItm As PivotItem
' set the Pivot Table
Set PvtTbl = Worksheets("Sheet1").PivotTables("Detail_Digital")
With PvtTbl
.PivotFields("Tag").ClearAllFilters ' <-- clear all filters to "Tag"
'Debug.Print Worksheets("Sheet1").Range("B1").Value
For Each PvtItm In .PivotFields("Tag").PivotItems
If PvtItm.Name = Worksheets("Sheet1").Range("B1").Value Then
PvtItm.Visible = True
Else
PvtItm.Visible = False
End If
Next PvtItm
End With
End Sub

How do I get the name of a table from a range variable?

I dimmed the variable:
Dim mainTableRange As Range
Then gave it a value:
Set mainTableRange = Range("tLedgerData") ' tLedgerData is an Excel table.
Now I'm trying to get the name of the table (which is "tLedgerData") from the variable to reference columns in that table even if the table name changes.
I tried
mainTableRange.Name
and
mainTableRange.Name.Name
(See how do you get a range to return its name.) Both threw run-time error '1004': Application defined or object-defined error.
mainTableRange.Select selected all table data excluding the header and total rows.
I think you're having an X-Y problem here: solving problem X when the solution is for problem Y.
[...] to reference columns in that table even if the table name changes
Have the table / ListObject alone on its own dedicated worksheet, and give the sheet a CodeName. That way you can do this:
Dim tbl As ListObject
Set tbl = LedgerDataSheet.ListObjects(1)
And now you have the almighty power of the ListObject API to do whatever it is that you want to do. For example, retrieve the column names:
Dim i As Long
For i = 1 To tbl.ListColumns.Count
Debug.Print tbl.ListColumns(i).Name
Next
In other words, you don't need to care for the name of the table. What you want is to work with its ListObject. And since you never need to refer to it by name, the table's name is utterly irrelevant and the user can change it on a whim, your code won't even notice.
I believe an Excel table and named-range are two different things which is why the .name.name doesn't work. A table is a ListObject and once you set a range equal to a table you should be able to continue to call that range without an error.
Curious, what is the reason why your table might change unexpectedly?
I wrote out some lines of code to show a couple things. You can create tables and reuse the range variables after the table name changes. You can also set AlternativeText for the table with some identifying string and use that to locate a particular table if you suspect the table name may change.
Option Explicit
Public TestTable As Range
Sub CreateTable()
ActiveSheet.ListObjects.Add(xlSrcRange, [$A$1:$C$4], , xlYes).name = "Table1"
ActiveSheet.ListObjects("Table1").AlternativeText = "Table1"
End Sub
Sub SetTableRange()
Set TestTable = Range("Table1")
End Sub
Sub SelectTable()
TestTable.Select
End Sub
Sub RenameTable()
ActiveSheet.ListObjects("Table1").name = "Table2"
[A1].Select
End Sub
Sub SelectRenamedTable()
TestTable.Select
End Sub
Sub ClearSelection()
[A1].Select
End Sub
Sub FindTable1()
Dim obje As ListObject
For Each obje In ActiveSheet.ListObjects
If obje.AlternativeText = "Table1" Then
MsgBox "Found " & obje.AlternativeText & ". Its current name is: " & obje.name
End If
Next obje
End Sub
Sub ConvertTablesToRanges()
' I found this snippet in a forum post on mrexcel.com by pgc01 and modified
Dim rList As Range
On Error Resume Next
With ActiveSheet.ListObjects("Table1")
Set rList = .Range
.Unlist ' convert the table back to a range
End With
With ActiveSheet.ListObjects("Table2")
Set rList = .Range
.Unlist ' convert the table back to a range
End With
On Error GoTo 0
With rList
.Interior.ColorIndex = xlColorIndexNone
.Font.ColorIndex = xlColorIndexAutomatic
.Borders.LineStyle = xlLineStyleNone
End With
End Sub

Searching and Returning bold values in VBA

I know that this probably isn't the most ideal way to to do this but just bear with me.
I have a document with a few tables on it. I'm using a userform to search the tables/sub-categories and return the relevant values. I want to select the sub categories with a range of option buttons on a userform, these will in turn set the range for the search function to look within. I also want to dynamically update the option buttons if a new table was to be added or anything along those lines.
The only thing that differentiates the title of a sub-category/table, and the items within it, is that the title of a sub-category/table is bold. So what I'm looking to do is search the first column of the spreadsheet and return the names of any entries in bold. These values are then used to set the names of the option buttons :).
The following function is my attempt at finding the text entities in column a that are in bold, returning them and setting each to an individual variable to be used in another function. The bold1 .... variables are all globally defined variables as I need them in another sub, as is the page variable which contains the relevant page to be used. Currently the code returns an error stating "variable or with block not set" and using the debugger I can see that bold1 .... and all the other boldx variables have no value set. Does anybody know whats going on/how to fix this function.
Thanks in advance :)
Sub SelectBold()
Dim Bcell As Range
For Each Bcell In Worksheets(Page).Range("A1:A500")
If Bcell.Font.Bold = True Then
Set bold1 = Bcell
End If
Next
End Sub
EDIT: I simplified the above function, to remove clutter and help narrow in on the issue. I want the above function to store the contents of the found cell (any cell in the document in bold at this stage) in the variable bold1
This will return an array of values from bold cells in column A of Page.
You can fill a combo or list box with theses values using their list property.
ComboBox1.List = getSubCategories("Sheet1")
Function getSubCategories(Page As String) As String()
Dim arrSubCategories() As String
Dim count As Long
Dim c As Range
With Worksheets(Page)
For Each c In .Range("A2", .Range("A" & Rows.count).End(xlUp))
If c.Font.Bold Then
ReDim Preserve arrSubCategories(count)
arrSubCategories(count) = c.Value
count = count + 1
End If
Next
End With
getSubCategories = arrSubCategories
End Function
you may find useful to have a Range returned with subcategories cells found:
Function SelectBold(Page As String, colIndex As String) As Range
With Worksheets(Page)
With .Range(colIndex & "1", .Cells(.Rows.Count, colIndex).End(xlUp)).Offset(, .UsedRange.Columns.Count)
.FormulaR1C1 = "=if(isbold(RC[-1]),"""",1)"
.Value = .Value
If WorksheetFunction.CountA(.Cells) < .Rows.Count Then Set SelectBold = Intersect(.SpecialCells(xlCellTypeBlanks).EntireRow, .Parent.Columns(1))
.Clear
End With
End With
End Function
Function IsBold(rCell As Range)
IsBold = rCell.Font.Bold
End Function
to be possibly exploited as follows:
Option Explicit
Sub main()
Dim subCategoriesRng As Range, cell As Range
Set subCategoriesRng = SelectBold(Worksheets("bolds").Name, "A") '<--| pass worksheet name and column to search in
If Not subCategoriesRng Is Nothing Then
For Each cell In subCategoriesRng '<--| loop through subcategories cells
'... code
Next cell
End If
End Sub

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