Фильтрация нескольких сводных таблиц на основе выпадающего списка с использованием 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
Да, мои исходные данные имеют мой месяц как дату, отформатированную как ммм, гг, и мой выбор в раскрывающемся списке для месяца одинаков. Код отлично работает при поиске текстовой информации, но просто не будет искать дату   -  person Danners    schedule 23.08.2016
comment
Также опубликуйте код, который не работает.   -  person jeffreyweir    schedule 24.08.2016


Ответы (1)


Вот несколько предложений.

  1. Какая у вас версия Экселя? Вы можете просто обойти эту проблему при использовании Excel 2010 или более поздней версии, потому что вы можете просто настроить слайсер в поле даты, а затем подключить этот слайсер к любым сводным таблицам, которые вы хотите синхронизировать. В более поздних версиях вы можете сделать то же самое, используя специализированный слайсер под названием 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 (т. е. полей, перетаскиваемых на панель «Фильтры»), как показано на следующем снимке экрана:

Поле страницы

Поэтому, если вы хотите использовать следующий код, вам придется перетащить поля месяца в сводную таблицу как 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 раскрывающимся спискам проверки данных, а затем сослался на эти имена в коде. Вам нужно будет сделать то же самое в мастер-листе.

Если вы не хотите менять макет сводной таблицы, обходной путь — добавить временную шкалу в поле месяца и программно изменить ее с помощью раскрывающихся списков. Затем он обновит сводную таблицу. Вот как это выглядит:

Временная шкала

Обратите внимание, что поле «Месяц» не выглядит так, будто к нему применен фильтр, но это так... о чем свидетельствуют итоги, отображаемые в сводной таблице.

Вот измененный код для версии, управляемой временной шкалой:

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. Оказывается, это не только ужасно неэффективно, но также требует, чтобы вы временно изменили числовой формат поля «Месяц» с формата МММ-ГГ на формат ДД-ММ-ГГ или аналогичный, потому что в противном случае VBA может неправильно интерпретировать год как в день, а затем используйте текущий год в качестве года. Итак, если ваш PivotItem - OCT-15, тогда VBA интерпретирует это как 15 октября 2016 года (текущий год, когда я это набираю) вместо 1 октября 2015 года. Неприятно.

Поэтому я бы посоветовал избегать итераций и либо изменить формат сводной таблицы и использовать мой первый подход, либо добавить временную шкалу и использовать мой второй подход.

person jeffreyweir    schedule 23.08.2016
comment
Какую версию Excel вы используете? - person jeffreyweir; 24.08.2016
comment
Привет Джерри, спасибо за ваш ответ. Мой код, который не работает, точно такой же, как указано выше, но с заменой «Регион» на «Месяц», а D5 заменен на D3. При этом ничего не происходит. Я использую Excel 2016, но слайсеры, к сожалению, не подходят, поскольку конечный пользователь хочет, чтобы все работало с выбором диапазона дат с помощью двух раскрывающихся списков на листе 1 (другие обычные таблицы также являются частью панели инструментов, и я не создавал исходный файл). У меня такое чувство, что это проблема с датой, но что мне добавить в код, который вы предлагаете? - person Danners; 24.08.2016
comment
Я также пытался создать функцию включения множественного выбора, но теперь я снова уверен, как это сделать. - person Danners; 24.08.2016
comment
Можете скинуть ссылку на образец файла? Слишком сложно устранить неполадки иначе. Не стесняйтесь удалять что-либо конфиденциальное. - person jeffreyweir; 24.08.2016
comment
Что касается слайсеров, их цель состоит в том, чтобы соединить все поля даты во всех сводных точках вместе, так что, если один из них изменится, все они будут изменены, чтобы показать одно и то же без какого-либо 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
Просто чтобы внести ясность, я предлагаю вам соединить сводные данные со слайсерами, а затем где-нибудь спрятать слайсеры и заменить существующую проверку данных на сводную таблицу, маскирующую раскрывающийся список проверки данных, как в посте I. ссылка на выше. Вы получаете именно тот результат, который вам нужен, без кода 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? дл=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