Excel i VBA

Jak szybko pobrać dane z wielu takich samych plików i arkuszy Excela znajdujących się w jednym folderze - makro

Jakiś czas temu stworzyłem plik w programie Microsoft Excel z kodem VBA (z makrem), który służył mi do pobierania danych z wielu plików i arkuszy. Teraz odświeżyłem ten plik i postanowiłem go udostępnić wszystkim zainteresowanym. Wiem, że od czasu do czasu jego funkcjonalność przydaje się i pozwala zaoszczędzić grube godziny żmudnej pracy. Plik zawiera przydatny panel konfiguracyjny w arkuszu "konfig" oraz makro, które znacznie szybciej pozwala pobrać dane. Dokładnie chodzi o pobieranie danych o takiej samej strukturze (tabeli), które znajdują się w więcej niż w jednym arkuszu. Może to być jeden plik i setki arkuszy, lub setki plików z jednym lub kilkoma arkuszami. Cechą wspólną wszystkich danych jest taka sama tabela (najczęściej z różnymi informacjami) w każdym z tych arkuszy. Więcej wyjaśniam w dalszej części tego wpisu.

Jak szybki jest plik z moim makrem?

W moich ostatnich testach pobierałem tym makrem około dziesięciu tysięcy wierszy z dwunastu plików i około trzystu pięćdziesięciu arkuszy. Tworzony był jeden plik na miesiąc, a w każdym arkusz na kolejny dzień miesiąca i w każdym arkuszu kilkadziesiąt pozycji. Czas od kliknięcia w przycisk uruchamiania procedury do pobrania danych w jednym arkuszu wyniósł niecałe dziesięć sekund.

W tym teście nie miałem bardzo dużej ilości plików i danych, więc proces przebiegł dość szybko. Oczywistym jest, że przy znacznie większej ilości plików i arkuszy makro będzie dłużej pobierać dane. Warto też wiedzieć, że najwięcej czasu w całej procedurze zajmuje otwarcie pliku, później jego zamknięcie, a przegląd arkuszy i pobieranie danych jest relatywnie szybkie. Z tego powodu duże pliki (waga) będą wydłużać proces.

Oczywiście to tylko przykład, w którym czas zależy od wielu czynników, także od komputera. Jednak myślę, że przykład ten pokazuje jak szybko możesz wyciągnąć tabele z wielu arkuszy w wielu skoroszytach. Prace ręczne zajęłyby dziesiątki minut, może godziny, a przede wszystkim, kto ma do tego zdrowie i chciałby tyle klikać...

Żeby bardzo szybko pobrać dane, makro na początku procedury wyłącza niektóre funkcje excela, które spowalniają otwieranie plików. Wszystkie te funkcje są ponownie włączone na końcu makra - procedury. Jakie to funkcje piszę w dalszej części.

Pobierz plik xlsm


Plik jest w formacie xlsm i jak już wspomniałem zawiera makra (VBA). Na dole tego wpisu zamieściłem cały kod, który jest w pliku. Możesz go przejrzeć i ocenić, czy nie jest szkodliwy. Teoretycznie możesz też sam umieścić go w swoim pliku. Jednak ze względu na zdefiniowane nazwy komórek w arkuszu, do którego odwołuje się makro, nie będzie działał w innym skoroszycie (chyba, że też zdefiniujesz nazwy lub zmodyfikujesz kod). Przed kodem (na końcu tego wpisu) pokazuję jakie nazwy zdefiniowałem w arkuszu "konfig" i do jakich komórek się odwołują.

Jednak myślę, że nie ma potrzeby żeby te wszystkie rzeczy robić. W końcu nie jest moją intencją żeby umieszczać złośliwy kod, który mógłby wyrządzić krzywdy. Jak dokładnie wygląda procedura po uruchomieniu makra opisuję w dalszej części tego wpisu.

Tutaj pobierz plik

Zarówno plik jak i makro możesz dowolnie edytować na swoje potrzeby.


W jakich warunkach przydaje się makro do szybkiego pobierania danych?

Przede wszystkim sprawdza się do wyciągania danych z tabel o takiej samej budowie umieszczonych w wielu plikach (skoroszytach) lub w wielu arkuszach. Ilość wierszy nie ma znaczenia, bo makro samo to sprawdza. Ważny jest wiersz i kolumna początkowa oraz kolumna końcowa. Wartości te definiujsz w arkuszu konfig. Wyciągnąłem te dane z kodu do arkusza, żeby szybko i łatwo dostosować makro do swoich potrzeb (bez ingerencji w kod).

