Филтриране на множество обобщени таблици въз основа на падащи селекции с помощта на VBA

Надявам се някой да може да помогне. Имам табло за управление, създадено от някой друг, където има множество таблици в листове, всички работещи от падащи селекции на дати (От - До) на лист 1. Бях помолен да добавя към това и създадох осеви таблици, които са най-подходящи за работата. Проблемът, който имам, е, че трябва да филтрират въз основа на падащите дати на лист 1.

Надявам се, че това е възможно чрез VBA.

Успях да накарам обобщените си отчети да се филтрират въз основа на друго падащо меню, което е текстово. Но не мога да накарам същия код (когато е променен, за да се фокусира върху опцията „месец“ и свързаната падаща клетка), за да работи за избор на дата, а също така не мога да разбера как да разреша множество селекции, така че да мога да избера диапазона от дати.

Кодът, който използвам, е както следва:

Private Sub Worksheet_Change(ByVal Target As Range)

Dim ws As Worksheet
Dim pt As PivotTable
Dim pi As PivotItem
Dim strField As String

strField = "Region"

On Error Resume Next
Application.EnableEvents = False
Application.ScreenUpdating = False

If Target.Address = Range("D2").Address Then

    For Each ws In ThisWorkbook.Worksheets
        For Each pt In ws.PivotTables
            With pt.PageFields(strField)
                For Each pi In .PivotItems
                    If pi.Value = Target.Value Then
                        .CurrentPage = Target.Value
                        Exit For
                    Else
                        .CurrentPage = "(All)"
                    End If
                Next pi
            End With
        Next pt
    Next ws

End If

Application.EnableEvents = True
Application.ScreenUpdating = True

End Sub

Всяка помощ, която някой може да предостави, ще бъде много оценена. Аз съм сравнително нов в VBA и се опитвам да коригирам кода, който намирам онлайн, но се боря.

Благодаря

Преработено: Опитах и ​​кода по-долу, който намерих другаде, който се използваше за избиране на периоди от време

Sub FilterPivotDates()
'
Dim dStart As Date
Dim dEnd As Date
Dim pt As PivotTable
Dim pf As PivotField
Dim pi As PivotItem

Application.ScreenUpdating = False
On Error Resume Next

dStart = Sheets("Pivots").Range("F2").Value
dEnd = Sheets("Pivots").Range("f3").Value

Set pt = ActiveSheet.PivotTable1
Set pf = pt.PivotFields("Month")

pt.ManualUpdate = True

pf.EnableMultiplePageItems = True

For Each pi In pf.PivotItems
  pi.Visible = True
Next pi

For Each pi In pf.PivotItems
 If pi.Value < dStart Or pi.Value > dEnd Then
pi.Visible = False
End If
Next pi

Application.ScreenUpdating = False
pt.ManualUpdate = False

Set pf = Nothing
Set pt = Nothing

End Sub

В примера открих, че това се управлява от бутон, но току-що го пробвах в листа. Но това също не работи за мен.


person Danners    schedule 23.08.2016    source източник
comment
всъщност вашият месец взет ли е от дата във формат dd/mm/yyyy или нещо подобно?   -  person Shai Rado    schedule 23.08.2016
comment
Да, моите изходни данни имат моя месец като дата, форматирана като mmm yy, и моите падащи селекции за месец са същите. Кодът работи абсолютно добре, когато търсите текстова информация, но просто няма да търси датата   -  person Danners    schedule 23.08.2016
comment
Моля, публикувайте и кода, който не работи.   -  person jeffreyweir    schedule 24.08.2016


Отговори (1)


Ето няколко предложения.

  1. Каква версия на Excel имате? Може просто да заобиколите проблема, ако използвате Excel 2010 или по-нова версия, тъй като можете просто да настроите Slicer в полето за дата и след това да свържете този Slicer към всяка обобщена таблица, която искате да синхронизирате. В по-късните версии можете да направите същото, като използвате специализиран слайсер, наречен Timeline. Написах свързана публикация по този въпрос преди време на следната връзка, която може да представлява интерес: http://dailydoseofexcel.com/archives/2014/08/16/sync-pivots-from-dropdown/

  2. #P3#
    #P4#

Това може да е вашият проблем. Наскоро изпитах някои подобни проблеми и го заобиколих, като преобразувах датата, по която исках да филтрирам Pivot, в DateSerial (за да заобиколя „несъвместимостите“ на датите в САЩ срещу не-САЩ) и след това прехвърлих този DateSerial като Long, със следното ред от код:

CLng(DateSerial(Година(vItem), Месец(vItem), Ден(vItem)))

Вашият код може да се нуждае от нещо подобно. Ако промените въпроса си, за да включите точния код, който не работи, тогава ще го разгледам.

  1. Вижте този скорошен SO въпрос, на който отговорих: Може лесно да бъде променен, за да прави това, което искате. Филтриране на обобщена таблица с vba

