Just SQL Report - JSR

Egyszerű és hatékony SQL alapú riportkészítés
Ebben a példában egy gyors és hatékony SQL alapú riportkészítési megoldást mutatok be. A riportok HTML, PDF és Excel formátumban is megtekinthetők.

Bár ez az eszköz nem alkalmas minden típusú riport előállítására, éppen ez adja az előnyét: könnyen használható és nagyon gyors, ami a legtöbb gyakorlati esetben teljes mértékben elegendő.

A legtöbb riport master-detail (mester-részlet) típusú, vagyis az adatok jellemzően két szinten jelennek meg. A JSR nevű riportgenerátor azonban akár 5 szintű adathierarchiát is támogat, vagyis a következőt:
master → detail → detail → detail → detail

A módszer lényege, hogy mindössze egyetlen SQL SELECT lekérdezést kell készítenünk, amely tartalmazza a master,s detail, subdetail stb. mezőket. A JSR automatikusan felismeri a különböző adatszintek közötti kapcsolatot, a riport struktúrája alapján.

A működés logikája
A riport egyes részei panelokra (band-ekre) vannak felosztva.
A JSR belső működése azon az elven alapul, hogy két egymást követő, azonos szinten lévő panel nem tartalmazhat teljesen megegyező adatokat. Ez az elv lehetővé teszi, hogy a JSR hatékonyan meghatározza, melyik adat melyik panelban jelenjen meg – anélkül, hogy külön adatcsoportosításokat vagy extra logikát kellene hozzáadnunk.

Lássunk erre egy egyszerű példát.

Users tábla adatai:

ID FirstName LastName Born
1 Johan Wagner 1980-06-02
2 Paul Noringed 1970-01-02
3 Johan Wagner 2001-10-05

Projects tábla adatai azt mutatja, hogy egy user milyen projekkel rendelkezik:

ID ProjName UserID Badzet
1 Slovak Telekom 1 10000,50
2 France Telekom 2 25689,50
3 Deutche Telekom 3 31200,90
4 Pierte Hungary 1 1500,00
5 Cargo Slovakia 2 58000,00
6 Penta Slovakia 1 1567,70

SELECT FirstName, LastName, ProjName, Badzet
FROM Users
LEFT JOIN Projects ON UserID = Users.ID
ORDER BY FirstName, LastName, ProjName

UID FirstName LastName ProjName
3 Johan Wagner Deutche Telekom
1 Johan Wagner Penta Slovakia
1 Johan Wagner Pierte Hungary
1 Johan Wagner Slovak Telekom
2 Paul Noringed Cargo Slovakia
2 Paul Noringed France Telekom

Készítsunk egy egyszerű riportot:

 
[REPORT]
  report="Report Title"
  comment="my comment1"
  comment="my comment2"
  comment="generted: %date %time"

  [band=1] top="20px"
    <fld=FirstName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;" 
    <fld=LastName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;" 
  [summary=1] top="20px" 
    <fld=COUNT(FirstName)> prefix="Users: " width="195" style="border: 2px solid gray; text-align:center;" <column=Summary> style="font-weight:bordel;height:25px;" 

[SQL]
  SELECT FirstName, LastName 
  FROM Users
  ORDER BY FirstName, LastName

	

jsr1 Ebben a riportban érdemes észrevenni, hogy két azonos nevű felhasználó van, ami két különböző embert jelöl, más születési dátummal, de a születési dátumot, nem akarjuk megjeleníteni, mert bizalmas információ. Itt ez még nem jelent gondot, mivel ennek a panelnak (band=1) nincs kapcsolata más alárendelt panellal, ezért a riport nem ellenőrzi azt, hogy ugyanazok az adatok jelennek meg azonos panelban. A következő, lenti példában viszont már más lesz a helyzet.