Przykłady w jakich sprawdzi się opisywane makro do wyciągania danych:

  • codziennie generowany nowy plik (skoroszyt) z taką samą strukturą i umieszczany w tym samym folderze
  • co jakiś czas generowany plik (skoroszyt) z wieloma arkuszami o takiej samej strukturze
  • plik generowany raz w miesiącu (12 plików w roku), a w każdym pliku arkusz na kolejny dzień (365 arkuszy w 12 plikach)
  • plik generowany codziennie (365 plików w roku), a w każdym arkusze o takiej samej budowie (na przykład zamówienia) - kilkaset lub kilka tysięcy arkuszy w roku.

To tylko kilka przykładów, żeby pokazać o co mi chodzi. Tak naprawdę każdy buduje swoją strukturę plików i zakładek z konkretnego powodu. Dlatego makro jest bardzo uniwersalne i nie sprawdza nazw plików (tylko rozszerzenie), ani nazw arkuszy. Za to szuka wszystkich plików w konkretnym folderze i wszystkich arkuszy w tych plikach, a z każdego z nich kopiuje wskazany zakres komórek.

Jeżeli zastanawiasz się jak szybko pobrać dane z takich plików do jednego arkusza, to być może właśnie znalazłeś tutaj rozwiązanie.

Po co pobierać dane z wielu arkuszy do jednego?

Przede wszystkim dane rozproszone w wielu arkuszach bardzo ciężko analizować, a z czasem może pojawić się taka potrzeba. Pobranie wszystkiego do jednego arkusza pozwoli znacznie skuteczniej pracować z danymi. W ten sposób powstanie jedna duża tabela. Żeby jeszcze bardziej uprościć analizę danych, możesz zdecydować, czy w ostatnich kolumnach mają być dodane informacje o plikach i arkuszach, z których dane były pobrane.

Nawet jeżeli z jakiegoś powodu nie potrzebujesz wszystkich danych, to mając je w jednej tabeli wraz z nazwami plików i arkuszy łatwo możesz je usunąć, czy filtrować.


Przy okazji, zobacz mój wpis Jak masowo dodać grafik pracy do kalendarza Google i do smartfona lub tabletu z Androidem


Założenia - ustawienia w arkuszu konfiguracyjnym "konfig"

Konfiguracja została wyciągnięta do arkusza żeby w łatwy sposób można było ją zmieniać
  1. Rozszerzenie plików
    • tutaj wybierz rozszerzenie plików, w których masz dane do pobrania
    • możesz wybrać "xls", "xlsx" lub "xlsm" - lista rozwijana
  2. Ścieżka do plików
    • tutaj podaj ścieżkę do katalogu, w którym masz pliki (z których chcesz pobrać dane do jednego arkusza). Jeżeli chcesz wyciągnąć dane z plików, które trzymasz w różnych folderach, najlepiej będzie skopiować je wcześniej do jednego folderu.
  3. Numer pierwszego wiersza
    • Podaj numer pierwszego wiersza, w którym znajdują się dane, np. 3 (założenie, że w każdym arkuszu tabela z danymi rozpoczyna się od tego samego wiersza). Parametr ten zamieściłem ze względu na to, że nie zawsze tabele muszą być tworzone od pierwszego wiersza.
  4. Litera pierwszej kolumny zakresu
    • Podaj literę pierwszej kolumny tabeli, np. B (założenie, że w każdym arkuszu tabela z danymi rozpoczyna się w tej samej kolumnie). Tabela nie musi zaczynać się od kolumny A, dlatego tutaj także jest wybór.
  5. Litera ostatniej kolumny zakresu
    • Podaj literę ostatniej kolumny tabeli, np. AO (założenie, że w każdym arkuszu tabela z danymi kończy się w tej samej kolumnie). Ostatnią kolumnę zakresu można łatwo wyciągnąć makrem. Jednak w tym przypadku wolę ustalić to "na sztywno", żeby mieć pewność, że ilość pobranych kolumn z każdego arkusza będzie taka sama. Tym parametrem możesz też ograniczyć ilość pobieranych kolumn z tabel w arkuszach. Może to być przydatne, gdyby do analizy potrzebne były tylko początkowe kolumny.
  6. Czy dodać kolumnę z nazwą arkusza
    • Tutaj możesz zdecydować, czy w ostatniej kolumnie (następnej, np. w AP - w moim przykładzie dane pobierane z plików są do kolumny AO) mają być dodawane informacje o nazwie arkusza, z którego pobrane są dane - lista rozwijana
  7. Czy dodać kolumnę z nazwą pliku
    • Tutaj możesz zdecydować, czy w ostatniej kolumnie (albo AP, albo AR - gdy już dodana jest nazwa arkusza) ma być dodawana informacja o nazwie skoroszytu, z którego pobrane są dane - lista rozwijana
  8. Czy pobierać dane tylko z arkuszy z nazwą jak data
    • Jeżeli arkusze były nazywane datą (rozpoznawany format przez Excela), to możesz ograniczyć pobieranie danych tylko z tych arkuszy (pozostałe - jeżeli są - będą ignorowane) - lista rozwijana

