JasperReport – część II
Ze względu na fakt że zdecydowana większość aplikacji ma jako część funkcjonalności szeroko pojęte generowanie raportów – ponownie na warsztacie znalazł się Jasper. Tym razem jednak postaram się przedstawić sposób na proste tworzenie raportów wymagających nie tylko dynamicznej ilości wierszy, ale także i kolumn. Nie będę się skupiać na tematach omówionych w poprzednim artykule o Jasperze i omówię tylko to co jest tu ‘nowością’, łącznie z krótkim opisem użycia narzędzia iReport.
Problem
Stosunkowo łatwo można wyobrazić sobie raport, w którym musimy przedstawić dane w nieznanym z góry rozmiarze. O ile dodawanie nowych elementów w pionie jest trywialnym zagadnieniem w Jasperze, tak generowanie danych w poziomie jest już dość kłopotliwe. Raport z dynamiczną ilością zarówno kolumn jak i wierszy wydaje się być niemożliwym do zrobienia. Na szczęście iReport posiada dość nietypowy element który można umieścić na raporcie. Jest to tabela krzyżowa (crosstab). Jak można przypuszczać – służy ona do obsługi tych nietypowych sytuacji.
Tworzenie szablonu raportu
Zacznijmy zatem. Na początku potrzebne będzie nam DTO do przechowania danych które chcemy wyświetlić.
public class ReportElementDTO {
private String columnName;
private String rowName;
private Integer value;
public String getColumnName() {
return this.columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public String getRowName() {
return this.rowName;
}
public void setRowName(String rowName) {
this.rowName = rowName;
}
public Integer getValue() {
return this.value;
}
public void setValue(Integer value) {
this.value = value;
}
}
Następnie w iReporcie tworzymy sobie nowy raport i definiujemy w nim jako źródło danych przedstawioną powyżej strukturę (najprościej poprzez Data -> Report Query -> JavaBean Data Source):
Następnie tworzymy Tabelę krzyżową. Pojawia się wizard, w którym mamy możliwość zdefiniowania wszystkich parametrów tabeli. Na początku wybieramy raport z którego nasza tabela będzie korzystała (obiekty, parametry, itd – czyli nasz dokument):
Następnie wybieramy parametr który ma być brany jako kolejne wiersze:
Następnie wybieramy parametr który ma być brany jako kolejne kolumny:
Kolejnym krokiem jest określenie zachowania części z danymi. Tu oprócz pola z danymi podajemy także funkcję która będzie odpowiedzialna za przetworzenie danych w kolumnach/wierszach. Tu najczęściej wykorzystywaną opcją jest suma:
Następnie określamy czy nasza tabela ma mieć kolumnę/wiersz podsumowujący oraz czy chcemy mieć widoczną siatkę pomiędzy polami:
Pozostało tylko zatwierdzić podane powyżej informacje i mamy już gotową tabelę!
Jak to działa?
W wyniku powyższych czynności w iReporcie powstaje standardowy raport z tabelą krzyżową oraz dodatkowa karta właściwości tej tabeli. Tam można podejrzeć wszystkie podane wcześniej ustawienia i je zmodyfikować. Na tej części można także dodać dodatkowe informacje (na przykład zdefiniować kolumny podsumowań jako nazwy brane z Resource Bundle’a).
W jaki sposób zasilić taką tabelę danymi? Otóż jest to osiągane poprzez odpowiednią konstrukcję źródła danych. Jako dane przysyła się zwykłą jednowymiarową listę przedstawionych powyżej obiektów ReportElementDTO, sam Jasper zajmuje się odpowiednim przetworzeniem tej listy. W skrócie działa to tak że z jednowymiarowej listy jest tworzona dwuwymiarowa macierz, przy czym wartości są grupowane poprzez stwierdzenie ‘równości’ danych w odpowiednich property. W przypadku gdy zdefiniowaliśmy ‘columnName’ jako property odpowiadające za nazwę danej kolumny – dane się pojawią w kolejnych wierszach dla tych elementów z listy, które spełniają warunek ‘equals’ na danej wartości ‘columnName’. Analogiczna sytuacja jest w przypadku wierszy (tu odpowiada za to property ‘rowName’). Dodatkowo mozna zdefiniować swój własny sposób porównywania tych wartości, łącznie z kierunkiem sortowania. Logika nakazuje uważać że property ‘value’ odpowiada za wyświetlaną wartość. I tak właśnie jest, należy jednak pamiętać o wykorzystanej funkcji – w moim przypadku dzięki funkcji ‘sum’ pojawią się tu wartości będące sumą wszystkich wystąpień danego elementu. Jak np. na liście źródłowej znajdą się dwa identyczne z punktu widzenia tabeli krzyżowej dane (odpowiednio ‘columnName’ oraz ‘rowName’ są takie same) – wartości ‘value’ będą zsumowane. Poza tą funkcją są dostępne jeszcze inne ciekawe funkcje, choćby ‘count’, która po prostu liczy ilość wystąpień danego elementu.
Aplikacja
W celu zobrazowania możliwości tabel krzyżowych napisałem małą aplikację opartą o Springa. Jest to rozwinięcie poprzedniej aplikacji stworzonej na potrzeby wspomnianego już poprzedniego artykułu o Jasperze. Większość użytych rzeczy jest tam opisana. Aplikacja jest bardzo prosta, jej praca polega na przyjęciu od użytkownika wartości które zostaną następnie użyte do wygenerowania odpowiedniej wielkości tabeli krzyżowej. Całość kodu jaki powstał, łącznie z plikiem szablonu raportu w formacie ‘*.jrxml’ jest dostępny pod tym adresem.
Podsumowanie
Tabela krzyżowa jest stosunkowo prostą konstrukcją, która w miarę przystępny sposób umożliwia definiowanie dynamicznych raportów. Po odpowiednim zaprojektowaniu szablonu jedyną większą trudnością jest właściwe przygotowanie źródła danych. Jak widać jednak z załączonego kodu, całość jest zdecydowanie mniej straszna niż by się wydawało.
Osobną kwestią jest samo narzędzie iReport. Mimo swoich wad jest to bardzo przydatne narzędzie i po pewnej praktyce staje się niesamowicie przydatny. Można w nim bardzo szybko stworzyć szablon raportu który po przekompilowaniu do formatu ‘*.jasper’ staje się gotowym do użycia plikiem. Uważam że iReport jest bardzo dobrym narzędziem do przygotowywania szablonów raportów. Mimo swoich wad bardzo pomaga w procesie tworzenia tych szablonów, dzięki czemu możemy się skupić na tym co tak bardzo lubimy – kodowaniu ;-)














Recent Comments