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ń.
