Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
669 views
in Technique[技术] by (71.8m points)

excel - Filtering pivot table with vba

I have a chart that picks the info from a pivot table that I have with daily data. I am trying to create activeX buttons so it can filter the data which is as ROW LABEL, to see how my data behaved in the last week and in the last month

So, what I have until now and it is not working is:

Private Sub weekbtn1_Click() Dim i As Integer

If weekbtn1 = True Then
i = 0
Do Until Datavalue(date) - i = 42005
With ActiveSheet.PivotTables("Pivotcompsprice").PivotFields("Date")
    .PivotItems DateValue(Date) - i.Visible = False
    i = i + 1
End With    
Loop

i = 0
Do Until i = 7
With ActiveSheet.PivotTables("Pivotcompsprice").PivotFields("Date")
    .PivotItems Datevalue(date) - i.Visible = True
End With
Loop
Else
End If

End Sub

I put this 42005 because it is the last date that I have the data which is 1/1/2015...I was thinking that it was possible to filter all the data as "false" and then Making True what I want, but it doesn't work!

Can someone help me?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's not possible to hide all items in a PivotField. You always have to leave at least one visible.

It will be much faster and easier if you use VBA to leverage the inbuilt Date Filters functionality i.e. this: DateFilter

Here's a sample file where I do just that: https://1drv.ms/x/s!Ah_zTnaUo4DzjhezQ3OTq9tq1APC

Note that this functionality is only available on RowFields or ColumnFields. So my code below won't work on PageFields.

Here's a generic routine that lets you choose what interval type and interval period you want to filter the pivot field on, as well as optionally select the date you want to count forward/back from.

Sub Pivots_FilterPeriod(sInterval As String, _
                        lNumber As Long, _
                        Optional vRelativeTo As Variant, _
                        Optional pf As PivotField)

    'Programmer:        Jeff Weir
    'Contact:           weir.jeff@gmail.com
    'Description:       Lets you programatically filter a Pivot RowField or ColumnField by specifying
    '                   an interval type (e.g. days, weeks, months, quarters, years)
    '                   as well as an interval count (e.g. 7, -7)
    '                   If the optional vRelativeTo field is left blank, it counts back/foward from
    '                   the youngest/oldest item depending on whether lNumber is positive/negative
    '                   It leverages off the inbuilt DateFilters functionality, and as such does not
    '                   work on RowFields.


    Dim dteDateAdd As Date
    Dim dteFrom As Date
    Dim dteTo As Date

    On Error GoTo errhandler

    If pf Is Nothing Then
        On Error Resume Next
        Set pf = ActiveCell.PivotField
        On Error GoTo errhandler
        If pf Is Nothing Then GoTo errhandler
    End If

    With pf
        If .DataType = xlDate _
            And .Orientation <> xlPageField _
            And .Orientation <> xlDataField Then

            If IsMissing(vRelativeTo) Or vRelativeTo = "" Then
                .AutoSort xlAscending, "Date"
                If lNumber > 0 Then
                    vRelativeTo = .PivotItems(1)
                Else
                    vRelativeTo = .PivotItems(.PivotItems.Count)
                End If
            End If

            Select Case UCase(sInterval)
                Case "D", "DD", "DDD", "DDDD", "DAY", "DAYS": sInterval = "d"
                Case "W", "WW", "WWW", "WWWW", "WEEK", "WEEKS": sInterval = "ww"
                Case "M", "MM", "MMM", "MMMM", "MONTH", "MONTHS": sInterval = "m"
                Case "Q", "QQ", "QQQ", "QQQQ", "QUARTER", "QUARTERS": sInterval = "q"
                Case "Y", "YY", "YYY", "YYYY", "YEAR", "YEARS": sInterval = "yyyy"
            End Select

            dteDateAdd = DateAdd(sInterval, lNumber, vRelativeTo)
            If lNumber > 0 Then
                dteDateAdd = dteDateAdd - 1
            Else
                dteDateAdd = dteDateAdd + 1
            End If

            If dteDateAdd < vRelativeTo Then
                dteFrom = dteDateAdd
                dteTo = vRelativeTo
            Else
                dteFrom = vRelativeTo
                dteTo = dteDateAdd
            End If

            With Application
                .ScreenUpdating = False
                .EnableEvents = False
                .Calculation = xlCalculationManual
            End With

            .ClearAllFilters
            .PivotFilters.Add2 _
                Type:=xlDateBetween, _
                Value1:=CStr(dteFrom), _
                Value2:=CStr(dteTo)
        End If
    End With

errhandler:
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = xlCalculationAutomatic
    End With

End Sub

Here's some screenshots demonstrating how it looks in practice, using different parameters.

This shows how to filter on the last 5 days from the most recent data:

Last 5 days from most recent data

And by changing the sign, it works out that we must want the first 5 days from the oldest data on record:

First 5 days from oldest records

If you specify an actual date in that RelativeTo field, it will count forward/back from there depending on whether the Number parameter is positive/negative. Here's the next 5 days from today's date as I write this:

Next 5 days from today

...and here's the last 5 days:

enter image description here

It will let you specify whether you want days, weeks, quarters, months, or years. For instance, here's the last 2 weeks counting back from the most recent record:

enter image description here

I'm using a Worksheet_Change event here to trigger it, but you can hook it up to a button if you like, and feed it the parameters you want.

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim bContinue As Boolean
    If Not Intersect(Target, Range("Interval")) Is Nothing Then bContinue = True
    If Not Intersect(Target, Range("Number")) Is Nothing Then bContinue = True
    If Not Intersect(Target, Range("RelativeTo")) Is Nothing Then bContinue = True
    If bContinue Then Pivots_FilterPeriod [Interval], [Number], [RelativeTo], Sheet1.PivotTables(1).PivotFields("Date")

End Sub

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...