Help Modifying Existing Forum Code that Filters Pivot Tables

Katterman

Board Regular
Joined
May 15, 2014
Messages
103
Office Version
  1. 365
Platform
  1. Windows
  2. Mobile
  3. Web
Hello Everyone

I'm looking for some assistance in Modifying some existing code to filter a pivot table.
I've searched all over the board (and Google) and found many variations of code to do this
but have yet to tweak it to a point that works for me.

I'm using some code provided by Jerry Sullivan found HERE and it works on my pivot table except
for one thing. I'm using an Array to hold a number of dates and i need the code to select only the
dates in the array to be visible. The code as is will select the first and last dates in the array but will also
select ALL dates in between. It does not "ignore" and dates that are midding from the array between the first and last dates.

This is what i have and would like to tweak to use only the vales found in my Array.

Code:
Sub Pivot_Outage_Dates()


'http://www.mrexcel.com/forum/excel-questions/606328-change-pivot-page-filter-based-upon-two-cell-values-dates.html#post3007354


    Dim dtFrom As Date, dtTo As Date
    Dim pt As PivotTable
    Dim ERow1 As Date
     
    With Sheets("STATS")
    ERow1 = Columns("O").Find("*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows, LookIn:=xlValues).Value
    End With
    
    With Sheets("NAT_Pivot")
        Set pt = .PivotTables("PivotTable6")
        dtFrom = Sheets("STATS").Range("O10")
        dtTo = ERow1
    End With
    
    Call Filter_PivotField_by_Date_Range( _
        pt.PivotFields("Date Created"), dtFrom, dtTo)
End Sub


Public Function Filter_PivotField_by_Date_Range(pvtField As PivotField, _
        dtFrom As Date, dtTo As Date)
        Dim bTemp As Boolean, i As Long
        Dim dtTemp As Date, sItem1 As String
    
    On Error Resume Next
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual


    With pvtField
        .Parent.ManualUpdate = True
        For i = 1 To .PivotItems.Count
            dtTemp = .PivotItems(i)
            bTemp = (dtTemp >= dtFrom) And _
                (dtTemp <= dtTo)
            If bTemp Then
                sItem1 = .PivotItems(i)
                Exit For
            End If
        Next i
'        If sItem1 = "" Then
'            MsgBox "No items are within the specified dates."
'            Exit Function
'        End If




        If .Orientation = xlPageField Then .EnableMultiplePageItems = True
        .PivotItems(sItem1).Visible = True
        For i = 1 To .PivotItems.Count
            dtTemp = .PivotItems(i)
            If .PivotItems(i).Visible <> _
                ((dtTemp >= dtFrom) And (dtTemp <= dtTo)) Then
                .PivotItems(i).Visible = Not .PivotItems(i).Visible
            End If
        Next i
    End With
    
    pvtField.Parent.ManualUpdate = False
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
End Function
This code:
Code:
    With Sheets("STATS")
    ERow1 = Columns("O").Find("*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows, LookIn:=xlValues).Value
    End With

Would need to be replaced with my Array Code:
Code:
    With Worksheets("STATS")
    Arr1 = .Range("O10", .Range("O" & Rows.Count).End(xlUp)).Value
    End With

And as far as the Array goes, it comes from a Dynamic range that populates with dates in a range of either
7 fields (Weekly) or 31 Fields (Monthly). It populates the array based on the Non Empty fields in the range.

Well, Hopefully that made sense and someone can assist.
Like mentioned before, I've looked around a lot and tried many pieces of code
before reaching out for help

Thank you all for reading and to those who reply.

Scott
 

Excel Facts

How to show all formulas in Excel?
Press Ctrl+` to show all formulas. Press it again to toggle back to numbers. The grave accent is often under the tilde on US keyboards.
Just bumping up this post as no replies yet.

Thanks in advance for anyone's help.

Scott
 
Upvote 0
Hi Scott, Could there be some items in the array Arr1 that are outside of the range of dates between the start date and end date? If so, are those items to be visible or hidden after filtering?

If all the dates in Arr1 are to be Visible, then the date start/end doesn't really affect the result.

What is the date format that is displayed in the PivotTable?
What is the date format that is displayed on the worksheet for the items that are read into Arr1?
 
Upvote 0
Hello Jerry, Thanks for the Reply

There would NOT be dates outside of the array. Anything Not In the Array should be Hidden.
On the Worksheet there are either 7 or 31 dates that if an adjacent cell is selected "yes"
that date will be copied into another columns of either 7 or 31 cells to build the array from.
There may be some "Non Empty" cells in the 7 or 31 cell columns below any dates that were entered
with that "Yes" but those Empty cells are not be included in the array.

Both Date Formats (Worksheet Data in Array and Pivot Table Data should be M/D/YYYY

Scott

Hi Scott, Could there be some items in the array Arr1 that are outside of the range of dates between the start date and end date? If so, are those items to be visible or hidden after filtering?

If all the dates in Arr1 are to be Visible, then the date start/end doesn't really affect the result.

What is the date format that is displayed in the PivotTable?
What is the date format that is displayed on the worksheet for the items that are read into Arr1?
 
Last edited:
Upvote 0
Scott, Here's a general purpose sub that you can use to filter a PivotField to show an array of items.

Code:
Private Sub FilterPivotField(ByVal pvf As PivotField, _
   ByVal vItems As Variant)

'--filters pivotfield to show only items in vItems list

'--approach is to compare the visibleitems property to vItems.
'    items in both lists: No change
'    items in visibleitems property only: hide
'    items in vItems only: unhide if pivotitem exists

 Dim bHasMatches As Boolean
 Dim dctCurrentlyVisible As Object
 Dim dctToShow As Object
 Dim lNdx As Long
 Dim sItem As String
 Dim pvi As PivotItem
 Dim vKey As Variant
 
 Set dctCurrentlyVisible = CreateObject("Scripting.Dictionary")
 Set dctToShow = CreateObject("Scripting.Dictionary")
 dctCurrentlyVisible.CompareMode = 1 'TextCompare
 dctToShow.CompareMode = 1
 
 '--validate vlist is array
 If Not IsArray(vItems) Then
   sItem = vItems
   ReDim vItems(1, 1)
   vItems(1, 1) = sItem
 End If
 
 '--do processes specific to orientation of pivotfield
 Select Case pvf.Orientation
   Case xlPageField
      '--Optional: if one item only- use CurrentPage
      If UBound(vItems) = 1 Then
         pvf.ClearAllFilters
         On Error Resume Next
         pvf.CurrentPage = vItems(1, 1)
         If Err.Number <> 0 Then _
            MsgBox "No matching items found - Report Filter cleared."
         On Error GoTo 0
         GoTo ExitProc
      End If
      
      If pvf.EnableMultiplePageItems = False Then
         pvf.EnableMultiplePageItems = True
      End If
 
      '--put all currently visible items into dictionary
      For Each pvi In pvf.PivotItems
         If pvi.RecordCount Then
            If pvi.Visible = True Then _
               sItem = dctCurrentlyVisible.Item(pvi.Caption)
         End If
      Next pvi
 
   Case xlRowField, xlColumnField
       '--put all currently visible items into dictionary
      For Each pvi In pvf.VisibleItems
         sItem = dctCurrentlyVisible.Item(pvi.Caption)
      Next pvi
   Case Else
      MsgBox "Incorrect PivotField Orientation. Exiting macro."
      GoTo ExitProc
 End Select
 
 '--step through list of items to be visible
 pvf.Parent.ManualUpdate = True
 For lNdx = LBound(vItems) To UBound(vItems)
   sItem = vItems(lNdx, 1)
   '--if already visible, mark item
   If dctCurrentlyVisible.Exists(sItem) Then
      dctCurrentlyVisible(sItem) = "No Change"
      bHasMatches = True
   Else
      '--show if exists, handle if doesn't exist
      On Error Resume Next
      pvf.PivotItems(sItem).Visible = True
      If Err.Number = 0 Then bHasMatches = True
      On Error GoTo 0
   End If
 Next lNdx
 
 If bHasMatches Then
   '--at least one item will be visible after filtering
   With dctCurrentlyVisible
      For Each vKey In .Keys
         If .Item(vKey) <> "No Change" Then
            '--hide items visible at start but not in vItems
            pvf.PivotItems(vKey).Visible = False
         End If
      Next vKey
   End With
 Else
   MsgBox "No matching items found"
 End If
 pvf.Parent.ManualUpdate = False

ExitProc:
End Sub

Here's an example calling procedure based on your scenario....
Code:
Sub Pivot_Outage_Dates()
 Dim pvt As PivotTable
 Dim Arr1 As Variant
     
 With Sheets("STATS")
   Arr1 = .Range("O10", .Range("O" & Rows.Count).End(xlUp)).Value
  '---or reference your DNR by name so it can be moved without modifying VBA
   Arr1 = .Range("MyDNR_Name").Value

 End With
    
 Set pvt = Sheets("NAT_Pivot").PivotTables("PivotTable6")
  
 Call FilterPivotField(pvf:=pvt.PivotFields("Date Created"), vItems:=Arr1)

End Sub
 
Last edited:
Upvote 0
Hello Jerry

You are an Excel VBA God ..LOL:laugh:
This works PERFECTLY and exactly how i needed.
Is there a way to also uncheck (Hide) the " (Blank) " selection?

List.jpg


Aside from that, I Thank You Very Much for all your efforts in writing that code
to assist me and Appreciate all you do for those of us in this Forum.

On a side note, can you recommend and books / resources that could help myself and others
who love working in excel, gain the higher levels of VBA coding knowledge that you
and many others on this forum have? I Know practice makes perfect so i continue doing that
as well.

Thanks
Scott
 
Upvote 0
Scott, I'm glad that worked for you and I appreciate your kind feedback. :)

In my testing, the code handled blank items the way I think you are wanting. If a blank PivotItem is checked with "(blank)" visible (as in your image), a key "(blank)" is added to the dictionary: dctCurrentlyVisible. If there is not an item named "(blank)" in arr1, then "(blank)" will be unchecked during this step of the process:

Code:
   With dctCurrentlyVisible
      For Each vKey In .Keys
         If .Item(vKey) <> "No Change" Then
            '--hide items visible at start but not in vItems
            pvf.PivotItems(vKey).Visible = False
         End If
      Next vKey
   End With

Are you getting different results or do you have a different scenario that isn't working as expected?

On a side note, can you recommend and books / resources that could help myself and others
who love working in excel, gain the higher levels of VBA coding knowledge that you
and many others on this forum have? I Know practice makes perfect so i continue doing that
as well.

What methods have worked best for you in the past for learning Excel or other technical subjects? (books, classes, web articles, trial and error experimentation)?
 
Upvote 0
Hello Jerry

My Array does Not have any "(Blanks)" in it. Just The required Dates to keep Visible.
Therefore, in theory, the "(Blanks)" in the Pivot Table should also be Un-Selected (Hidden).
I have rechecked my Array and No Blanks.

Scott, I'm glad that worked for you and I appreciate your kind feedback. :)

In my testing, the code handled blank items the way I think you are wanting. If a blank PivotItem is checked with "(blank)" visible (as in your image), a key "(blank)" is added to the dictionary: dctCurrentlyVisible. If there is not an item named "(blank)" in arr1, then "(blank)" will be unchecked during this step of the process:
Are you getting different results or do you have a different scenario that isn't working as expected?


What methods have worked best for you in the past for learning Excel or other technical subjects? (books, classes, web articles, trial and error experimentation)?

The Methods I like are Books, Trial and Error and then Web Articles / Forums (Such as this one that contains MANY Talented people in here like yourself that i Aspire to be as skilled as in Excel.

Thanks Again for your valuable time and efforts.

Scott
 
Upvote 0
Scott, Try doing some testing in the Immediate Window of the VB Editor to find the point at which the blanks aren't being handled correctly.

First use the manual filter checkboxes to display only one date and the (blank) item.

Then add some Debug.Print statements to the code so you can monitor if the (blank) is added to the dictionary, then later set to Visible=False.

For example, if your dates are in the RowField area, modify to this...
Code:
       '--put all currently visible items into dictionary
      For Each pvi In pvf.VisibleItems
         sItem = dctCurrentlyVisible.Item(pvi.Caption)
[COLOR="#0000CD"][B]         Debug.Print "Added to dictionary: " & _
            pvi.Caption & "> characters: " & Len(pvi.Caption)[/B][/COLOR]
      Next pvi

The purpose of the character count is to see if (blank) is being read as "" or " " instead of "(blank)".

Near the end of the code...
Code:
     For Each vKey In .Keys
[COLOR="#0000CD"][B]         Debug.Print vKey & ": " & .Item(vKey)[/B][/COLOR]
         If .Item(vKey) <> "No Change" Then
            '--hide items visible at start but not in vItems
            pvf.PivotItems(vKey).Visible = False
         End If
      Next vKey

I tested this with 1/2/2016 and (blank) initially checked, and 1/2/2016 in the range to be read into Arr1.

The resulting output was....
Added to dictionary: 1/2/2016> characters: 8
Added to dictionary: (blank)> characters: 7
1/2/2016: No Change
(blank):

In my test, (blank) was hidden after running the code which is what you want.
 
Upvote 0
Hello Jerry

Ok, Here are some issues / Results.

To first Clarify My Pivot Structure, this is what is selected for fields and where and the
default View before anything is filtered when your code is run.
Items.jpg
Table.jpg



After inserting the debug code ( First time debugging)
I tested this with 1/4/2016 and (blank) initially checked,
Table - Sel.jpg

and 1/4/2016 in the range to be read into Arr1.

The resulting output was....
NOTHING in Immediate window and Pivot Table looked like this:
Table - Sel-ARR1-NoIM.jpg

I then fixed the Pivot back to 1/4/2016 and (blank) initially checked
and then
selected Nothing in the Arr1

The resulting Immediate window output was....
Added to dictionary: 1/4/2016> characters: 8Added to dictionary: 1/5/2016> characters: 8
Added to dictionary: 1/6/2016> characters: 8
Added to dictionary: 1/7/2016> characters: 8
Added to dictionary: 1/8/2016> characters: 8
Added to dictionary: 1/9/2016> characters: 8
Added to dictionary: 1/10/2016> characters: 9

and the pivot maintained the original Manual selections
(1/4/2016 and (blank) initially checked)


Sorry this has become a bit of a stumper and more work than either of us planned.

Other than this "Blanks" issue, the code is perfect and ran the way i wanted from Day one of getting it.

Scott



Scott, Try doing some testing in the Immediate Window of the VB Editor to find the point at which the blanks aren't being handled correctly.

First use the manual filter checkboxes to display only one date and the (blank) item.

Then add some Debug.Print statements to the code so you can monitor if the (blank) is added to the dictionary, then later set to Visible=False.

For example, if your dates are in the RowField area, modify to this...
Code:
       '--put all currently visible items into dictionary
      For Each pvi In pvf.VisibleItems
         sItem = dctCurrentlyVisible.Item(pvi.Caption)
[COLOR=#0000CD][B]         Debug.Print "Added to dictionary: " & _
            pvi.Caption & "> characters: " & Len(pvi.Caption)[/B][/COLOR]
      Next pvi

The purpose of the character count is to see if (blank) is being read as "" or " " instead of "(blank)".

Near the end of the code...
Code:
     For Each vKey In .Keys
[COLOR=#0000CD][B]         Debug.Print vKey & ": " & .Item(vKey)[/B][/COLOR]
         If .Item(vKey) <> "No Change" Then
            '--hide items visible at start but not in vItems
            pvf.PivotItems(vKey).Visible = False
         End If
      Next vKey

I tested this with 1/2/2016 and (blank) initially checked, and 1/2/2016 in the range to be read into Arr1.

The resulting output was....
Added to dictionary: 1/2/2016> characters: 8
Added to dictionary: (blank)> characters: 7
1/2/2016: No Change
(blank):

In my test, (blank) was hidden after running the code which is what you want.
 
Upvote 0

Forum statistics

Threads
1,223,903
Messages
6,175,284
Members
452,630
Latest member
OdubiYouth

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top