Zabezpieczenie makra i komunikaty o błędach

Jak już wspomniałem na początku, to makro stworzyłem na swoje potrzeby. Od tego czasu używałem go tylko ja i tylko do plików, którymi sam się opiekowałem. I w takich warunkach nie miałem żadnych problemów z działaniem makra. Tym samym nie pojawiały się żadne komunikaty o błędach. To wszystko spowodowało, że sposób oprogramowania błędów w przedstawianej procedurze był dla mnie wystarczający.

Jednak nie oznacza to, że w innym środowisku nie będą pojawiać się błędy, które nie są oprogramowane. W końcu każdy tworzy inne pliki. Z tego powodu nie daję gwarancji, że makro będzie działać z każdą strukturą plików i z każdym układem tabel. W przypadku pojawienia się komunikatu błędu nie ma zagrożenia dla pobieranych danych. Jeżeli błąd jest opisany przeze mnie to procedura zostanie zakończona, a pobrane dane będą prawdopodobnie niekompletne lub nie będzie ich w ogóle - w zależności od powodu błędu. Gdy błąd nie jest opisany przeze mnie, to procedura zostanie przerwana, a pobrane dane nie będą kompletne. Sytuacje tego typu jest mi ciężko przewidzieć, gdy nie wiem jak wyglądają pliki, z których chcesz pobrać dane.

Dlatego, dopiero gdy dowiem się, że procedura w wielu przypadkach nie działa (innym użytkownikom - na przykład Tobie), będę mógł podjąć próbę naprawienia tego. Tutaj znów nie daję gwarancji, że to się uda. Po prostu chciałbym żebyś zrozumiał, że to narzędzie powstało z mojej potrzeby i z wykorzystaniem mojej wiedzy, która w końcu jest ograniczona.

W każdym razie, przerwana procedura nigdy nie jest dobra. I ta także nie będzie. W przypadku tego programu, poza faktem, że nie będziesz miał pobranych danych (dane w Twoich plikach są bezpieczne), powstaje jeszcze jeden problem. Na początku procedury wyłączone zostało kilka funkcji, które przyśpieszyły działanie.

Jest to poniższy fragment:

 With Application

    'przyśpieszenie procedury przez wyłączenie niepotrzebnych ruchów
    .ScreenUpdating = False
    .EnableEvents = False
    .DisplayAlerts = False
    .AskToUpdateLinks = False

Przycisk "Napraw", gdy coś pójdzie nie tak

Gdy procedura zostanie przerwana, powstanie potrzeba włączenia tych funkcji. Mówię tutaj o sytuacji, gdy pojawił się błąd, który nie jest przeze mnie opisany w procedurze. Dla opisanych błędów problem ten nie powinien wystąpić. W celu włączenia tych funkcji (wyłączonych na początku działania makra) należy wcisnąć przycisk "Napraw", który znajduje się w arkuszu "konfig". Jest on tylko i wyłącznie po to, by przywrócić wyłączone wcześniej funkcje. W przypadku prawidłowego działania makra przycisk nie musi być używany. Oczywiście jest to przycisk naprawiający, więc jego użycie w dowolnym momencie nie spowoduje żadnego negatywnego skutku. Jednak jego wciskanie, gdy nie pojawił się błąd przerywający procedurę, mija się z celem.

Procedura naprawiająca wygląda tak:

Sub Napraw()
'2010-05-01 kramkom

With Application

    .DisplayAlerts = True
    .AskToUpdateLinks = True
    .EnableEvents = True
    .ScreenUpdating = True

