I have a pivot table that is connected to cube. My main goal is to go through all filters in this pivot and download a list of all filtered elements.
I have this part of the code:
Dim pv As PivotTable
Set pv = Sheet2.PivotTables("PivotTable1")
'read data from filters section
For Each ffield In pv.PageFields
On Error Resume Next
a = ffield.Name
'to check if in filter there is "multiple item" selected we have to shorten the string
'eg. if filter field is [Service Line].[Function].[SubFunction] (hierarchy)
'we have to check only CubeFields [Service Line].[Function]
reverse_a = StrReverse(a)
first_dot = Application.Find(".", reverse_a)
proper_string = Left(a, Len(a) - first_dot)
is_marked_multiple = pv.CubeFields(proper_string).EnableMultiplePageItems
'to list all item that are selected with multiple item we use
'visibleitemlist method
'if multiple item is not checked we use
'currentpagename method
If is_marked_multiple Then
items_filtered = pv.PivotFields(a).VisibleItemsList
Else
items_filtered = pv.PivotFields(a).CurrentPageName
End If
Next
Everything is ok when I have filtered some data with multiple items checked - macro uses "VisibleItemsList" method
eg:
output:
If multiple item is not checked it also works fine - it uses "CurrentPageName" method:
eg:
output:
The problem is when I have checked multiple items selection and I have nothing filtered (meaning all is selected)
eg:
output:
the output is just an empty string...
What am I doing wrong in this case?
I need the filter fields because based on this I am creating other table.
I would appreciate any comments/links to help me with the case!
Related
I have created an array in VBA in my Access application, and when I run it I get the intended results in the immediate window. What I am trying to do now is to take that array and put it into a form control (possibly a subform dataset?). I do not know how to this though on a multidimensional array. Below is the code that creates my array (it's dynamic, it can contain from zero to 10 results depending on how many records are in the DB.
' We need to get all of the participants for this engagement (Name, Email, Division and Role)
strSQL4 = "SELECT tblPerson.Person_FName, tblPerson.Person_LName, tblPerson.Email, tblORD_Division.ORD_Div, tblEngParRole.Role FROM tblORD_Division INNER JOIN ((tblEngagements INNER JOIN tblEngParRole ON tblEngagements.ENG_ID = tblEngParRole.Eng_ID) INNER JOIN tblPerson ON tblEngParRole.Person_ID = tblPerson.Person_ID) ON tblORD_Division.ORD_DIv_ID = tblPerson.ORD_Div_ID WHERE tblEngagements.Eng_ID = " & Me.Eng_ID
Set rs4 = CurrentDb.OpenRecordset(strSQL4)
rs4.MoveLast
rs4.MoveFirst
'Let's retrieve ALL Rows in the rs4 Recordset
varParticipants = rs4.GetRows(rs4.RecordCount)
Debug.Print "******************************************" 'Column Format only
Debug.Print "Last Name", "First Name", "Email", , "ORD_Div", "Role"
Debug.Print "---------------------------------------------------------------------------------------------"
For intRowNum = 0 To UBound(varParticipants, 2) 'Loop thru each Row
For intColNum = 0 To UBound(varParticipants, 1) 'Loop thru each Column
'To Print in Table Format, no numbered Fields or Rows
Debug.Print varParticipants(intColNum, intRowNum),
Next
Debug.Print vbCrLf
Debug.Print "******************************************" 'Column Format only
Next
rs4.Close
Set rs4 = Nothing
Thanks
Access doesn't provide a convenient way to display an array on a form. Skip the array and use a form/subform approach to display your data.
Build a query similar to your current query, but with these two changes:
Include tblEngagements.Eng_ID in the list of SELECT columns.
Discard the WHERE clause so the query will return all rows regardless of their Eng_ID values.
Build a new form based on that query.
Add the new form as a subform to your original form. On the subform control's property sheet, set the Link Master Fields and Link Child Fields properties to Eng_ID
Then, in operation, the subform should display only those rows whose Eng_ID values match the Eng_ID of the current row in the parent form.
In an Excel pivot table, when I select multiple items in a report filter, Excel just displays that I have selected multiple items.
Data
I can select multiple items:
However, once the selection is done, I don't see which elements I have selected.
I want to display which items are selected, e.g. when the report is printed. I found a way to do this using VBA and a user defined function.
Function GetVisibleItems(FieldName As String) As String
Dim PivotTable As PivotTable
Set PivotTable = ActiveSheet.PivotTables(1)
Dim PivotField As PivotField
Set PivotField = PivotTable.PivotFields(FieldName)
Dim PivotItem As PivotItem
Dim Result As String
For Each PivotItem In PivotField.PivotItems()
If PivotItem.Name <> "(blank)" Then
If PivotItem.Visible Then
If Len(Result) > 0 Then Result = Result & ", "
Result = Result & PivotItem.Name
End If
End If
Next
GetVisibleItems = Result
End Function
Is it possible to get the same result using just Excel formulae, not VBA?
Martin - This probably isn't as straight forward as you are looking for, but using workbook functions to build the string you are looking for ...
Below is a simple table of information ...
... and a pivot table created from it ...
In the pivot, you can see that Person 2 and Person 6 are filtered out.
Back at the table, a column was added using this formula (filled down) ...
=IF(ISERROR(GETPIVOTDATA("Grade",Sheet5!$A$3,$A$1,A2)),"",A2)
Note: Sheet5 contains the Pivot table. A3 is the top left corner of the pivot.
Providing this result ...
Where there are blanks instead of Person 2 and Person 6.
The string was generated using Chip Pearson's StringConcat UDF because it's more compact than all the typing needed with & or CONCATENATE ...
What I was looking for is provided by Slicers. A slicer shows the range that has been selected and is printable. Writing the list of visible Pivot Elements into a cell is possible, maybe even with a tricky Excel formula, but seems like over-engineering it.
The TEXTJOIN function can do this. Excel 2016 onwards.
The TEXTJOIN function combines the text from multiple ranges and/or strings, and includes a delimiter you specify between each text value that will be combined. If the delimiter is an empty text string, this function will effectively concatenate the ranges.
I have a Data table with an Auto Filter (shown Below).
Sub Tariff_Filter()
Dim columnNumber, tableRow, tableColumn, tableWidth As Integer
Dim tableName, columnName As String
tableName = "Tariff_Table"
columnName = ActiveSheet.Range("A1").Value
'This clears the existing filter
ActiveSheet.ListObjects(tableName).Range.AutoFilter
'Assign some numbers we need to know about the table to check the headers
tableRow = ActiveSheet.ListObjects(tableName).Range.Row
tableColumn = ActiveSheet.ListObjects(tableName).Range.Column
tableWidth = ActiveSheet.ListObjects(tableName).Range.Columns.Count
'If a column title with the specified value does not exist VBA throws an error which we need to catch
On Error GoTo ErrorHandler
'Search through the table column header row to find the specified column and assign the number to columnNumber
columnNumber = Application.WorksheetFunction.Match(columnName, Range(Cells(tableRow, tableColumn), Cells(tableRow, tableColumn + tableWidth)), 0)
'Apply the filter "1" to the found columnNumber
ActiveSheet.ListObjects(tableName).Range.AutoFilter field:=columnNumber, Criteria1:="1"
'Exit the sub otherwise the "error handling" will be provoked
Exit Sub
ErrorHandler:
MsgBox columnName & "Please Specify Required Channel"
End Sub
As i cant seem to figure out how to get my combo-box's to show only the visible cells after filtering the table i was wondering if there is a way i can create a a validation box to show the visible cells or copy the visible data into a seperate table underneath. I can then use the validation box/ secondary table as a focus point for the combo-box's on the user-form.
Thanks in advance
If I'm understanding your question correctly, you would like to have a data-validation drop-down list that updates as the table is filtered and only displays visible items for a given column.
You can do this by using the following formula in Data Validation (I'm assuming your table header row starts in A1 and it's col A you need to display):
=OFFSET($A$2,,,SUBTOTAL(103,TableName[column name]))
This formula expands from the starting cell (A2) by a specified height in number of rows. We are defining the height using SUBTOTAL with function number 103 - this means that the height is defined using COUNTA, but only on visible cells, so it will expand and collapse as the table is filtered.
Be aware: since the height is defined using a counta function, it will only count cells containing data, therefore if you have blanks in your table, the range will not be defined correctly. Also if you have any repeated data, these will be repeated in your drop-down box, this method will not condense them into a neat, unique list.
Hope this is helpful.
D
I'm stuck on this issue and cannot figure out what it is I am doing wrong. I'm in the process of writing a macro to loop through visible fields in a pivot table, find the items in those fields that are filtered, and then apply those filters to the source data table. The particular problem I'm having deals with a loop that is supposed to look in a field, find the visible pivot items, and then store those items as variables. I've been messing around with trying to terminate the loop if all pivot items are visible. Below is what I have so far:
Sub PivotTest2()
Dim pi As PivotItem
Dim count As Integer
Dim available As Integer
Dim row As Integer
available = ActiveSheet.PivotTables("Cities").PivotFields("City").PivotItems.count
row = 2 'This is your starting row for display
For Each pi In ActiveSheet.PivotTables("Cities").PivotFields("City").PivotItems
If pi.Visible Then
count = count + 1
End If
If count = available Then
MsgBox ("All Pivot Items Are Selected")
End If
If count <> available Then
row = row + 1
Range("'Sheet4'!G" & row) = pi.Name
End If
Next pi
End Sub
So whenever I have a filter on a city, or group of cities, the macro pastes them to a range in the spreadsheet. Eventually, I want to store them as variables, but for now I'm just pasting them for the purposes of working through the code. You can also see that when the number of visible items is equal to the total number of pivot items in that field, I'm returning a message box. Eventually, that message box will go away and be replaced by code that tells it to start looking through pivot items in the next visible field.
I realize that this might be unnecessary, as applying all visible items as filters to the source data field would result in all items being shown, which accomplishes the same thing. However, I'm more curious about what it is I'm doing wrong at this point. The code pastes all items to the range, regardless of whether there is a filter or not. However, the message box only returns when there is no filter applied, so it appears to be working correctly.
Any input/feedback would be appreciated. Thanks.
It seems that part of your checks should be outside your loop which determines the amount of visible PivotItems.
At first, I'd suggest to move the Next pi after the first If-End If block. Your count variable should then contain the number of visible items. If all items are visible, your message box should then appear. However, for the second part (copying visible items), you'd need to loop again.
To avoid the second loop, you may want to copy the pi.Name values to a temporary range, and copy this range to the final range only if there are filters applied.
Try this:
For Each pi In ActiveSheet.PivotTables("Cities").PivotFields("City").PivotItems
If pi.Visible Then
count = count + 1
Range("'Sheet4'!G" & row) = pi.Name
row = row + 1
End If
Next pi
If count = available Then
MsgBox ("All Pivot Items Are Selected")
End If
Your code doesn't check if the city is visible before pasting, which is why it always pastes every city name.
I am currently using DevExpress 10.2 within Visual Studio 2010. In a previous question I was trying to print the current user view of a DevExpress GridControl with the user's choice of expanded or collapsed master rows and/or group sections. I was told this was not possible at this time. I have now decided to use the following code:
gvPOinvoiceBanded.OptionsPrint.ExpandAllGroups = False
gvPOinvoiceBanded.OptionsPrint.ExpandAllDetails = False
when I want it to be completely collapsed while printing as by default these are set to true.
I was just wondering if there is someway to check either the total number of expanded master rows or the total number of collapsed master rows. I would also like to do the same thing for the groups as you can have the groups expanded while the master rows are not.
You can get the number of expanded group rows using a loop like this:
Dim ExpandedGroupCount As Integer = 0
Dim Handle As Integer = -1 'group rows have negative row handles
Do Until GridView1.GetRow(Handle) Is Nothing
If GridView1.GetRowExpanded(Handle) Then
ExpandedGroupCount += 1
End If
Handle -= 1
Loop
'Do whatever with expanded group count
MsgBox(String.Format("Number of Expanded Group Rows: {0}{2}Number of Group Rows: {1}",
ExpandedGroupCount, Math.Abs(Handle + 1), Environment.NewLine))
Similarly, you can do this to get the count of expanded master rows:
Handle = 0
Dim ExpandedMasterRowCount As Integer = 0
Do Until GridView1.GetRow(Handle) Is Nothing
If GridView1.IsMasterRow(Handle) Then
If GridView1.GetMasterRowExpanded(Handle) Then
ExpandedMasterRowCount += 1
End If
End If
Handle += 1
Loop
MsgBox(String.Format("Number of Expanded Master Rows: {0}", ExpandedMasterRowCount))
Of course, if you are only checking so that you can see if you need to set the collapse this probably isn't worth the effort. There is no direct property that provides the counts you are looking for.
You could also probably use the events that fire when rows are collapsed and expanded to track the count as it changes. You have to be careful with that though because the event only fires once when expand or collapse all happens. So if you go with that method be sure to check the rowHandle in the event arguments parameter for GridControl.InvalidRowHandle. That is the value used in the case of collapse or expand all.