Jan 11 2010

Wtorki z VBA cz.12 – Usuwanie pustych wierszy

Posted by Marcin

Wraz z nastaniem Excela 2007 kwestie wydajności oprogramowania dla Excela zaczynają być IMHO coraz istotniejsze. Dlaczego? Dlatego, że ilość wierszy (milion!), lub raczej ilość komórek, które przetwarzalibyśmy stosując prymitywne metody brute-force jest tak duża, że makra wykonywałyby się zbyt długo. Dlatego warto się czasami chwilę zastanowic jak zredukować ilość operacji i zaplanować w miarę wydajny algorytm. Dziś przedstawię Wam pomysł jak usunąć wszystkie puste wiersze, unikając przeglądania każdego z wierszy.

Pomysł jest banalny: zamiast przeglądać wszystkie wiersze, spróbujmy ograniczyć pole poszukiwań tylko do tych, które zawierają się w tzw. obszarze roboczym (obszar listy, danych itp.). Możemy go zidentyfikować za pomocą właściwości UsedRange obiektu Worksheet. Oto nasza procedura:

 
Option Explicit
Sub UsunPusteWiersze()
 
Dim OstatniWiersz As Long
Dim Indeks As Long
 
    OstatniWiersz = ActiveSheet.UsedRange.Row - 1 +
ActiveSheet.UsedRange.Rows.Count
    For Indeks = OstatniWiersz To 1 Step -1
        If Application.WorksheetFunction.CountA(Rows
(Indeks)) = 0 Then
            Rows(Indeks).Delete
        End If
    Next Indeks
 
End Sub
 

Najpierw musimy znaleźć granice naszego obszaru (ostatni wiersz). Nie jest to takie oczywiste na pierwszy rzut oka, ponieważ nasz obszar roboczy nie musi (choć może) zaczynać się od pierwszego wiersza, zatem zwykła instrukcja UsedRange.Rows.Count jest niewystarczająca. Proponuję zatem takie rozwiązanie:

 
OstatniWiersz = ActiveSheet.UsedRange.Row - 1 + _
ActiveSheet.UsedRange.Rows.Count
 

Co się tutaj dzieje? Prosta rzecz: znajdujemy pierwszy wiersz (ActiveSheet.UsedRange.Row), odejmujemy jedynkę i dodajemy do tego liczbę wszystkich wierszy naszego zakresu (UsedRange.Rows.Count).

Następnie, zaczynając od ostatniego wiersza przesuwamy się za pomocą pętli For... Step -1... Next w górę (zwracam uwagę na Step -1) sprawdzając czy dany wiersz jest pusty. Jeśli jest pusty - usuwamy go.

Na zakończenie dodam jeszcze kilka słów na temat sprawdzania, czy wiersz jest pusty. Instrukcja:

 
Application.WorksheetFunction.CountA(Rows(Indeks)) = 0
 

wykorzystuje funkcję arkusza CountA (w PL ILE.NIEPUSTYCH()) aby sprawdzić, czy w dowolnej komórce danego wiersza (CountA(Rows(Indeks))) znajduje się jakakolwiek wartość lub wyrażenie. Jeśli nie - wiersz jest usuwany.

Podsumowanie

Przedstawiony przykład jest bardzo prosty i do zastosowań tzw. produkcyjnych wymaga jeszcze nieco dopracowania (blokada ekranu, informacja np. w pasku statusu ile procent już zostało wykonane etc.), niemniej pozwala uzmysłowić jak wiele czasu i mocy procesora możemy zaoszczędzić poprzez przemyślany algorytm i unikanie niepotrzebnych działań.

Powiązane artykuły:

Leave a Reply