End With

End Sub

gdzie:

  • .DisplayAlerts = True - włącza alerty
  • .AskToUpdateLinks = True - włącza powiadomienia o aktualizacji linków do zewnętrznych źródeł
  • .EnableEvents = True - włącza zdarzenia (procedury umieszczone w module ThisWorkbook)
  • .ScreenUpdating = True - włącza odświeżanie ekranu

Jak łatwo się domyślić, właśnie te funkcje są wyłączane na początku działania makra. Są to funkcje na poziomie Excela, a nie pliku, czy procedury. Stąd mają wpływ na działanie Excela nawet po zamknięciu pliku, dlatego ważne jest, by przywrócić ich działanie w przypadku błędu.

Jak działa makro?

Narzędzie otwiera po kolei wszystkie skoroszyty w lokalizacji podanej w panelu konfiguracyjnym, które są zgodne ze zdefiniowanym rozszerzeniem. Nie musisz martwić się o bezpieczeństwo tych danych, ponieważ pliki są otwierane tylko do odczytu. Po otwarciu pierwszego pliku tworzy się nowy (tymczasowy) plik, do którego są wstawiane dane z otwartego pliku. Tymczasowy plik z danymi nie jest zapisywany przez makro. Po zakończeniu działania makra sam decydujesz, czy chcesz ten plik zamknąć bez zapisywania zmian, czy chcesz go zapisać i zachować.

Makro nie ingeruje w zawartość plików - wszystkie otwiera tylko do odczytu, a na koniec zamyka je bez zapisywania zmian.

W otwartym skoroszycie makro "przegląda" wszystkie arkusze i z podanego w panelu konfiguracyjnym zakresu pobiera dane. Ostatni wiersz szukany jest przez makro na podstawie danych w kolumnie początkowej. Z założenia w tej kolumnie powinny być dane w każdym wierszu. A już na pewno w ostatnim, gdyż na tej podstawie ustalana jest ilość wierszy do kopiowania.

Dane z każdego arkusza są wstawiane w jeden arkusz (w tymczasowym pliku utworzonym przez makro). W ten sposób makro kupuje dane do jednego arkusza za każdym razem dodając informacje z kolejnego arkusza na końcu tworzonej tabeli. W zależności od ustawień w arkuszu konfiguracyjnym może dodawać jedną lub dwie kolumny z nazwami arkuszy i (lub) z nazwami skoroszytów.

Plik jest zamykany bez zapisania, gdy pętla sprawdzająca arkusze zakończy swój bieg. Następnie powtarza tę samą czynność z kolejnym plikiem w podanej lokalizacji. Makro kończy działanie, gdy otworzy wszystkie pliki we wskazanej lokalizacji i pobierze dane do jednego skoroszytu.

Jak już wspomniałem, po zakończonej pracy tymczasowy skoroszyt z danymi pozostaje do Twojej dyspozycji. Możesz go zapisać lub nie. Czynność możesz powtarzać wielokrotnie, ponieważ za każdym razem będzie się tworzyć nowy plik z danymi. W ten sposób możesz powtórzyć proces, gdyby okazało się, że potrzebujesz zmienić ustawienia w arkuszu "konfig", a niepotrzebne pliki po prostu zamknąć bez zapisania zmian.

Definicja komórek w arkuszu konfig

W arkuszu są zdefiniowane poniższe nazwy komórek. Bez tych definicji makro nie będzie działać, chyba że zmodyfikujesz je, by odnosiło się do komórek, a nie ich nazw. W pobranym pliku nie musisz nic z tym robić. Wspominam o tym żeby przedstawić w jaki sposób plik został stworzony.

Wszystkie komórki, do których odwołuje się makro mają zdefiniowaną nazwę jak na tym obrazku

Makro do szybkiego pobierania danych z wielu arkuszy

Poniżej znajdziesz cały kod, który pomaga szybko pobrać dane z wielu plików i arkuszy do jednego. Dokładnie taki kod jak niżej jest umieszczony w pliku, o którym tutaj piszę. Znajdziesz tam gotowe narzędzie, które możesz wykorzystać na swoje potrzeby.

Option Explicit

'2017-04-05 kramkom
'moduł pobierania tabel o takich samych wymiarach (szerokość) z wszystkich arkuszy wszystkich plików
'znajdujących się w podanej lokalizacji
'ilość wierszy ustalana jest przez makro na podstawie ostatniej niepustej komórki w kolumnie "litera pierwszej kolumny zakresu"

