I'm trying to make a report form that will ask what month and year you want the report to show. However, there is a specific pivot table that uses a four-year range to show trends data.
However, all the pivot tables on my workbook are connected through Power Pivot/Data Model. Using this source here, I was able to easily change slicers for single-items only.
An example that's working:
ActiveWorkbook.SlicerCaches("Slicer_Month2").VisibleSlicerItemsList = "[Calendar].[Month].&[" & frmGen.cbMonth.Text & "]"
But when I used a loop to replace multiple selections in the slicer, I've encountered an error after it's done looping all of the selection, with an error '28': Out of stack space.
For i = 0 To 3 Step 1
ActiveWorkbook.SlicerCaches("Slicer_Year").VisibleSlicerItemsList(i + 1) = "[Calendar].[Month].&[" & frmGen.txtYear.Text - 3 + i & "]"
Next
Since there's already four that was selected on the slicer, it should have been able to replace it, which is also shown when I added the code onto the watch window. But it always show that error after the loop, even if I lower the loop count.
Is there another way of selecting multiple items in a slicer that's connected through Power Pivot?
Thanks to Damian for providing a clue to my problem, I simply had to update one of the pivot tables that's linked to the slicer and it updated the other pivots just fine.
For i = 0 To 3 Step 1
ar(i) = "[Calendar].[Year].&[" & frmGen.txtYear.Text - 3 + i & "]"
Next
ActiveWorkbook.Sheets("pg2").PivotTables("pvtPg2_SPARK").PivotFields("[Calendar].[Year].[Year]").VisibleItemsList = ar
Related
I am trying to compare spending data from two sources: a curated manual input from users and an automated extract, for different business units. The common data from both sources is the ID of the spending.
The idea is to aggregate both data sources (excel Tables) into one Table where the first two columns are the ID of the spending, the next column is the spending data from users related to that ID and the last one is the spending data from automated extract.
In this table, I'll have "double" the total spending for each ID, but then I can do a pivot table where I'll clearly compare the users input with the automated extract for each ID.
I highlighted the important fields I need to copy and paste.
[![PGIvsManual][3]][3]
My code is the following
Sub PGIvsManualInput()
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set PGIvsManualTable = Worksheets("PGI vs Dépenses (Auto)").ListObjects("PGIvsManualInputAuto")
Set PGITable = Worksheets("PGI Clean").ListObjects("PGIExtract")
Set ManualInputTable = Worksheets("Dépenses").ListObjects("Dépenses")
'Cleaning the table
With Worksheets("PGI vs Dépenses (Auto)").Range("PGIvsManualInputAuto")
.ClearContents
.Borders(xlInsideHorizontal).LineStyle = xlNone
End With
With PGIvsManualTable
If .ListRows.Count >= 1 Then
.DataBodyRange.Rows.Delete
End If
End With
'Copy the data
PGITable.ListColumns(1).DataBodyRange.Resize(, 2).Copy Destination:= _
PGIvsManualTable
Ant that's where it gets messy. I can't even get the first batch of data to properly import! I am trying to copy the 2 first columns from PGITable and paste them in the 2 first columns of PGIvsManualTable. This worked previously without defining any destination column in my first example, even though both the input and destination Tables didn't have the same number of columns
But in this case, it extends the pasting to all columns of my destination table! I don't understand this comportment as it doesn't happen on my previous example with basically the exact same code!!
I tried to set the destination as follows but always got errors:
PGIvsManualTable.ListColumns(1).DataBodyRange.Resize(, 2) ==> Error 91
PGIvsManualTable.DataBodyRange(1,1) ==> Error 438
PGIvsManualTable.ListColumns(1).Resize(, 2) ==> Error 438
And a few others, but it never worked properly.
I expect the output to be my selected columns copy/pasted properly in my destination column, based on the coordinates I provide in the ListObecjts.DataBodyRange.
I guess that if I manage to make this first import work, all other will work on the same template, but in the meantime, my code seem to work on the previous example.
Deletion of the DataBodyRange.Rows will cause an issue if you then try to paste into the DataBodyRange.
As a workaround, you could delete all rows after the first, something like this example:
Sub Test()
Dim firstTbl As ListObject, secondTbl As ListObject
Set firstTbl = Sheet1.ListObjects("Table1")
Set secondTbl = Sheet1.ListObjects("Table2")
With secondTbl
.DataBodyRange.Clear
If .ListRows.Count > 1 Then
.DataBodyRange.Offset(1).Resize(.ListRows.Count - 1).Rows.Delete
End If
End With
firstTbl.ListColumns(1).DataBodyRange.Resize(, 2).Copy secondTbl.DataBodyRange(1, 1)
End Sub
I have an excel OLAP pivot table which has a filter above. The filter is hierarchical in that you can drill down and down several levels to see what you want to see.
I am trying to use VBA to filter to a specific level and then loop through all that level's child items to perform additional actions. My problem is figuring out how to get to that list of child items. I can filter to the level I need but that's where things get sticky.
ActiveSheet.PivotTables("PivotTable1").PivotFields( _
"[Accounts].[Business Bankers].[Cost Centre Code5]").VisibleItemsList = Array( _
"[Accounts].[Business Bankers].[Cost Centre Code5].&[" & AreaArr(i, 2) & "]")
For Each pi2 In ActiveSheet.PivotTables("PivotTable1").PivotFields( _
"[Accounts].[Business Bankers].[Cost Centre Code6]").PivotItems
MsgBox pi2.Caption
MsgBox pi2.Value
MsgBox Right(pi2.Caption, Len(pi2.Caption) - 11)
Worksheets("Town").Copy ActiveSheet.Name = Right(pi2.Caption, Len(pi2.Caption) - 11)
Next
That for each loop doesn't work. I am trying to figure out how to loop through all the child items that exist for Cost Centre Code5.
Thanks!
What I've found, in Excel 2010, is that when only one item is selected, PivotTables("x").PivotFields("y").PivotItems.Count is 0. Therefore any looping is not executed.
This is the case even if your filter has Select Multiple Items checked. In other words, you need to have Select Multiple Items and have more than one item selected so that you can loop over the collection. Very annoying.
You can supposedly access your one selected item as follows PivotTables("x").PivotFields("y").PivotItems according to MS documentation, but I've found that if I try to assign that method to a PivotItem variable I get a Type Mismatch. Contrary to the documentation, the method returns a PivotItems type every time. Unfortunately, it has a count of zero when there is only a single selected item, so you cannot inspect it.
I am trying to create a menu with list boxes in order to be able to select a number of customers from a list in an excel sheet. There are two list boxes, one with all the (default) data and one with the selected customers.
There is no problem adding one customer but when I add a second customer the graphic interface shows nothing, but after some debugging, the SelectedCustomers.RowSource still have the two rows in its data:
?SelectedCustomers.RowSource
$8:$8,$11:$11
This would have me believe there is some error with how I save the data or some limitations to Excel that I am not aware of. This is the code I use to save the data:
Private Sub CommandButton5_Click()
Dim temp As Range
For i = 0 To DefCustomers.ListCount - 1
If DefCustomers.Selected(i) = True Then
If temp Is Nothing Then
Set temp = Range(Rows(i + 4).Address)
Else
Set temp = Application.Union(temp, Range(Rows(i + 4).Address))
End If
End If
Next i
SelectedCustomers.RowSource = temp.Address
End Sub
Has someone experienced this before or know what the problem might be?
Instead of RowSource use AddItem method:
For i = 0 To DefCustomers.ListCount - 1
If DefCustomers.Selected(i) Then
SelectedCustomers.AddItem DefCustomers.Selected(i)
End If
Next i
There are known issues with ListBox.RowSource property in Excel VBA.
[EDIT]
After the discussion...
No matter of number of columns, you can copy rows from source sheet into another sheet, then bind SelectedCustomers listbox to that data
I've got a pivot table with 2 report filters I'm setting them to "Ashley" and 112 respectively. The data table has both but not on the same line so the pivot table should return a blank or 0 for the sum of the data I want to retrieve.
If I set these report filters in as stated above all goes well, but if I do it in vba excel crashes.
here is my code
.PivotTables("TtlGinShiftDT").PivotFields("Gin").ClearAllFilters
.PivotTables("TtlGinShiftDT").PivotFields("Gin").CurrentPage = CStr(.Cells(NewPTData + 1, 3))
.PivotTables("TtlGinShiftDT").PivotFields("Shift").ClearAllFilters
.PivotTables("TtlGinShiftDT").PivotFields("Shift").CurrentPage = CStr(.Cells(NewPTData + 1, 1))
Most of the time the 2 filters would have some valid data, but occasionally not, so it's been running fine up until today.
As a work around I've put an if statement before I do line 4 in the code which references a countifs formula on the worksheet (using the filter values).
This gets me by, but it seems like it shouldn't be so. What am I doing wrong
C-H
office 2010
I have a dataset with 60+ thousand rows in excel and about 20 columns. The "ID column" sometimes repeats itself and I want to add a column that will return 1 only in the row that is the most recent only IF it repeats itself.
Here is the example. I have…
ID DATE ColumnX
AS1 Jan-2013 DATA
AS2 Feb-2013 DATA
AS3 Jan-2013 DATA
AS4 Dec-2013 DATA
AS2 Dec-2013 DATA
I want…
ID DATE ColumnX New Column
AS1 Jan-2013 DATA 1
AS2 Feb-2013 DATA 0
AS3 Jan-2013 DATA 1
AS4 Dec-2013 DATA 1
AS2 Dec-2013 DATA 1
I've been trying with a combination of sort and nested if's, but it depends on my data being always in the same order (so that it looks up the ID in the previous row).
Bonus points: consider my dataset if fairly large for excel, so the most efficient code that won't eat up processor would be appreciated!
An approach you could use is to point MSQuery at your table and use SQL to apply the business rules. On the positive side, this runs very quickly (a couple seconds in my tests against 64k rows). A huge minus is the query engine does not seem to support Excel tables exceeding 64k rows, but there might be ways to work around this. Regardless, I offer the solution in case it gives you some ideas.
To set up first give your data set a named range. I called it MYTABLE. Save. Next select a cell to the right of your table in row 1, and click through Data | From other sources | from Microsoft Query. Choose Excel Files* | OK, browse for your file. The Query Wiz should open, showing MYTABLE available, add all the columns. Click Cancel (really), and click Yes, you want to continue editing.
The MSQuery interface should open, click the SQL button and replace the code with the following. You will need to edit some specifics, such as the file path. (Also, note I used different column names. This was sheer paranoia on my part. The Jet engine is very finicky and I wanted to rule out conflicts with reserved words as I built this.)
SELECT
MYTABLE.ID_X,
MYTABLE.DATE_X,
MYTABLE.COLUMN_X,
IIF(MAXDATES.ID_x IS NULL,0,1) * IIF(DUPTABLE.ID_X IS NULL,0,1) AS NEW_DATA
FROM ((`C:\Users\andy3h\Desktop\SOTEST1.xlsx`.MYTABLE MYTABLE
LEFT OUTER JOIN (
SELECT MYTABLE1.ID_X, MAX(MYTABLE1.DATE_X) AS MAXDATE
FROM `C:\Users\andy3h\Desktop\SOTEST1.xlsx`.MYTABLE MYTABLE1
GROUP BY MYTABLE1.ID_X
) AS MAXDATES
ON MYTABLE.ID_X = MAXDATES.ID_X
AND MYTABLE.DATE_X = MAXDATES.MAXDATE)
LEFT OUTER JOIN (
SELECT MYTABLE2.ID_X
FROM `C:\Users\andy3h\Desktop\SOTEST1.xlsx`.MYTABLE MYTABLE2
GROUP BY MYTABLE2.ID_X
HAVING COUNT(1) > 1
) AS DUPTABLE
ON MYTABLE.ID_X = DUPTABLE.ID_X)
With the code in place MSQuery will complain the query can't be represented graphically. It's OK. The query will execute -- it might take longer than expected to run at this stage. I'm not sure why, but it should run much faster on subsequent refreshes. Once results return, File | Return data to Excel. Accept the defaults on the Import Data dialog.
That's the technique. To refresh the query against new data simply Data | Refresh. If you need to tweak the query you can get back to it though Excel via Data | Connections | Properties | Definition tab.
The code I provided returns your original data plus the NEW_DATA column, which has value 1 if the ID is duplicated and the date is the maximum date for that ID, otherwise 0. This code will not sort out ties if an ID's maximum date is on several rows. All such rows will be tagged 1.
Edit: The code is easily modified to ignore the duplication logic and show most recent row for all IDs. Simply change the last bit of the SELECT clause to read
IIF(MAXDATES.ID_x IS NULL,0,1) AS NEW_DATA
In that case, you could also remove the final LEFT JOIN with alias DUPTABLE.
Sort by ID, then by DATE (ascending). Define entries in new column to be 1 if previous row has the same ID and next row has a different ID or is empty (for last row), 0 otherwise.
It could be done in VBA. I'd be interested to know if this is possible just using formulas, I had to do something similar once before.
Sub Macro1()
Dim rowCount As Long
Sheets("Sheet1").Activate
rowCount = Cells(Rows.Count, 1).End(xlUp).Row
Columns("A:D").Select
Selection.AutoFilter
Range("D2:D" & rowCount).Select
Selection.ClearContents
Columns("A:D").Select
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Add Key:=Range _
("B1:B" & rowCount), SortOn:=xlSortOnValues
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.SortFields.Add Key:=Range _
("A1:A" & rowCount), SortOn:=xlSortOnValues
ActiveWorkbook.Worksheets("Sheet1").AutoFilter.Sort.Apply
Dim counter As Integer
For counter = 2 To rowCount
Cells(counter, 4) = 1
If Cells(counter, 1) = Cells(counter + 1, 1) Then Cells(counter, 4) = 0
Next counter
End Sub
So you activate the sheet and get the count of rows.
Then select and autofilter the results, and clear out Column D which has the 0s or 1s. Then filter on the values mbroshi suggested that you say you're already using. Then execute a loop for each record, changing the value to 1, but then back to 0 if the value ahead of it has the same ID.
Depending on your processor I dont think this would take more than a minute or two to run. If you do find something using formulas I would be interested to see it!