Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
ID tematu: 70853 Skopiuj do schowka 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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
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 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
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

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.wip.pl

Archiwum

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