Dim Roz     As String       'rozszerzenie

Dim Path        As String   'ściezka
Dim i           As Long     'iteracja dla tablicy wirtualnej z nazwami plików w folderze
Dim WkbTemp     As Workbook 'tymczasowy plik, w którym zapisywane są wyniki

Dim npw         As String   'Numer pierwszego wiersza
Dim lpkz        As String   'Litera pierwszej kolumny zakresu (tabeli)
Dim lokz        As String   'Litera ostatniej kolumny zakresu (tabeli)
Dim cdkzna      As Boolean  'Czy dodać kolumnę z nazwą arkusza - wstawiana jako ostatatnia (dodatkowa)
Dim cdkznp      As Boolean  'Czy dodać kolumną z nazwa pliku - wstawiana jako ostatatnia - za nazwą arkusza (jeżeli ta jest wstawiona)
Dim cpdtzaznjd  As Boolean 'Czy pobierać dane tylko z arkuszy z nazwą jak data

Sub StartProces()
'2017-04-05 kramkom
'procedura startowa uruchamiana przyciskiem w arkuszu "konfig"

Dim tbl_PlikiFolderuFc  As Variant      'tablica z nazwami plików we wskazanym folderze

tbl_PlikiFolderuFc = tbl_PlikiFolderu   'pobranie nazw plików pasujących do założeń opisanych w arkuszu "konfig"

'zakończenie prodecudury, gdy brak plików o danych parametrach
If IsEmpty(tbl_PlikiFolderuFc) Then

   ' MsgBox "Brak plików w folderze " & Path, vbInformation, "Brak plików"
    
        Exit Sub

End If

'Dim czas

'czas = Timer

With Application

    'przyśpieszenie procedury przez wyłączenie niepotrzebnych ruchów
    .ScreenUpdating = False
    .EnableEvents = False
    .DisplayAlerts = False
    .AskToUpdateLinks = False
    
End With

    With ThisWorkbook.Worksheets("konfig")
    
        On Error Resume Next

        'przypisanie wartości określonych w arkuszu "konfig" do zmiennych
        npw = .Range("npw").Value
        lpkz = .Range("lpkz").Value
        lokz = .Range("lokz").Value
        cdkzna = .Range("cdkzna").Value
        cdkznp = .Range("cdkznp").Value
        cpdtzaznjd = .Range("cpdtzaznjd").Value

        If Err.Number <> 0 Then
        
            ' MsgBox Err.Number
            
            Err.Clear
            
                MsgBox "Nie mogłem pobrać danych z arkusza konfig", vbInformation, "Problem w arkuszu konfig"
                
                GoTo koniec
        
        End If
        
    End With
    
    Set WkbTemp = Workbooks.Add

        'otwieranie wszystkich znalezionych plików i wyciąganie danych
        For i = 1 To UBound(tbl_PlikiFolderuFc, 2)
        
            Workbooks.Open Path & tbl_PlikiFolderuFc(1, i), , 1
    
                If Err.Number <> 0 Then

                    ' MsgBox Err.Number
            
                    Err.Clear
            
                        MsgBox "Nie mogłem otworzyć skoroszytu " & tbl_PlikiFolderuFc(1, i), vbInformation, "Błąd przy otwarciu pliku"
                
                            GoTo koniec
            
                End If
    
                Call tbl_DanePliku(CStr(tbl_PlikiFolderuFc(1, i)))
    
            Workbooks(tbl_PlikiFolderuFc(1, i)).Close 0

        Next i
        
koniec:

    'włączenie spowalniaczy
    Call Napraw

'MsgBox Timer - czas

On Error GoTo 0

Set WkbTemp = Nothing

End Sub

Function tbl_DanePliku(File As String) As Variant
'2017-04-05 kramkom
'funkcja pobierająca dane z arkuszy do tablicy wirtualnej

Dim Wks     As Object
Dim Wkb     As Workbook
Dim n       As Variant
Dim Ost     As Long
Dim kp      As Byte

Set Wkb = Workbooks(File)

'kolumna do nazwy pliku
'jeżeli wstawiaa jest nazwa pliku, to musi być nazwa pliku przesunięta o kolejną kolumnę, stąd 2
kp = IIf(cdkzna, 2, 1)

On Error Resume Next

With Wkb

