Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Пробежаться по всем фильтрам / 6 сообщений из 6, страница 1 из 1
18.02.2011, 17:00
    #37125152
Пробежаться по всем фильтрам
Здравствуйте,
хочу перебрать все столбцы с фильтрами, количество которых задано пользователем.
Кроме вложенных циклов ничего в голову не приходит.
Неизвестное количество вложенных циклов, по-моему, не реализуется в VBA.
Но должны же быть какие-то варианты?
...
Рейтинг: 0 / 0
18.02.2011, 18:02
    #37125278
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пробежаться по всем фильтрам
Задача совершенно не понятна.
Но если нужно неизвестное количество вложеных циклов, то используется рекурсия.
...
Рейтинг: 0 / 0
18.02.2011, 18:04
    #37125284
Игорь Горбонос
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пробежаться по всем фильтрам
> Автор: Дмитрий-(сколько-же-нас?)
> хочу перебрать все столбцы с фильтрами, количество которых задано пользователем.
> Неизвестное количество вложенных циклов, по-моему, не реализуется в VBA.


Не понял, а почему неизвестное количество?
На мой взгляд(не замутнённый нарзаном) тут всего один цикл по столбцам выбранным пользователем, внутри которого второй
цикл по автофильтрам для проверки вхождения столбца в область действия фильтра. Ну или наоборот :)

Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
21.02.2011, 09:52
    #37127479
Пробежаться по всем фильтрам
White OwlЗадача совершенно не понятна.
Но если нужно неизвестное количество вложеных циклов, то используется рекурсия.
С рекурсией в VBA, вроде, какие-то проблемы?
По-крайней мере, я как-то пробовал на какой-то не сложной задаче -- не заработало...

Игорь ГорбоносНе понял, а почему неизвестное количество?
На мой взгляд(не замутнённый нарзаном) тут всего один цикл по столбцам выбранным пользователем, внутри которого второй
цикл по автофильтрам для проверки вхождения столбца в область действия фильтра. Ну или наоборот :)


Количество неизвестно, потому что задаётся пользователем в начале выполнения макроса, через InputBox.
Цикл по автофильтрам не работает, т.к. нужно выставлять значения всех полей.
Т.о. если заданы три поля и первое поле содержит -- 5 значений автофильтра, 2-е поле -- 3, 3-е -- 2, то для перебора всех значений нужно, что-то типа:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
For i= 1  to  5 
 .Autofilter Field:= 1 , Criteria1:=C_a( 1 ,i)
 For j= 1  to  3 
  .Autofilter Field:= 2 , Criteria1:=C_a( 2 ,j)
  For k= 1  to  2 
    .Autofilter Field:= 3 , Criteria1:=C_a( 3 ,k)
  Next
 Next
Next
Только количество полей неизвестно :)
Без рекурсии не обойтись?
...
Рейтинг: 0 / 0
21.02.2011, 11:24
    #37127705
Игорь Горбонос
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Пробежаться по всем фильтрам
> Автор: Дмитрий-(сколько-же-нас?)
> Количество неизвестно, потому что задаётся пользователем в начале выполнения макроса, через InputBox.

И что? Ну задал пользователь и что? Кстати! А что задает пользователь через InputBox?

> Цикл по автофильтрам не работает, т.к. нужно выставлять значения всех полей.

Вот это не понял. Что значит не работает и какие значения нужно выставлять?

> Т.о. если заданы три поля и первое поле содержит -- 5 значений автофильтра, 2-е поле -- 3, 3-е -- 2, то для
> перебора всех значений нужно, что-то типа:

Здесь тоже не совсем понятно - что ты хочешь получить в результате? Зачем перебирать все возможные комбинации? почему-бы
не пройтись только по существующим комбинациям этих автофильтров?

Например:Исходные данные на листе в столбцах A-AM, но отбор происходит по данным расположенным в столбцах -
P-T
Остальные данные просто копируются в результат.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
Option Explicit

Private Sub Svertka()
'
' Макрос1 Макрос
' Макрос записан 14.01.2009 (user)
'

'
Dim sCurrentFiltRange As String
Dim r As Range
Dim s As Worksheet, sh As Worksheet, shOut As Worksheet, w As Workbook, w1 As Workbook
Dim vPriznak As Variant
Dim vMonth As Variant
Dim vGroup As Variant

On Error GoTo labErr

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

' Запоминаем текущую книгу и лист. Они считаются исхолдными данными
Set w = Application.ActiveWorkbook
Set sh = Application.ActiveSheet
' Проверяем наличие автофильтра, можно устанавливать самому, но ...
If sh.AutoFilter Is Nothing Then
    MsgBox "Установите автофильтр"
    Exit Sub
End If
' Получаем адрес используемого в автофильтре диапазона
sCurrentFiltRange = sh.AutoFilter.Range.Address
' Добавляем новую книгу для сохранения результатов
Set w1 = Application.Workbooks.Add
Application.DisplayAlerts = False
w1.PrecisionAsDisplayed = True
Application.DisplayAlerts = True

' Добавляем в новую книгу два листа, для списка уникальных значений автофильтра и для конечного результата
CheckSheet w1, "Уникальные"
Set s = CheckSheet(w, "Результат") 'w.Worksheets.Add

' Копируем "шапку" данных из источника в результат
w.Activate
sh.Rows( 1 ).Copy
s.Select
s.Rows( 1 ).Select
s.Paste
s.Range("AD1").Value = "Пустое"
s.Range("AE1").Value = "Количество записей в оригинале"