Egy master-detail riport a userek projektjeivel:

 
[REPORT]
  report="Report Title"
  comment="my comment1"
  comment="my comment2"
  comment="generted: %date %time"
  
  [band=1] top="20px"
    <fld=@UID>
    <fld=SERIAL()> width="30" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;" 
    <fld=FirstName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;" 
    <fld=LastName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;" 
   
  [band=2] top="-1px" left="10px" 
    <fld=SERIAL()> width="30" <column=N.> style="font-weight:normal;"
    <fld=ProjName> width="150" style="text-align:center; color:navy;"   <column=Project> style="font-weight:normal;" 
    <fld=ROUND2(Bt)> width="150" sufix=" €" <column=Badzet> style="font-weight:normal;" 

  [summary=2] top="10px" left="10px"
    <fld="..."> width="30"  style="border: 2px solid silver";
    <fld=COUNT(ProjName)> prefix="Projects: " width="148" style="border: 2px solid silver; text-align:center;";
    <fld=ROUND0(SUM(Bt))> prefix="Badzet ∑: " width="149" style="border: 2px solid silver"; sufix=" €"
   
  [summary=1] top="20px" left="0px"
    <fld=COUNT(UID)> prefix="Users: " width="95" style="border: 2px solid gray; text-align:center;" <column=Summary> style="font-weight:bordel;height:25px;" colspan="3"; 
    <fld=COUNT(ProjName)> prefix="Projects: "  width="95" style="border: 2px solid gray; text-align:center;" 
    <fld=ROUND0(SUM(Bt))> prefix="Badzet ∑: " width="150" style="border: 2px solid gray;" sufix=" €"
   
[SQL]
  SELECT Users.ID as UID, FirstName, LastName, Badzet as Bt
  FROM Users
  LEFT JOIN Projects ON UserID = Users.ID
  ORDER BY FirstName, LastName, ProjName
	
	

jsr2 Ebben a reportban 2 panelban (band=1, band=2) jelennek meg az adatok. Mindkét panelnak van egy összegző panelja is (summary=2, summary=1).
A adatok megjelenitetésének dizajnját a stílus adja meg, ami azonos a jól ismert a HTML stílussal.
Ebben a példában minden mezőnek megvan adva a stílusa, amit természetesen egyszerűsíteni lehet class hivatkozással, a gyakran használt stílusok számára.

Egyetlen fontos dolog, amit észre kell venni a <fld=@UID>, ami egy olyan mezőre hivatkozik, amit nem akaruk megjeleníteni (not visible: @FieldName), de mégis fontos, mert ennek alapján a riport megtudja különböztetni a két azonos nevű felhasználót, hogy két különböző személyről van szó.

Ha ezt sort <fld=@UID> kihagynánk, akkor a riport nem tudná megkülönböztetnia két azonos nevű felhasználót és az alábbi módon jelennénk meg ez az adatok:

jsr3 Itt fontos észrevenni, hogy a riport nem az SQL adataira támaszkodik, hanem azokra az adatokra, amikre hivatkozást adunk a riportnak fld mezőben. Csak ezeket az adatokat figyeli és csak ezeken az adatokon lehet megszámlálást COUNT(...) és összegzést SUM(...) végrehajtani az összegző panelban. Tehát a summarizációs panelban csak olyan mezők szerepelhetnek, melyek szerepeltek az adott panelban is, melyeket átadtunk a riportnak.

Szintén nagyon fontos az adatok sorbarendezése. Ha az datok nincsenek megfelelően sorbarendezve (order by), akkor a riport nem tudja helyesen felismerni, hogy az adatok hová tartoznak, melyik panelba kell tenni őket.

A JSR program értékelése
A JSR program használata egyszerű, futása gyors és a riportnak csak egy kis része foglalja a memóriát, mivel folyamatosan fájba töténik a riport kimentése. Ezért alkalmas nagy terjedelmű riportok generálására, HTML, PDF, EXCEL formátumban és lehetőséget nyújt a vonalkód megjelenitésre is.
Hátránya, hogy logikájából következően nem általános és bizonyos adatelőkészítést vagy operációkat az adatbazis szintjén (vagy a SQL lekérdezés szintjén) kell elvégezni.
Természetesen ha a JSR egy programozási nyelvbe van ágyazva (pl. Go, Delphi, Python, Java), mint komponens, akkor a számítási lehetőségek nagyban kibővülnek és composite report készítésre is alkalmas lehet.