W tym artykule chciałbym opowiedzieć Ci o tak potężnej funkcji FastReportu jak "raporty wielopoziomowe" - możesz porównać jego strukturę do drzewa "trzon, grubsze gałęzie z których wyrastają cieńsze i tak dalej aż do liści" lub do struktury przedsiębiorstwa "Działy, pododziały, pracownicy". Często są one nazywane “master-detail” lub "główny-podrzędny" - i takie raporty składają się z kilku tabel. Jedna tabela posiada listę podmiotów głównych, druga tabela powiązana z pierwszą posiada listę podmiotów podrzędnych w odniesieniu do pierwszej - jaki konkretny podmiot z pierwszej jest podrzędny do danego podmiotu podrzędnego. I tak dalej.
FastReport zapewnia wbudowaną obsługę 6 poziomów nestingu (więcej można zrobić za pomocą obiektu Nested Report, ale o tym później). W rzeczywistych zastosowaniach rzadko zachodzi potrzeba drukowania raportów z dużą zawartością danych; zazwyczaj jest ono ograniczone do 1 do 3 poziomów.
Przykład przygotowania raportu wielopoziomowego
Przyjrzyjmy się przykładowi tworzenia raportu dwupoziomowego. Będzie on zawierał dane z tabel Customer i Orders. Pierwsza tabela to lista klientów, druga to lista zamówień złożonych przez klientów. Tabele zawierają dane następującego rodzaju:
Customer:
CustNo Company
1221 Kauai Dive Shoppe
1231 Unisco
1351 Sight Diver
Orders:
OrderNo CustNo SaleDate
1003 1351 12.04.1988
1023 1221 01.07.1988
1052 1351 06.01.1989
1055 1351 04.02.1989
1060 1231 28.02.1989
1123 1221 24.08.1993
Jak widać, druga tabela zawiera listę wszystkich zamówień złożonych przez wszystkie firmy. Aby uzyskać listę zamówień złożonych przez konkretną firmę, należy wybrać z tabeli rekordy, których pole CustNo = numer wybranej firmy. Raport oparty na tych danych będzie wyglądał jak poniżej:1221 Kauai Dive Shoppe
1023 01.07.1988
1123 24.08.1993
1231 Unisco
1060 28.02.1989
1351 Sight Diver
1003 12.04.1988
1052 06.01.1989
1055 04.02.1989
Przejdźmy do tworzenia raportu. Tworzymy nowy projekt w Delphi, umieszczamy na formularzu dwa komponenty TTable, komponent TDataSource, dwa komponenty TfrxDBDataSet i jeden TfrxReport.
Podłączamy dane z bazy danych do obiektów raportu
Następujące elementy należy skonfigurować w następujący sposób:
Table1: DatabaseName = 'DBDEMOS' TableName = 'Customer.db' Table2: DatabaseName = 'DBDEMOS' TableName = 'Orders.db' DataSource1: DataSet = Table1 frxDBDataSet1: DataSet = Table1 UserName = 'Customers' frxDBDataSet2: DataSet = Table2 UserName = 'Orders'
W projektancie raportu podpinamy nasze źródła danych w oknie "Raport|Dane...".
Dodaj do strony zakładki "Dane poziomu 1" (master) i "Dane poziomu 2" (detail). A z panelu danych (po prawej stronie) do odpowiednich obszarów będziemy wyciągać pola tabeli (głównej i podrzędnej). I będzie wyglądać to tak:
Proszę zwrócić uwagę, że pole"Dane poziomu 1" powinno być umieszczone powyżej! Jeżeli jest ono umieszczone poniżej pola"Dane poziomu 2", FastReport zgłosi błąd podczas uruchamiania raportu.
Teraz przy uruchomieniu możemy zobaczyć, że lista zamówień jest taka sama dla każdego klienta i zawiera wszystkie dane z tabeli Orders. Stało się tak, ponieważ nie włączyliśmy filtrowania rekordów w tabeli Orders.
Wróćmy do naszych źródeł danych. W komponencie Table2 ustawmy właściwość MasterSource = DataSource1. W ten sposób nawiązaliśmy relację "główny - podrzędny". Teraz musimy ustawić warunek, aby filtrować rekordy w źródle podrzędnym. W tym celu należy wywołać edytor właściwości MasterFields komponentu Tabela2:
Musimy połączyć dwa pola CustNo w obu źródłach. Aby to zrobić, wybierz indeks CustNo z listy na górze, wybierz pola i kliknij "Dodaj". Połączone pola zostaną przeniesione do okna dolnego. Następnie zamknij edytor przyciskiem OK.
Kiedy uruchomisz raport, FastReport wykona następujące czynności. Wybranie kolejnego rekordu z tabeli głównej (Customer) spowoduje ustawienie filtru na tabeli podrzędnej (Orders). W tabeli pozostaną tylko te rekordy, które spełniają warunek Orders.CustNo = Customer.CustNo, tzn. dla każdego klienta zostaną wyświetlone tylko jego zamówienia:
W podobny sposób można budować raporty zawierające do 6 poziomów danych.