'pętla po wszsytkich arkuszach w pliku
For Each Wks In .Worksheets

    'wyłączenie pobierania, gdy włączone pobieranie danych tylko z arkusza z nazwą jak data
    If cpdtzaznjd And Not IsDate(Wks.Name) Then
    
      '  Stop
    
    Else
        
        Ost = Last(Wks.Columns(lpkz))
        
        'jeżeli są dane w podanej kolumnie (Litera pierwszej kolumny zakresu)
        If Ost > 0 Then

            'pobranie danych z podanego zakresu do tablicy
            n = Wks.Range(lpkz & npw & ":" & lokz & Ost).Value
        
                With WkbTemp.Worksheets(1)
        
                    'ustalenie pierwszego pustego wiersza w tymczasowym skoroszycie z pobranymi danymy
                    With .Cells(Last(.Columns(1)) + 1, 1)
        
                        .Resize(UBound(n), UBound(n, 2)).Value = n
                
                        'wstawienie nazwy arkuszy w ostatniej kolumnie (jeżeli PRAWDA w pozycji "Czy dodać kolumnę z nazwą arkusza"
                        If cdkzna Then
                    
                            .Offset(, UBound(n, 2) + 1).Resize(UBound(n)).Value = Wks.Name
           
                        End If
                
                        'wstawienie nazwy pliku w ostatniej kolumnie (jeżeli PRAWDA w pozycji "Czy dodać kolumnę z nazwą pliku"
                        If cdkznp Then
                
                            .Offset(, UBound(n, 2) + kp).Resize(UBound(n)).Value = Wkb.Name
           
                        End If
           
                    End With
        
                End With
        
            End If

    End If
    
    If Err.Number <> 0 Then

        Err.Clear
        
            MsgBox "Wystąpił błąd podczas pobierania danych ze skoroszytu " _
                & Chr(10) & Wkb.Name & _
                Chr(10) & "w arkuszu " & Wks.Name

    End If

Next Wks

End With

Set Wkb = Nothing
Set Wks = Nothing

End Function

Function tbl_PlikiFolderu() As Variant
'2017-04-05 kramkom
'procedura pobiera nazwy plików w folderze

Dim File        As String
Dim tblTemp2()    As Variant

i = 0

On Error Resume Next

'pobranie rozszerzenia oraz ścieżki do katalogu z pliku "konfig"
With ThisWorkbook.Worksheets("konfig")

    Roz = "." & .Range("roz")

    Path = .Range("path") & "\"

End With

    If Not PathIsExists(Path) Then
    
        MsgBox "Problem z dostępem do plików w podanym katalogu " _
            & Chr(10) & Path, vbInformation, "Problem z katalogiem"
        
            GoTo koniec
    
    End If

    File = Dir(Path & "*" & Roz)      'czy jest plik

    'pętla po wszystkich plikach we wskazanym katalogu
    Do While File <> ""
        
        'ustalenie wielkości tablicy wirtualnej do nazw plików
        i = i + 1
        ReDim Preserve tblTemp2(1 To 1, 1 To i)
  
            'przypisanie nazwy pliku do tablicy
            tblTemp2(1, i) = File
   
                File = Dir()       'szukaj kolejnego pliku
   
    Loop
    
koniec:
    
    'przypisanie wyników do funkcji
    If i > 0 Then tbl_PlikiFolderu = tblTemp2
    
On Error GoTo 0

End Function

Sub Napraw()
'2010-05-01 kramkom

With Application

    .DisplayAlerts = True
    .AskToUpdateLinks = True
    .EnableEvents = True
    .ScreenUpdating = True

End With

End Sub

Function PathIsExists(Sciezka As String) As Boolean
'2010-05-01 kramkom

   PathIsExists = IIf(Dir(Sciezka, vbDirectory) = "", False, True)

End Function

Function Last(Rng As Excel.Range) As Long
    ' wg. Ron de Bruin, 20 Feb 2007
    ' http://www.rondebruin.nl/last.htm
    On Error Resume Next
    Last = Rng.Find(What:="*", _
                    After:=Rng.Cells(1), _
                    LookAt:=xlPart, _
                    LookIn:=xlFormulas, _
                    SearchOrder:=xlByRows, _
                    SearchDirection:=xlPrevious, _
                    MatchCase:=False).Row
    On Error GoTo 0
End Function
Robert Kramer

Disqus Comments Loading...
Autor
Robert Kramer