ID tematu: 70853
 |
Filtrowanie 3 kryteria |
Autor |
Wiadomość |
stingtanner
ExcelGaduła 500+

Wersja: Win Office 2013
Pomógł: 17 razy Posty: 654
|
Wysłany: 18-05-2021, 10:54 Filtrowanie 3 kryteria
|
|
|
Witajcie
Mam chyba nietypowy problem związany z filtrowaniem.
W załączniku jest małe makro:
Kod: | Sub doXLSX_filter()
Dim wb As Workbook, sh As Worksheet
Dim auf As String, pos As String, sap As Range
Dim lr As Long
Set wb = ThisWorkbook
Set sh = wb.Worksheets("Stückliste")
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
auf = Selection.Offset(, -2).Value
pos = Selection.Offset(, -1).Value
Set sap = ActiveCell
sh.Range("A2:AM" & lr).AutoFilter Field:=1, Criteria1:=auf
sh.Range("A2:AM" & lr).AutoFilter Field:=2, Criteria1:=pos
' With sh.AutoFilter.Range
' If IsEmpty(.Range("C2", Cells(Rows.Count, "C").End(xlUp)).SpecialCells(xlCellTypeVisible).Cells(2, 1).Value) Then
' MsgBox "Nie podales numeru SAP lub zdublowane zamowienie. Sprawdz."
' .Range("C2", Cells(Rows.Count, "C").End(xlUp)).SpecialCells(xlCellTypeVisible).Cells(2, 1).Select
' Exit Sub
' End If
' End With
'
'
' Call doXLSX
'
' sh.Range("A2:AM" & lr).AutoFilter Field:=1
' sh.Range("A2:AM" & lr).AutoFilter Field:=2
'
' sap.Select
End Sub |
Klikam w numer 105, który jest w kolumnie C.
Numer ten jest za każdym razem inny / unikalny, ale numery w kol A i B mogą się powtarzać.
Makro aktualnie łapie kliknięta komórkę, następnie przypisuje 2 komórki obok do zmiennych.
Tymi zmiennymi filtruję kolumny A i B.
To działa dobrze, pod warunkiem, że nie powtarza mi się numer z kolumny A i B.
Chciał bym dołożyć teraz 3 opcję, aby stworzyć unikalny zakres, który kończy się na linii poziomej pod każdym zestawem numerów z kol A i B.
Zaznaczyłem kolorami zakresy jakie chciał bym osiągnąć po zastosowaniu filtrowania lub innej operacji.
Nie wiem czy można to osiągnąć jakimś filtrowaniem zaawansowanym, czy już muszą iść inne sprawdzania?
Kolumna C gdzie jest numer 105, czasami pod tym numerem jest pusto aż do kolejnego zakresu, a częściej z numerami K..
Wynikiem jest zapisanie tego zakresu jako nowego pliku, który składa się z 3 numerów, a w nim maja być tylko dane dotyczące tych numerów.
W tym przykładzie dany kolor to osobny plik.
PS.
Kolorem proszę się nie sugerować, to tylko zobrazowanie, w oryginale ich nie ma.
Filtrowanie_3_kryteria.xlsm
|
Pobierz Plik ściągnięto 58 raz(y) 23.2 KB |
|
|
 | ID posta:
405000
|
|
|
 |
|
|
|
kuma
Excel Expert

Wersja: Win Office 2010
Pomógł: 1531 razy Posty: 4366
|
Wysłany: 19-05-2021, 11:25
|
|
|
Przyglądnij się takiemu rozwiązaniu.
Filtrowanie odbywa się w dodatkowym arkuszu 'tmp'. W nim dokonuje się filtrowanie, zostawiłem miejsce na Twoje dodatkowe działania, np.zapis do nowego skoroszytu, itp, itd.
Po zakończeniu działań arkusz ten jest usuwany.
Wstawiłem linię z komendą 'Stop', abyś mógł wypróbować i sprawdzić zanim arkusz zostanie usunięty.
Po upewnieniu się, że wszystko działa dobrze, usuń tę linię.
Jeśli wybór komórki będzie poza kol. C to nie będzie danych po odfiltrowaniu.
Nie należy wybierać, w kol. C, komórki z wartościami, np, 37bar, bo będą niewłaściwe dane do filtrowania. Kod: | Sub doXLSX_filter_kuma()
Dim wb As Workbook, sh As Worksheet
Dim auf As String, pos As String
Dim lr As Long
Dim st As Range
Dim nxt As Range
Application.ScreenUpdating = False
Set wb = ThisWorkbook
Set sh = wb.Worksheets("Stückliste")
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
Set st = sh.Columns(3).Find("bar", after:=Cells(Selection.Row, 3), lookat:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious)
Set nxt = Range(sh.Cells(st.Row + 1, st.Column), sh.Cells(lr, st.Column)).Find("bar", lookat:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext)
If nxt Is Nothing Then Set nxt = sh.Cells(lr + 1, st.Column)
On Error Resume Next
auf = Selection.Offset(, -2).Value
pos = Selection.Offset(, -1).Value
With wb
.Sheets.Add(after:=.Sheets(.Sheets.Count)).Name = "tmp"
sh.Range("A" & st.Row & ":AM" & nxt.Row - 1).Copy Sheets("tmp").[a2]
End With
With Sheets("tmp").[a1].CurrentRegion
sh.Rows(2).Copy .Parent.[a1]
.AutoFilter Field:=1, Criteria1:=auf
.AutoFilter Field:=2, Criteria1:=pos
Dim a
If .Columns(1).SpecialCells(xlVisible).Cells.Count = 1 Then
MsgBox "Nie ma danych po odfiltrowaniu"
GoTo end_
End If
'
'tutaj zrób co potrzebujesz
'
'
End With
Stop
end_:
Application.DisplayAlerts = False
Sheets("tmp").Delete
Application.DisplayAlerts = True
End Sub |
|
_________________ Pozdrawiam. |
|
 | ID posta:
405061
|
|
|
 |
|
|
stingtanner
ExcelGaduła 500+

Wersja: Win Office 2013
Pomógł: 17 razy Posty: 654
|
Wysłany: 19-05-2021, 12:07
|
|
|
kuma,
Dziękuję za rozwiązanie.
Tego się obawiałem, że nie ma tutaj tak mocno rozwiniętego sposobu filtrowania i trzeba będzie mocno kombinować.
Twoje rozwiązanie oczywiście działa jak należy. Problem jednak w tym że chciałem uniknąć tworzenia dodatkowego arkusza, który jak widać rozwiązuje problem bardzo dobrze.
Troszkę kombinowałem i poszedłem w podobną stronę co ty, ale bez tworzenia nowego arkusza:
Kod: | Sub doXLSX_filter()
Dim wb As Workbook, sh As Worksheet
Dim auf As String, pos As String, sap As Range
Dim lr As Long, i As Long
Set wb = ThisWorkbook
Set sh = wb.Worksheets("Stückliste")
lr = sh.Cells(sh.Rows.Count, "A").End(xlUp).Row
Dim r1 As Range, r2 As Range, r3 As Range
auf = Selection.Offset(, -2).Value
pos = Selection.Offset(, -1).Value
Set sap = ActiveCell
sh.Range("A2:AM" & lr).AutoFilter Field:=1, Criteria1:=auf
sh.Range("A2:AM" & lr).AutoFilter Field:=2, Criteria1:=pos
Set r1 = sap.Offset(-1, -2)
Do
i = i + 1
Loop Until sap.Offset(i).Value Like "*105*"
Set r2 = sap.Offset(i)
Set r3 = Range(r1, r2.Offset(-2, 14))
With sh.AutoFilter.Range
If IsEmpty(.Range("C2", Cells(Rows.Count, "C").End(xlUp)).SpecialCells(xlCellTypeVisible).Cells(2, 1).Value) Then
MsgBox "Nie podales numeru SAP lub zdublowane zamowienie. Sprawdz."
.Range("C2", Cells(Rows.Count, "C").End(xlUp)).SpecialCells(xlCellTypeVisible).Cells(2, 1).Select
Exit Sub
End If
End With
Call doXLSX
sh.Range("A2:AM" & lr).AutoFilter Field:=1
sh.Range("A2:AM" & lr).AutoFilter Field:=2
sap.Select
End Sub |
Wyznaczam początek i koniec zakresu pętlą, pewnie rozwiązanie wolniejsze ale też działa.
Jednak nie jest to jeszcze rozwiązanie idealne.
Zobaczę które na dłuższą metę i wielkość danych okaże się wydajniejsze. |
|
 | ID posta:
405064
|
|
|
 |
|
|
Artik
Artik