---Редактиране---

Най-ефективният начин за програмно филтриране на пивоти за период от време е да използвате вградената функционалност Дата между, т.е. това нещо:

Дата между

Единственият проблем е, че тази функционалност не е достъпна за PageFields (т.е. полета, преместени в панела с филтри), както е показано на следната екранна снимка:

PageField

Така че, ако искате да използвате следния код, ще трябва да плъзнете вашите полета за месец в обобщената таблица като RowField, така:

RowField

Ако приемем, че това няма да създаде проблеми, тогава можете да използвате следния код:

Private Sub Worksheet_Change(ByVal Target As Range)

Dim pt As PivotTable
Dim vItem As Variant
Dim rFrom As Range
Dim rTo As Range

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

Set rFrom = Range("dvFrom")
Set rTo = Range("dvTo")

If Not Intersect(Target, rFrom) Is Nothing Or Not Intersect(Target, rTo) Is Nothing Then
    If rFrom < rTo Then
        For Each vItem In Array("PivotTable1", "PivotTable2") 'Change PivotTable names as appropriate
            Set pt = Sheet1.PivotTables(vItem) 'Change Sheet as appropriate
            With pt.PivotFields("Month")
                .ClearAllFilters
                .PivotFilters.Add2 _
                    Type:=xlDateBetween, _
                    Value1:=CLng(DateSerial(Year(rFrom), Month(rFrom), Day(rFrom))), _
                    Value2:=CLng(DateSerial(Year(rTo), Month(rTo), Day(rTo)))
                    'I use "CLng(DateSerial" because otherwise VBA may get confused
                    ' if the user's Excel i set to a non US dateformat.
            End With
        Next vItem
    End If
End If

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

End Sub

Обърнете внимание, че присвоих имената dvFrom и dvTo на вашите падащи менюта за валидиране на данни и след това посочих тези имена в кода. Ще трябва да направите същото във вашия основен лист.

Ако не искате да промените оформлението на обобщената си таблица, тогава заобиколно решение е да добавите TimeLine в полето за месеца и да го промените програмно чрез падащите менюта. След това ще актуализира обобщената таблица. Ето как изглежда това:

Времева линия

Обърнете внимание, че полето Месец не изглежда като към него е приложен филтър, но го прави... както се вижда от общите суми, които се показват в обобщената таблица.

Ето модифицирания код за управляваната от времевата линия версия:

Private Sub Worksheet_Change(ByVal Target As Range)

Dim vItem As Variant
Dim rFrom As Range
Dim rTo As Range
Dim lFrom As Long
Dim lTo As Long
Dim dte As Date

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

Set rFrom = Range("dvFrom")
Set rTo = Range("dvTo")

If Not Intersect(Target, rFrom) Is Nothing Or Not Intersect(Target, rTo) Is Nothing Then
    lFrom = CLng(DateSerial(Year(rFrom), Month(rFrom), Day(rFrom)))
    lTo = CLng(DateSerial(Year(rTo), Month(rTo), Day(rTo)))
    If lFrom < lTo Then
        For Each vItem In Array("NativeTimeline_Month", "NativeTimeline_Month1") 'Adjust timeline names as neccessary
            ActiveWorkbook.SlicerCaches(vItem).TimelineState. _
                SetFilterDateRange lFrom, lTo
        Next vItem
    End If
End If


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


End Sub

И това ни оставя с вашия оригинален подход - итерация през PivotItems. Оказва се, че това не е просто ужасно неефективно, но също така изисква временно да промените числовия си формат на полето Месец от формат MMM-YY на формат DD-MM-YY или подобен, защото в противен случай VBA може да тълкува погрешно годината като на ден и след това използвайте текущата година като година. Така че, ако вашият PivotItem е OCT-15, тогава VBA интерпретира това като 15 октомври 2016 г. (текущата година, докато пиша това) вместо 1 октомври 2015 г. Гадно.

Така че бих посъветвал да избягвате итерациите и или да промените формата на обобщената си таблица и да използвате моя първи подход, или да добавите TimeLine и да използвате моя втори подход.

