Code zum Ausgeben eines Textberichts schreiben

In diesem Thema wird ein Beispiel für ein Textberichtsprogramm und einen entsprechenden Handler beschrieben.

Voraussetzungen

Übersicht

Das Programm druckt eine Liste aller Kunden in der SQL-Datenbank mit den aktuellen Beträgen aus.

Im Verlauf des Programms finden die folgenden Ereignisse statt:
  1. Das Berichtsgeneratorprogramm erstellt Variablen, die auf CustomerRecord und textReportHandler basieren.
  2. Der Berichtsgenerator ruft die Funktion start() des Handlers auf.
  3. Die Funktion start() des Handlers erstellt eine Variable, die auf dem TextReport-ExternalType-Abschnitt basiert, und gibt Funktionen für zwei Ereignisse an: onEveryRow und onLastRow. Die Funktion übergibt dann die Steuerung des Berichts mithilfe der Funktion myReport.startReport() an die Textberichtsengine.
  4. Die Funktion myReport.startReport() nimmt keine Änderungen an der Berichtsformatierung vor; daher gibt die Berichtsengine die Steuerung an den Handler und dieser wiederum an den Berichtsgenerator zurück.
  5. Der Berichtsgenerator erstellt mithilfe der EGL-Anweisung open eine Ergebnismenge. Diese Ergebnismenge enthält alle Kunden aus der aktuellen Datenbank.
  6. Der Berichtsgenerator durchläuft die Ergebnismenge in einer Schleife. Für jeden Kunden wird der Kundenname und der Kontostand an die Handlerfunktion output() gesendet.
  7. Der Handler speichert den Kundennamen und den Kontostand in einem Datensatz, auf den alle Funktionen im Handler zugreifen können, und aktualisiert den laufenden Gesamtsaldo.
  8. Der Handler übergibt die Steuerung dann mithilfe der Funktion outputToReport() an die Berichtsengine.
  9. Nach der Ausführung gewisser Verwaltungsaufgaben ruft die Berichtsengine die Funktion onEveryRow() im Handler auf.
  10. Die Handlerfunktion onEveryRow() sendet den Kundennamen in der aktuellen Druckposition, wechselt zur 40. Spalte der Seite, gibt den Kundensaldo aus und sendet einen Rücklauf und einen Formularvorschub an die Berichtsdatei.
  11. Die Steuerung wird an den Berichtsgenerator zurückgegeben, der den nächsten Kundendatensatz zum Verarbeiten sucht. Nach der Verarbeitung sämtlicher Kunden ruft der Generator die Funktion finish() im Handler auf.
  12. Die Handlerfunktion finish() übergibt die Steuerung über die Funktion finishReport() an die Berichtsengine.
  13. Die Berichtsengine sucht eine Funktion für das Ereignis der letzten Zeile und ruft die Funktion onLastRow() des Handlers auf.
  14. Die Handlerfunktion onLastRow() gibt die laufende Summe aus, die vom Handler aktualisiert wurde.
  15. Die Berichtsengine schließt die Berichtsdatei. Die Steuerung wird an den Handler und schließlich an den Generator zurückgegeben, der die Ausführungseinheit beendet.

Kundendatensatz

Das Programm verwendet für den Zugriff auf die SQL-Kundendatenbank den folgenden Datensatz:
record CustomerRecord type SQLRecord
   {tableNames = [["ADMINISTRATOR.CUSTOMER", "L1"]], 
    keyItems = [customerNumber]}

   customerNumber STRING      {column="C_NUMBER", maxLen=6};
   customerName STRING        {column="C_NAME", isSQLNullable=yes, maxLen=25};
   customerAddr1 STRING       {column="C_ADDR1", isSQLNullable=yes, maxLen=25};
   customerAddr2 STRING       {column="C_ADDR2", isSQLNullable=yes, maxLen=25};
   customerAddr3 STRING       {column="C_ADDR3", isSQLNullable=yes, maxLen=25};
   customerBalance MONEY      {column="C_BALANCE", isSQLNullable=yes};
end

Berichtsgenerator

Die Ausführung beginnt mit dem Berichtsgenerator.
package com.companyb.customer;

program reportGenerator type BasicProgram

myCustomer CustomerRecord;
myHandler textReportHandler{};

   function main()
      myHandler.start();  // passes control to handler
      
      // get customer list from database
      open myResults scroll for myCustomer;
      forEach (from myResults)  // loop through results
         myHandler.output(myCustomer.customerName, myCustomer.customerBalance);
      end // forEach  
      myHandler.finish();  // close report
   end
end

Generischer Handler

Der Berichtsgenerator und die Berichtsengine rufen Funktionen des Handlers auf.
package com.companyb.customer;

record reportRecord type BasicRecord 
   customerName STRING;
   customerBalance MONEY;
end

handler textReportHandler type BasicHandler 

myReport TextReport{};   // creates instance
currentReportRecord reportRecord;
runningTotal MONEY = 0;
   
   function start()
      myReport.onEveryRowListener = onEveryRow;
      myReport.onLastRowListener = onLastRow;
      
      // accept defaults on everything but destination file
      myReport.startReport("D:/temp/customerReport.txt",
        null,null,null,null,null,null);
   end
   
   function output(cName STRING in, cBal MONEY in)
      // this information comes from the forEach loop in the main program
      currentReportRecord.customerName = cName;
      currentReportRecord.customerBalance = cBal;
      runningTotal = runningTotal + cBal;
      
      // pass control to the report engine
      // onEveryRow is called
      myReport.outputToReport();  
   end
           
   function finish()
      // pass control to the report engine again
      // onLastRow is called
      myReport.finishReport();
   end
   
   function onEveryRow(myEvent TextReportEvent in)
      myReport.printText(currentReportRecord.customerName);
      myReport.column(40);
      myReport.printText(currentReportRecord.customerBalance);
      myReport.println();
   end
   
   function onLastRow(myEvent TextReportEvent in)
      myReport.println();  // skip a line
      myReport.printText("All customers:");
      myReport.column(40);
      myReport.printText(runningTotal);
   end
end 

Feedback