Wersja: Win Office 365
Pomógł: 3231 razy Posty: 10702
|
Wysłany: 20-05-2021, 14:29
|
|
|
Nie wiem, czy to się na coś przyda. Ale skoro zrobiłem...
Zadanie zrozumiałem tak, że chcesz aby w arkuszu Stückliste po filtrowaniu były widoczne tylko dane z wybranego zakresu. A tym wybranym zakresem jest obszar "okalający" liczbę "105*".
Jednak w końcu chyba się okazało, że nie chodzi Ci o wizualizację, a tylko o określenie zakresu "okalającego" by go skopiować do nowego skoroszytu.
stingtanner napisał/a: | Problem jednak w tym że chciałem uniknąć tworzenia dodatkowego arkusza | Chyba Ci o to właśnie chodziło. Chcesz pewien zakres skopiować do nowego skoroszytu. kuma co prawda tworzy Ci arkusz w tym samym skoroszycie, ale jesteś już na tyle duży, że nie powinieneś mieć problemów z modyfikacją jego kodu.
Poniżej moja wersja robocza, która zachowuje się jak Autofiltr. Nie trzeba zaznaczać komórki z liczbą "105*", wystarczy aktywować jakąkolwiek komórkę w zakresie. Zastosowane filtrowanie jest pewnym oszustwem. Filtr jest zakładany tylko po to, by już bez makra odkryć wszystkie dane w tabeli lub wybrać inną liczbę "105*". Rozwiązanie jest nieco wolniejsze od Waszych, głównie z powodu zabawy z ukrywaniem/odkrywaniem wierszy ( i nie tylko). Lecz sekunda wte czy wewte raczej bez znaczenia. Testowałem na sporym zakresie danych, bo ok. 964k wierszy.
Kod: | Sub Filtrowanie()
Dim v As Variant
Dim i As Long
Dim lFrow As Long
Dim lLrow As Long
Dim lFFltrRow As Long
Dim lLFltrRow As Long
Dim oDic As Object
Dim vv() As Variant
Dim k As Long
Dim lActvCelRow As Long
With Tabelle1.AutoFilter.Range.Columns("C")
v = .Offset(1).Resize(.Rows.Count - 1).Value
lFrow = -1
lLrow = -1
lFFltrRow = .Row + 1
End With
lLFltrRow = UBound(v) + lFrow + lFFltrRow
Set oDic = CreateObject("Scripting.Dictionary")
For i = 1 To UBound(v)
If v(i, 1) Like "105*" Then
If Len(v(i, 1)) >= 6 Then
If lLrow = lFrow Then
lFrow = i - 1
Else
lLrow = i - 2
oDic.Add Tabelle1.Cells(lFrow + lFFltrRow - 1, 1).Resize(lLrow - lFrow + 1, 15), 0
ReDim Preserve vv(0 To 1, 0 To k)
vv(0, k) = lFrow + lFFltrRow - 1
vv(1, k) = lLrow + lFFltrRow - 1
k = k + 1
lFrow = lLrow + 1
End If
End If
End If
Next i
oDic.Add Tabelle1.Cells(lFrow + lFFltrRow - 1, 1).Resize(i - lFrow, 15), 0
ReDim Preserve vv(0 To 1, 0 To k)
vv(0, k) = lFrow + lFFltrRow - 1
vv(1, k) = lLFltrRow
lActvCelRow = ActiveCell.Row
For i = 0 To UBound(vv, 2)
If lActvCelRow <= vv(1, i) Then
If lActvCelRow >= vv(0, i) Then
Exit For
End If
End If
If i Mod 100 = 0 Then DoEvents
Next i
Application.ScreenUpdating = False
Tabelle1.AutoFilter.Range.AutoFilter Field:=3, Criteria1:=oDic.Keys()(i).Cells(2, 3).Value
With Tabelle1.AutoFilter.Range
.Offset(1).Resize(.Rows.Count - 1).EntireRow.Hidden = True
End With
oDic.Keys()(i).EntireRow.Hidden = False
MsgBox oDic.Keys()(i).Address
End Sub |
Artik |
_________________ Persistence is a virtue in the world of programming.
Weryfikator NIP - szybka, masowa weryfikacja w MF i VIES. |
|
 | ID posta:
405122
|
|
|
 |
|
|
stingtanner
ExcelGaduła 500+

Wersja: Win Office 2013
Pomógł: 17 razy Posty: 654
|
Wysłany: 21-05-2021, 10:19
|
|
|
kuma, Artik,
Muszę przyznać, że po zastosowaniu obu kodów, do istniejących rozwiązań jeden i drugi świetnie się spisują.
Wyniki są poprawne, a czas wykonywania w obu przypadkach jest zadowalający.
Artik napisał/a: | ale jesteś już na tyle duży, że nie powinieneś mieć problemów z modyfikacją jego kodu |
Oba rozwiązania zastosuję :) troszkę już urosłem i nie mam problemu, aby dostosować sobie kod :) |
|
 | ID posta:
405139
|
|
|
 |
|
|
|
Nie możesz pisać nowych tematów Nie możesz odpowiadać w tematach Nie możesz zmieniać swoich postów Nie możesz usuwać swoich postów Nie możesz głosować w ankietach Nie możesz załączać plików na tym forum Możesz ściągać załączniki na tym forum
|
Dodaj temat do Ulubionych Wersja do druku
|
|
Strona używa plików cookies.
Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe
|