May 15 2008

Generowanie i formatowanie raportu przy pomocy VBA

Posted by Bartek

Dzisiaj pokażę jak zbudować łatwy w rozwoju schemat do generowania raportów. Przyjmijmy, że w naszym skoroszycie mamy dużą tabele (100 kolumn i kilka tysięcy wierszy). Nasz aplikacja ma w oparciu o tą tabelę generować raporty. Każdy raport zapisywany jest w nowym skoroszycie. Oczywiście, jak to zwykle bywa, nie znamy listy raportów, które będą generowane przez naszą aplikację. W praktyce oznacza to dla nas tyle, liczba kolumn i wierszy w raporcie może być dowolna.

Krok 1 - Budujemy środowisko testowe

Zacznijmy od przygotowania prototypu symulującego zachowanie raportu. A naszym pliku stwórzym arkusz RAPORT, a następnie przygotujmy w nim poniższą tabelę.

Nasza procedura testująca będzie ładowała powyższy zakres do 2 tablic -- pierwszej, która zawiera nagłówki kolumn raportu, oraz drugiej która zawierać będzie jego treść. Te tablice wykorzystam jako dane wejściowe do wygenerowania raportu.
Kod procedury testującej wygląda następująco

Sub ProceduraTestujaca()
          'ustawiamy arkusz z danymi testowymi
          Dim wksDaneTestowe As Worksheet
10        Set wksDaneTestowe = ThisWorkbook.Worksheets("Test")
          'tablice zawierajace naglowek
          Dim headRaport As Variant
          'oraz tresc raportu
          Dim bodyRaport As Variant
          'Ładujemy naglowki do tablicy
          Dim headRange As Range
20        Set headRange = wksDaneTestowe.Range( _
                              wksDaneTestowe.Range("A1").Address, _
                              wksDaneTestowe.Range("A1").End(xlToRight).Address)
30        headRaport = headRange
          'oraz ciało
          Dim bodyRange As Range
40        Set bodyRange = wksDaneTestowe.Range( _
                              wksDaneTestowe.Range("A2").Address, _
                              wksDaneTestowe.Range("A2").End(xlToRight).End(xlDown).Address)
50        bodyRaport = bodyRange
          'sprawdzamy czy jest dane sie załadowały
60        MsgBox UBound(headRaport, 2) 'ile kolumn ma naglowek
70        MsgBox UBound(bodyRaport, 1) 'ile wierszy ma raport
          'czyścimy po sobie
80        Set wksDaneTestowe = Nothing
90        Set headRange = Nothing
100       Set bodyRange = Nothing
End Sub

Krok 2 - Składniki, czyli funkcje

Nasz moduł do tworzenia raportów będzie składał się z trzech funkcji. Pierwsza stworzy nowy arkusz, druga sformatuje nagłówek raportu, a trzecia jego wiersze. Funkcję, która posłuży nam do stworzenia nowego arkusza opisałem już w jednym z poprzednich postów. Poniżej zmodyfikowałem ją nieco żeby zwracała nam jako obiekt arkusz, w którym powstanie raport

Function createNewSheet(nazwa As String) As Worksheet
    Dim Skoroszyt As Workbook
    Set Skoroszyt = Application.Workbooks.Add()
    Dim Arkusz As Worksheet
    For Each Arkusz In Skoroszyt.Worksheets
        If Arkusz.Name = "Arkusz1" Then
           Arkusz.Name = nazwa
        Else
           Application.DisplayAlerts = False
           Arkusz.Delete
           Application.DisplayAlerts = True
        End If
    Next
    Set createNewSheet = Skoroszyt.Worksheets(nazwa)
End Functio

Do stworzenia nagłówka raportu wykorzystamy następującą funkcję:

Sub GenerowanieNaglowka(arkusz As Worksheet, naglowek as Variant)
    'w arkuszu z raportem tworzymy zakres zawierający komórki do sformatowania
    'w naszym przypaku nagłówek zawsze będzie znajdował się w pierwszym wierszu arkusza
    Dim Zakres As Range
    Set Zakres = arkusz.Range(arkusz.Cells(1, 1), arkusz.Cells(1, UBound(naglowek, 1)))
    'formatujemy zakres z nagłówkiem
    With Zakres
        With .Font
            .Name = "Arial"
            .Size = 8
            .ColorIndex = 2
        End With
        With .Interior
            .ColorIndex = 1
        End With
        With .Borders
            .LineStyle = xlContinuous
            .ColorIndex = 1
        End With
        .EntireColumn.ColumnWidth = 10
        .WrapText = True
        .HorizontalAlignment = xlCenter
    End With
    'zapisujemy nagłówki kolumn do naszego zakresu
    Zakres.Value = naglowek
End Sub

Do funkcji przekazywane są dwa parametry -- obiekt arkusz w którym będą przechowywane dane oraz tablica z naglówkami. Funkcja najpierw tworzy zakres o odpowiedniech dla nagłówka rozmiarach, następnie formatuje go i na końcu zapisuje do niego wartości. Oczywiście przedstawione w funkcji formatowanie jest bardzo uproszczone. Jeżeli chcemy zrobić coś bardziej wyrafinowanego, to proponuję nagrać makro formatujące jedną komórkę w taki sposób jak chcemy, a następnie podlglądnąć jego składnię, formatowania należy szukać w bloku.

   With Selection
        .HorizontalAlignment = xlCenter
        ....
    End With

Teraz wystarczy tylko przekleić interesujący nas fragment, zamienić Selection na Zakres i nasz nagłówek jest gotowy.
Ostatnią z funkcji będzie odpowiadała za formatowanie i zapis właściwej części raportu. Wygląda ona bardzo podobnie do funkcji generującej nagłówek

Sub GenerowanieBody(Arkusz As Worksheet, naglowek As Variant)
   Dim Zakres As Range
   Set Zakres = Arkusz.Range(Arkusz.Cells(2, 1), _
                             Arkusz.Cells(UBound(naglowek, 1) + 1, UBound(naglowek, 2)))
   With Zakres
     With .Borders
        .LineStyle = xlContinuous
     End With
     With .Font
        .Name = "Arial"
        .Size = 8
     End With
     .Columns.AutoFit
   End With
   Zakres.Value = naglowek
End Sub

Łączymy wszystko razem

Aby uruchomić naszą aplikację podmieniamy liniki z numerami 60 i 70 poniższymi

60       Dim wksRaport As Worksheet
          Set wksRaport = createNewSheet("RAPORT")
          Call GenerowanieNaglowka(wksRaport, headRaport)
70       Call GenerowanieBody(wksRaport, bodyRaport)

I to wszystko. W 90 linijkach udało stworzyć nam się prostą i elastyczną sturkturę do genrowania raportów.

Powiązane artykuły:

Leave a Reply