Excel VBA: Output Distinct Values and Subtotals - vba

I have data of this form:
Category Source Amount
Dues FTW $100
Donations ODP $20
Donations IOI $33
Dues MMK $124
There is no sort order. The categories are unknown at compile time. I want a VBA macro to cycle through the range, output a list of distinct values, with the subtotals for each. For the above data, it would look like this:
Category Total Amount
Dues $224
Donations $55
How can I do this? Also, is there a way to make the macro run every time the table above is updated, or is it necessary for the user to click a button?

You may want to use a built in Excel feature to do this. Looping can take a long time and be problematic if you have a lot of values to loop through.
Something like the following might get you started on creating a pivot table (from http://www.ozgrid.com/News/pivot-tables.htm)
Sub MakeTable()
Dim Pt As PivotTable
Dim strField As String
'Pass heading to a String variable
strField = Selection.Cells(1, 1).Text
'Name the list range
Range(Selection, Selection.End(xlDown)).Name = "Items"
'Create the Pivot Table based off our named list range.
'TableDestination:="" will force it onto a new sheet
ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, _
SourceData:="=Items").CreatePivotTable TableDestination:="", _
TableName:="ItemList"
'Set a Pivot Table variable to our new Pivot Table
Set Pt = ActiveSheet.PivotTables("ItemList")
'Place the Pivot Table to Start from A3 on the new sheet
ActiveSheet.PivotTableWizard TableDestination:=Cells(3, 1)
'Move the list heading to the Row Field
Pt.AddFields RowFields:=strField
'Move the list heading to the Data Field
Pt.PivotFields(strField).Orientation = xlDataField
End Sub
This is for subtotals (though I much prefer pivot tables)
http://msdn.microsoft.com/en-us/library/aa213577(office.11).aspx
EDIT:
I reread and have the following thoughts. Set up the pivot table on a separate sheet (without using any code) then put the following code on the sheet that has the pivot table so that the table will update everytime the sheet is selected.
Private Sub Worksheet_Activate()
Dim pt As PivotTable
'change "MiPivot" to the name of your pivot table
Set pt = ActiveSheet.PivotTables("MyPivot")
pt.RefreshTable
End Sub
Edit #2
Refresh all pivot tables on sheet
http://www.ozgrid.com/VBA/pivot-table-refresh.htm
Private Sub Worksheet_Activate()
Dim pt As PivotTable
For Each pt In ActiveSheet.PivotTables
pt.RefreshTable
Next pt
End Sub
The link has multiple options on how to refresh pivot tables in the sheet/workbook.

Related

Excel VBA Loop Through a PivotTable and perform calculation

I have a PivotTable that automatically refreshes every time I refresh a data set to our mySQL database in our office.
My Excel file launches a query against the mySQL database and returns a data table, and I have two PivotTables on separate sheets that will automatically update every time that is done. My code for that is below:
Sub UpdatePivots()
' This sub is intended to update all pivot charts in the by switching to the appropriate
' worksheet, locating the appropriate pivot table, and updating them.
Dim ws As Worksheet
Dim PT As PivotTable
For Each ws In ActiveWorkbook.Worksheets '<~~ Loop all worksheets in workbook
For Each PT In ws.PivotTables '<~~ Loop all pivot tables in worksheet
PT.PivotCache.Refresh
Next PT
Next ws
End Sub
What I am looking to do calculate a YIELD for some of the fields in the Pivot Table. The table currently looks like this below:
As you can see, I added in the "YIELD" column automatically and simply did an:
=GETPIVOTDATA("Pass / Fail",$B$5,"Job ID","Job 1","Pass / Fail","Pass")/GETPIVOTDATA("Pass / Fail",$B$5,"Job ID","Job 1")
Ideally, what I would like to do is add to my UpdatePivots() macro to automatically calculate the yield (Pass / Grand Total) for each of the rows listed.
This table is subject to change in size - sometimes I am looking at only 3 jobs in a given month (like September so far), other times my boss wants me to run this report for an entire year where I can have an upwards of 100 jobs. So I would like to use some pseudo code that might look like this:
Cell F6.Text = YIELD
<Apply Pivot Table Formatting to Cell F6>
for each row in pivottable {
Cell Fx.Value = Pass / Grand Total
}
Can anybody help me do that? I have tried brainstorming on paper, but don't even know where to start.
PS - How can I get the Pivot Table to stop that terrible formatting, and to keep my grayed cells? I want to eventually add in charts.
Thank you!!
The following code satisfies my need:
Sub CalculateYield()
k = Cells(Rows.Count, 2).End(xlUp).Row
For r = 9 To k
Cells(r, 6).Formula = "=" & Cells(r, 3).Address(False, False) & "/" & Cells(r, 5).Address(False, False)
Next
End Sub

