Здравствуйте. Вопрос требует вникнуть в задачу, поэтому буду благодарен за его изучение и уделенное время.
Нахожусь в поиске нормального решения для своей задачи. Данный пример приведён для простоты восприятия поставленной задачи
Есть умная таблица (List Object) (1 Фото.). В ней имеются 4 столбца. (Продукт | Цена | Размер коробки | Страна производства)
Конечная цель составить список на подобии тому, что приведено на фото 2. Т.е. нужно произвести фильтрацию по столбцам с последующим занесением информации в Word.
В данный момент времени вопроса о том, как занести это в Word нет. Вопрос в том, как красиво без решения "в лоб" сделать фильтрацию по 3 столбцам.
Т.е. необходимо сделать фильтрацию:
1) По столбцу Страна производства
Затем
2) Размер коробки
Затем
3) Цена
Взять информацию о продукте или продуктах. Затем по колонке цена необходимо сделать другой фильтр (если он там есть). Например в нашем примере другой фильтр имеется: Сначала идёт страна Индия, маленькая коробка, и имеется два вида цены (50 и 100). После того, как фильтры по цене закончатся необходимо поменять фильтр по полю "Размер коробки" и повторить все операции. Думаю логика задачи понятна.
Теперь о коде
С наскоку "родилось" следующее:
Код |
---|
Sub Макрос1()
Dim country As New Collection
Dim size As New Collection
Dim price As New Collection
Dim table As ListObject
Set table = Workbooks("пробник.xlsm").Worksheets("Лист2").ListObjects("Таблица2")
'Собираем все значения в столбце "Страна производства"
Set country = getValuesInColumn(table, "Страна производства")
'Собираем все значения в столбце "Размер коробки"
Set size = getValuesInColumn(table, "Размер коробки")
'Собираем все значения в столбце "Цена"
Set price = getValuesInColumn(table, "Цена")
Dim counterForCountry As Long
Dim counterForSize As Long
Dim counterForPrice As Long
'Начинаем фильтровать колонку "Страна производства" по одному из доступных значений:
For counterForCountry = 1 To country.Count
'Если какой-то фильтр в таблице имелся - сбросим его
If table.AutoFilter.FilterMode Then
table.AutoFilter.ShowAllData
End If
table.DataBodyRange.AutoFilter 4, country(counterForCountry) '- теперь наша таблица отфильтрована по столбцу "Страна производства"
'Начинаем фильтровать колонку "Размер коробки" по одному из доступных значений:
For counterForSize = 1 To size.Count
'Сбрасываем фильтр по данной колонке если он там был
table.DataBodyRange.AutoFilter 3
'Фильтруем по доступному полю из коллекции
table.DataBodyRange.AutoFilter 3, size(counterForSize)
'Начинаем фильтровать колонку "Цена" по одному из доступных значений:
For counterForPrice = 1 To price.Count
'Сбрасываем фильтр по данной колонке если он там был
table.DataBodyRange.AutoFilter 2
'Фильтруем по доступному полю из коллекции
table.DataBodyRange.AutoFilter 2, price(counterForPrice)
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'Прямо здесь у нас есть информация о продукте с которой мы можем что-либо сделать
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Next counterForPrice
'Сбрасываем фильтр по колонке "Цена"
table.DataBodyRange.AutoFilter 2
Next counterForSize
'Сбрасываем фильтр по колонке "Размер коробки"
table.DataBodyRange.AutoFilter 3
Next counterForCountry
End Sub
'Функция, которая возвращает коллекцию значений без повторений в переданной таблице переданной колонке.
Function getValuesInColumn(table As ListObject, nameOfColumn As String) As Collection
Set getValuesInColumn = New Collection
On Error Resume Next
Dim counter As Long
Dim value As String
For counter = 1 To table.ListRows.Count
value = Intersect(table.ListRows(counter).Range, table.ListColumns(nameOfColumn).DataBodyRange).value
getValuesInColumn.Add value, value
Next counter
End Function
|
Это как раз-таки то самое решение в лоб - в итоге 3 цикла, все циклы находятся в друг друге и образовывается своеобразная матрёшка. А что если таких столбцов будет не 3, а 4 или 5? Очень легко где-то ошибиться.
И да, могут быть такие случаи, когда программа фильтрует столбец по значению, которого нет в фильтре, но который есть в коллекции. Т.е. например страна Индия, коробка маленькая, а цена 75. Такой цены нету и после фильтра в таблице становится 0 строк. Этот случай не стоит рассматривать.
Вопрос в том, как сделать код менее громоздким, более понятым.
Я новичок в VBA и могу не знать каких-то специальных "трюков" для таких задач. Буду рад увидеть любые решения и любой полёт фантазии!