Autofilter в Excell
Как прочитать средствами VB список (для дальнейшего использования), который Excell формирует при создании автофильтра, и который всплывает при нажатии на стрелочку в верхней ячейке? То есть там получается список уникальных значений столбца... Так вот можно с этим списком как-нибудь работать? Заранее спасибо!!!
Очень интересный вопрос. Приношу за него благодарность! :!!!:
Первым делом хочу сказать, что если разных значений много, то они отображаются не все, а только часть. Ну да ладно.
Прямого и простого доступа к такому списку я не знаю. Как его получить?
Вижу такие способы:
1. Самому пробежаться по полю и сформировать такой список. (Не так сложно, как кажется!)
2. Создать на новом листе некую сводную таблицу, считать из нее список, лист удалить. (Могу помочь с кодом)
Что скажешь?
А со вторым способом - буду признателен помощи с кодом. Может быть, действительно будет быстрее. Только есть такая проблема - я никогда не сталкивался со сводными таблицами в екселе. Только в аксесе. Поэтому как-то не получается даже вручную создать сводную таблицу. Буду признателен за помощь.
Первый способ хорош. А если записей порядка 10000? Сколько же он будет это выбирать? Я предполагаю алгоритм с методом find и findnext. По моим подсчетам, такой список он будет создавать минут 10.
А со вторым способом - буду признателен помощи с кодом. Может быть, действительно будет быстрее. Только есть такая проблема - я никогда не сталкивался со сводными таблицами в екселе. Только в аксесе. Поэтому как-то не получается даже вручную создать сводную таблицу. Буду признателен за помощь.
Ну уж нет... 10 минут будут обрабатываться 10000 записей разве что на 486-м... Я вот сейчас напишу пробный алгоритмчик. У меня, конечно, довольно хороший комп (1400мгц), но все равно посмотрим...
Sub postavshiki()
i = 1
Worksheets("Лист1").Activate
Columns("D:D").Select
For Each c In Worksheets("Лист1").Range ("D7:d8135")
Debug.Print c.Address
Set f1 = Selection.Find(What:=c.Value, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False)
' firstaddress = f1.Address
If Range(f1.Address).Row = Range(c.Address).Row Then
Worksheets("Лист2").Cells(i, 2).Value = c.Value
i = i + 1
End If
Next
End Sub
Ну уж нет... 10 минут будут обрабатываться 10000 записей разве что на 486-м... Я вот сейчас напишу пробный алгоритмчик. У меня, конечно, довольно хороший комп (1400мгц), но все равно посмотрим...
Ну вот, пожалуйста.
Около секунды уходит на 10000 записей.
Его, наверное, надо будет к твоим нуждам приспособить как-то. Если что непонятно, спрашивай.
Dim w As Worksheet, NumCol As Integer, wn As Worksheet
Dim i As Long, j As Long
NumCol = 6
Application.ScreenUpdating = False
Set w = ActiveSheet
Set wn = ThisWorkbook.Worksheets.Add
i = 2 '1-ya stroka - zagolovki
j = 1
While w.Cells(i, NumCol).Value <> ""
If Application.WorksheetFunction.CountIf( _
wn.Range(wn.Cells(1, 1), wn.Cells(j, 1)), _
w.Cells(i, NumCol).Value) = 0 Then
'Novoe znachenie
wn.Cells(j, 1).Value = w.Cells(i, NumCol).Value
j = j + 1
End If
i = i + 1
Wend
Application.ScreenUpdating = True
End Sub
Еще могут быть тонкости в связи с тем, что в хвостах действительных чисел образуется всякий мусор (типа 1.50000023). Но с такими штуками и сам Эксель не очень четко работает. Если у тебя именно тот случай, придется форматировать предварительно. Пиши, разберемся.
Application.ScreenUpdating = False
Application.ScreenUpdating = True
Может и банальный вопрос, но учиться никогда не вредит.
А мог бы ты пояснить предназначение
Application.ScreenUpdating = False
Application.ScreenUpdating = True
Может и банальный вопрос, но учиться никогда не вредит.
В процессе выполнения любого твоего макроса все что ты делаешь, будет изображено на экране.
Возьмем, например, такой макрос:
Dim i As Long
For i = 1 To 10000
Range("A1").Value = i
Next i
End Sub
В процессе его работы ты увидишь, как в ячейке А1 значение от 1 до 10000. После каждого изменения значения Эксель заново рисует тебе весь экран.
Во-первых, на это уходит CPU, во-вторых это часто
выглядит не очень эстетично (моргает все по всему экрану).
Возьмем такой макрос:
Dim i As Long
Application.ScreenUpdating = False
For i = 1 To 10000
Range("A1").Value = i
Next i
Application.ScreenUpdating = True
End Sub
Внешне он работает так: машина задумывается, потом сразу появляется число 10000 (причем работает быстрее). После того, как .ScreenUpdating отключил обновление экрана, все операции Эксель делал "в уме", а после Application.ScreenUpdating = True "одним махом" нарисовал все сразу.
Поскольку обычно главную ценность в макросе представляет его результат (а не процесс работы), выглядит весьма разумным сэкономить время работы оного (вышеизложенный пример слишком простой, там разница во времени не так заметна) и нервы пользователя (а то тик еще заработает :) ). Вот.
Каким образом можно воспользоваться в коде VBA результатами работы автофильтра? Как мне получить номера отфильтрованных строк?
Вопрос по Autofilter.
Каким образом можно воспользоваться в коде VBA результатами работы автофильтра? Как мне получить номера отфильтрованных строк?
Проблем никаких. У каждого листа (Worksheet) есть свойство - AutoFilter, который является объектом. Через него можно устанавивать/менять активный фильтр, а также обратиться к свойству Range, который вернет все отобранные строки, например:
Dim w As Worksheet
Dim rangeFilter as Range
Set w = ActiveWorksheet
rangeFilter = w.AutoFilter.Range
' а так можно задать свой фильтр
w.AutoFilterMode = False
w.Range("A1").AutoFilter field:=1, Criteria1:="S"
Подробнее смотри в справке на "AutoFilter"
Проблем никаких. У каждого листа (Worksheet) есть свойство - AutoFilter, который является объектом. Через него можно устанавивать/менять активный фильтр, а также обратиться к свойству Range, который вернет все отобранные строки, например:
Dim w As Worksheet
Dim rangeFilter as Range
Set w = ActiveWorksheet
rangeFilter = w.AutoFilter.Range
' а так можно задать свой фильтр
w.AutoFilterMode = False
w.Range("A1").AutoFilter field:=1, Criteria1:="S"
Подробнее смотри в справке на "AutoFilter"
Autofilter.Range возвращает Range, НА который наложен фильтр.
Вопрос в другом - не как наложить фильтр, а как воспользоваться результатами его работы. То бишь отфильтрованными строками.
Autofilter.Range возвращает Range, НА который наложен фильтр.
Вопрос в другом - не как наложить фильтр, а как воспользоваться результатами его работы. То бишь отфильтрованными строками.
Отфильтрованные строки получаешь, используя этот range, пробегая по нему и определяя какие строки скрыты. Например так:
Set rangeFilter = w.AutoFilter.Range
For Each vRow In rangeFilter.Rows
If Not vRow.Hidden Then
' покажем номера отфильтрованных строк
MsgBox vRow.row
End If
Next
Отфильтрованные строки получаешь, используя этот range, пробегая по нему и определяя какие строки скрыты. Например так:
Set rangeFilter = w.AutoFilter.Range
For Each vRow In rangeFilter.Rows
If Not vRow.Hidden Then
' покажем номера отфильтрованных строк
MsgBox vRow.row
End If
Next
Попробуй освоить расширенный фильтр, он на много мощнее и многие задачи очень упрощаются