How to adjust PivotTable Filters

I'm trying to create a macro that will pull some data from a pivot table into a collection variable. What I'm wanting to do is to collect each Article's Sales Forecast and Insight each month for a single year (image below). The issue I have is that I don't know how to collect the information without it being shown in the pivot table, and I don't know how to have the macro adjust the column filters to meet my requirements.
I don't have access to the source of this pivot table and I'm reluctant to have the user manually adjust the table's column filters.
For clarification, the column filter goes by Year -> Quarter -> Month -> Week.
Edit:
What I'm trying to accomplish starts with a schedule workbook where the relevant article numbers are kept. The Master Scheduler has a different workbook with the input values (pivot table above) to base the calculations. This input workbook only has pivot tables and I don't know where it pulls the data; just this is where the Master Scheduler manually finds the relevant data.
My thought process is to pull the relevant articles from the scheduling workbook, pull all of the articles for one full year, sort out only the relevant articles, and place the sorted information into a new location in the Schedule workbook.
The issue I'm coming across is that the column filters may not be showing all of the relevant data and I don't know how to make VBA set the pivot table's filter to prevent this. The solutions that I have found changes the F9 cell, "Year," to an actual year value, which is not what I want to do.
In addition, when you manually open the column filter to select which year, there are four quarters (or seasons) where all four must have a check mark in the box for all twelve of the months to be available.
Hopefully this clarifies my question.
After some more research, I found this website that answers my question: Expand and Collapse Entire Pivot Table Fields – VBA Macro. I've also learned about the pt.ClearAllFilters command.
If the website becomes unavailable in the future, the code is also listed below.
Expand:
Sub Expand_Entire_RowField()
'Expand the lowest position field in the Rows area
'that is currently expanded (showing details)
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim iFieldCount As Long
Dim iPosition As Long
'Create reference to 1st pivot table on sheet
'Can be changed to reference a specific sheet or pivot table.
Set pt = ActiveSheet.PivotTables(1)
'Count fields in Rows area minus 1 (last field can't be expanded)
iFieldCount = pt.RowFields.Count - 1
'Loop by position of field
For iPosition = 1 To iFieldCount
'Loop fields in Rows area
For Each pf In pt.RowFields
'If position matches first loop variable then
If pf.Position = iPosition Then
'Loop each pivot item
For Each pi In pf.PivotItems
'If pivot item is collapsed then
If pi.ShowDetail = False Then
'Expand entire field
pf.ShowDetail = True
'Exit the macro
Exit Sub
End If
Next pi
End If
Next pf
'If the Exit Sub line is not hit then the
'loop will continue to the next field position
Next iPosition
End Sub
Collapse:
Sub Collapse_Entire_RowField()
'Collapse the lowest position field in the Rows area
'that is currently expanded (showing details)
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem
Dim iFieldCount As Long
Dim iPosition As Long
'Create reference to 1st pivot table on sheet
'Can be changed to reference a specific sheet or pivot table.
Set pt = ActiveSheet.PivotTables(1)
'Count fields in Rows area minus 1 (last field can't be expanded)
iFieldCount = pt.RowFields.Count - 1
'Loop backwards by position of field (step -1)
For iPosition = iFieldCount To 1 Step -1
'Loop fields in Rows area
For Each pf In pt.RowFields
'If position matches first loop variable then
If pf.Position = iPosition Then
'Loop each pivot item
For Each pi In pf.PivotItems
'If pivot item is expanded then
If pi.ShowDetail = True Then
'Collapse entire field
pf.ShowDetail = False
'Exit the macro
Exit Sub
End If
Next pi
End If
Next pf
'If the Exit Sub line is not hit then the
'loop will continue to the next field position
Next iPosition
End Sub
Edit: Solution Specific
Dim pt As PivotTable
Dim pf As PivotField
Set pt = ws.PivotTables(1)
'Setting all of the column filters to desired setup
For Each pf In pt.ColumnFields
pf.Hidden = False
pf.ClearAllFilters
'Drill Down until Months are opened, then exit the loop
If UBound(Split(pf.Name, "Month")) > 0 Then
pf.DrilledDown = False '<-- Ensuring nothing beneath "Months" is
Exit For
Else
pf.DrilledDown = True
End If
Next