' Получаем список уникальных комбинаций из
' признак филиал-Укрнафта или ещё какой-то,
' месяца оплаты, номера платёжного поручения,
' группы, вида и суммы оплаты
Set r = w1.Worksheets("Уникальные").Range("a1")
sh.Range("P:U").AdvancedFilter xlFilterCopy, , r, True
Application.DisplayAlerts = False
w1.PrecisionAsDisplayed = False
DoEvents
w1.PrecisionAsDisplayed = True
' Получаем массив уникальных данных, для прокрутки по автофильтру
vGroup = r.Range("a2:F" + CStr(r.SpecialCells(xlCellTypeLastCell).Row)).Value2
Application.DisplayAlerts = True

w.Activate
s.Select
Dim iPriz As Long, iMonth As Long, iGr As Long, i As Long, nCurrRow As Long, bFirst As Boolean
nCurrRow =  2 
Dim ar As Areas
For iGr = LBound(vGroup) To UBound(vGroup)
    With sh.Range(sCurrentFiltRange)
        ' Работаем с автофильтрами
        .AutoFilter Field:= 16 , Criteria1:=CStr(vGroup(iGr,  1 )) '"январь"
        .AutoFilter Field:= 17 , Criteria1:=CStr(vGroup(iGr,  2 )) '"филиал"
        .AutoFilter Field:= 18 , Criteria1:=CStr(vGroup(iGr,  3 )) '№ платежки
        .AutoFilter Field:= 19 , Criteria1:=CStr(vGroup(iGr,  4 )) '"п.01 Группа платежа"
        .AutoFilter Field:= 20 , Criteria1:=CStr(vGroup(iGr,  5 )) '"пп.01.1 Статья платежа"
        .AutoFilter Field:= 21 , Criteria1:=Replace(Trim(Format(vGroup(iGr,  6 ), "#,##0.00000")), ",", ".") ' сумма
        'Подсчитываем общее количество по автофильтру
        For Each r In sh.Range(sCurrentFiltRange).SpecialCells(xlCellTypeVisible).Areas
            i = i + r.Rows.Count ' .SpecialCells(xlCellTypeVisible).Rows.Count
        Next r
        If i >  1  Then
            bFirst = True
            For Each r In sh.Range(sCurrentFiltRange).SpecialCells(xlCellTypeVisible).Areas
            ' Выбираем первую, но не шапку и копируем её в результат
            ' и корректируем сумму на количество записей в автофильтре
                If r.Rows.Count >  1  Or Not bFirst Then
                    r.Rows( 1  + - 1  * CLng(bFirst)).Copy
                    s.Select
                    s.Rows(nCurrRow).Select
                    s.Paste
                    s.Cells(nCurrRow,  21 ).Value = "=" + Replace(CStr(s.Cells(nCurrRow,  21 ).Value), ",", ".") + "*" + 
CStr(i -  1 )
                    s.Cells(nCurrRow,  31 ).Value = CStr(i -  1 )
                    nCurrRow = nCurrRow +  1 
                    Exit For
                Else
                    bFirst = False
                End If
            Next r
        Else
            i = i
        End If
        pBar.Value = pBar.Value +  1 
        pBar.Refresh
'        Debug.Print i - 1, Round(CDbl(vGroup(iGr, 6)), 2), CStr(vGroup(iGr, 1)), CStr(vGroup(iGr, 2)), CStr(vGroup(iGr, 
 3 )), CStr(iGr)
        i =  0 
    End With
Next iGr
' Отключаем автофильтры
sh.ShowAllData
pBar.Value = pBar.Value +  1 
If nCurrRow >  2  Then
' Строим сводную для проверки
'    Call CreatePivotTables(sh, sCurrentFiltRange, s, "A1:AE" + CStr(nCurrRow - 1))
End If
sCurrentFiltRange = w1.Name
Set w1 = Nothing
Application.DisplayAlerts = False
' Закрываем книгу с уникальным списком
Application.Workbooks(sCurrentFiltRange).Close (False)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
pBar.Value = pBar.Value +  1 
pBar.Value = pBar.Max
If nCurrRow >  2  Then
    MsgBox "Закончили!"
Else
    MsgBox "Нет данных для обработки, данные не обработаны!", vbCritical + vbOKOnly
End If
Exit Sub
labErr:
sCurrentFiltRange = w1.Name
Set w1 = Nothing
Application.DisplayAlerts = False
Application.Workbooks(sCurrentFiltRange).Close (False)
Application.DisplayAlerts = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Что-то не получилось, данные не обработаны! Ошибка - " & Err.Description, vbCritical + vbOKOnly
End Sub

Private Function CheckSheet(w As Workbook, sName As String, Optional bCreate As Boolean = True) As Worksheet
Dim b As Boolean
b = Application.DisplayAlerts
Application.DisplayAlerts = False
On Error GoTo labErr
' Если есть лист пытаемся удалить его
w.Sheets(sName).Delete
If bCreate Then
' Если удалили и нужно создавать, создаем и возвращаем
    Set CheckSheet = w.Sheets.Add
    CheckSheet.Name = sName
End If
Application.DisplayAlerts = b
Exit Function
labErr:
Application.DisplayAlerts = b
If bCreate Then
' Если нужно создавать, создаем и возвращаем
    Set CheckSheet = w.Sheets.Add
    CheckSheet.Name = sName
End If
End Function


Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
21.02.2011, 12:07
    #37127850
Пробежаться по всем фильтрам
Игорь Горбонос,

Спасибо, за пример -- буду "копать"...

А через InputBox пользователь вводит регион -- подписи столбцов по которым будет проводиться перебор.
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Пробежаться по всем фильтрам / 6 сообщений из 6, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]