person jeffreyweir    schedule 23.08.2016
comment
Каква версия на Excel използвате? - person jeffreyweir; 24.08.2016
comment
Здравей Джери, благодаря ти за отговора. Моят код, който не работи, е точно както по-горе, но с регион, заменен с месец и D5, заменен с D3 - нищо не се случва, когато използвате това. Използвам excel 2016, но Slicers за съжаление не са опция, тъй като крайният потребител иска всичко да работи от избор на диапазон от дати, като се използват две падащи полета на лист 1 (други нормални таблици също са част от таблото за управление и аз не съм създал оригинален файл). Имам чувството, че това е проблем с датата, но къде да добавя в кода, който предлагате? - person Danners; 24.08.2016
comment
Също така се опитах да вградя функцията за активиране на множествен избор, но отново вече съм сигурен как да направя това - person Danners; 24.08.2016
comment
Можете ли да публикувате връзка към примерен файл? Твърде трудно за отстраняване на неизправности по друг начин. Чувствайте се свободни да премахнете всичко поверително. - person jeffreyweir; 24.08.2016
comment
По отношение на Slicers, целта им е да свържат всички полета за дата във всички Pivots заедно, така че ако един от тях се промени, всички те се променят, за да показват същото, без каквато и да е VBA. И според тази публикация, към която направих връзка в точка 1 по-горе, можете след това да „фалшифицирате“ падащо меню, като направите копие на обобщената таблица и премахнете всички полета от нея, с изключение на това, за което искате падащото меню. След това преместете това поле в панела Филтри. Изглежда точно като падащо меню, с една фина разлика: променете го и всички други обобщени таблици, свързани със слайсер, също се променят. просто. - person jeffreyweir; 24.08.2016
comment
Разбира се, но аз съм съвсем нов в този форум - можете ли да ме посъветвате как най-добре да направя връзка към файла? - person Danners; 24.08.2016
comment
Напълно съм съгласен, че слайсерите са оптималното решение - все пак по-голямата част от информацията в таблото за управление е настроена като нормални Excel таблици и графики, работещи от валидиране на данни - бях помолен да добавя към него и добавих опорни точки, тъй като те са най-добрите формат по мое мнение, но единственият начин за свързване на опорните точки да работят от същия период от време, който виждам, е чрез VBA - person Danners; 24.08.2016
comment
Използвайте услуга за споделяне на файлове като Dropbox или Google Docs или OneDrive, получете връзка за „споделяне“ от тази услуга и я публикувайте тук. - person jeffreyweir; 24.08.2016
comment
Само за да бъде ясно, предлагам да свържете оси със слайсери и след това да скриете слайсерите някъде и да замените съществуващото валидиране на данни с обобщена таблица, маскирирана като падащо меню за валидиране на данни, както е в публикацията, която аз връзка към по-горе. Получавате точния резултат, който търсите, с нулев VBA код. Можете ли да погледнете тази публикация и да потвърдите тук, че а) сте я разгледали и б) сте я отхвърлили поради причина x, ако по някакъв начин не е подходяща за целта. - person jeffreyweir; 24.08.2016
comment
Можете ли също да изясните какво имате предвид по-горе, когато казвате, че също се опитах да вградя функцията за активиране на множествен избор? Не следвам намерението ти. Искате ли потребителят да може да избира повече от една дата от DV? - person jeffreyweir; 24.08.2016
comment
За последния ви въпрос - това, което се стремя да направя, е да използвам две падащи менюта на лист 1, т.е. дата от и дата до в клетки T2 & V2, за да филтрирам всички мои обобщени таблици въз основа на месеца. Така че, например, ако отида на моите осеви таблици, след като избера 16 юни - 16 август на първа страница, те щяха да се филтрират към същата селекция. Така че потребителят би могъл да избере своите от и до дата на лист 1 по същия начин, по който го правят в момента, и това ще избере диапазона за цялото табло. Току що разглеждам споделянето на файлове и връзката към вас - person Danners; 24.08.2016
comment
Що се отнася до връзката за слайсери, разгледах това сега, но за съжаление няма да работи за моето табло за управление, тъй като това би обвързало опорните точки да работят само за едни и същи дати - докато имам нужда от нещо, което свързва не само опорните таблици, но и стандартните таблици в Excel. Текущите кутии за валидиране на данни работят със стандартни таблици със скрити формули (отново не създадох оригиналното табло за управление - просто добавих към него). Така че се надявах новите центрове, които добавих, да могат да се свържат със същите тези падащи менюта. - person Danners; 24.08.2016
comment
Връзка към файл: dropbox.com/s/4xzna22wv8bjlg6/Sample.xlsm? dl=0 - person Danners; 24.08.2016
comment
Редактирах горната публикация, за да покажа друг код, който опитах и ​​който не работи, който беше фокусиран върху действителния период от време на нещата - person Danners; 24.08.2016
comment
Готино. Имам вашия примерен файл и просто пиша два различни подхода. Имайте нещо за вас скоро. - person jeffreyweir; 25.08.2016
comment
Извинявам се за закъснението да се свържа с теб, Джефри, известно време не успях да се свържа онлайн, за да пробвам това. Това работи перфектно - много ви благодаря за помощта, много я оценявам. - person Danners; 05.09.2016
comment
Страхотен! Радвам се, че помогнах. - person jeffreyweir; 06.09.2016