Extracting data out of Pivot Table

I have a pivot table set up(see image to get a better idea). I am trying to extract data from the pivot table based on the country. You can see that the row country gives access to the row region, and the row region gives access to row product. I want to copy the data under the constraint of: France to get both regions, all products, and the sum of price and move it to sheet2.
Here is my idea how I could go about it, but the select method is not supported in the current property/method. How might I go about selecting all of the data under france?
Sheets("MY Pivot").PivotTables("MY_Pivot").PivotFields("Country").PivotItems("France" _
).ShowDetail = True 'Show pivot item
Sheets("MY Pivot").PivotTables("MY_Pivot").PivotFields("Country").PivotItems("France" _
).Select 'Select pivot item to copy
Selection.Copy 'Copy the pivot items
Sheets("Sheet2").Range("A1").Select 'Select sheet cell for paste
Sheets("Sheet2").Paste 'Paste the selected France results
You can copy the .PivotItems("France").DataRange.EntireRow to "Sheet2", without the need to use Select.
Code
Option Explicit
Sub CopyPivotItemDataRange()
Dim PvtTbl As PivotTable
Dim PvtFld As PivotField
' set the Pivot Table object
Set PvtTbl = Sheets("MY Pivot").PivotTables("MY_Pivot")
' set the Pivot Field object
Set PvtFld = PvtTbl.PivotFields("Country")
With PvtFld
.PivotItems("France").ShowDetail = True 'Show pivot item
' copy >> paste the entire Range data under "France" to "Sheet2"
.PivotItems("France").DataRange.EntireRow.Copy Destination:=Sheets("Sheet2").Range("A1")
End With
End Sub

Use VBA to capture the fields in pivot table

We can use below code to build a Pivot Table (This is a pivot table created by Power Pivot).
With ActiveSheet.PivotTables("PivotTable1").CubeFields(FieldName)
.Orientation = Orientation
.Position = Position
Is there some way to reverse the process? Suppose user has built a pivot table. We use VBA to capture the fields used on the table (find out corresponding FieldName(s), Orientation(s), and Position(s)) and save them, so next time, user can just run the macro and create the same pivot table again.
Thanks
Thanks to #OpiesDad. Below will work.
Sub Func1()
Dim objCubeFld As PivotField
Dim pvt As PivotTable
Set pvt = ActiveSheet.PivotTables("PivotTable1")
For Each objCubeFld In pvt.PivotFields
MsgBox objCubeFld & "-" & objCubeFld.Orientation
Next objCubeFld
End Sub

select range for Pivot in VBA

I want to create a macro for Pivot table with dynamic range. Pivot table is already made , I am just want to make Dynamic range selection macro. Range is A2:L
Please help Me how to create macro for just range selection and refresh All.
Sum of Amount in Document Currency Document Currency
Company Code Trading Partner BGN EUR
BG05 CH10 272,326.08 1,618.00
HS03 RS31 1,618.00
Below code is Woking for me. Got resolution.
Sub ChangeCaches()
Dim PT As PivotTable
Set PT = Sheets("OPEN ITEMS DETAIL").PivotTables("PivotTable1")
PT.SourceData = Sheets("Download").Range("A1").CurrentRegion.Address(True, True, xlR1C1, True)
End Sub