Scripting Zwischensumme am Ende einer Seite und Übertrag auf nächste Seite

Aus SAP-Wiki
Zur Navigation springenZur Suche springen

Siehe JavaScript und FormCalc Scripting im LiveCycle Designer.

Ein häufig geäußerter Wunsch an die Formularentwickler ist es, wenn die Zwischensumme einer Tabelle am Ende einer Ausgabeseite aufgeführt werden soll.

Das ist technisch nicht einfach zu realisieren, da im Druckprogramm und Kontext diese Information noch nicht zur Verfügung stehen kann. Sie entscheidet sich erst zur Laufzeit der Formularausgabe, bzw. wenn das Formular gerendert ist und daher muss für diese Aufgabenstellung Scripting (JavaScript oder FormCalc) verwendet werden.

Siehe Masterseite, Inhaltsbereich, Inhaltsseite, Ausgabeseite und Paginierung.

Anwendung mit Zwischensumme und Übertrag

In der nachfolgenden Projektanwendung war die Aufgabenstellung am Ende einer Ausgabeseite eine Zwischensumme auszugeben und am Anfang der nächsten Seite ein Übertrag (identisch mit der Zwischensumme der Vorseite).

Für diese Anwendung wurden verschiedene Scriptingtechniken und Funktionen des LiveCycle Designers bezüglich der Tabellenausgabe kombiniert. Es lohnt sich, dieses Zusammenspiel zu verstehen. Dieses Verständnis kann in vielen späteren Aufgabenstellungen bei der Formularentwicklung nützlich sein.

  • Darstellung einer Kopfzeile nur auf der ersten Tabellenseite.
  • Darstellung einer (anderen) Kopfzeile auf allen Tabellenausgabeseiten mit Ausnahme der ersten Tabellenseite.
  • Darstellung einer Fußzeile auf allen Tabellenausgabeseiten mit Ausnahme der letzten Tabellenseite, zur Ausgabe der Zwischensummen der Tabelle.
  • Darstellung einer (anderen) Fußzeile nur auf der letzten Tabellenausgabeseite, mit Ausgabe u. a. des Gesamtbetrags der Tabelle nur auf der letzten Tabellenausgabeseite.
  • Auslesen in einer Scriptingschleife alle Felder einer Seite und Summierung der Werte einer Spalte mit der Speicherung in einer lokalen Variable, um sie in das Zwischensummenfeld der Tabelle zu übertragen.
  • Nutzung einer globalen Variable zur Zwischenspeicherung Zwischensumme und Übertrag auf lokale Variablen/Felder.

Formularausgabe

Auf der ersten Tabellenausgabeseite gibt es noch keinen "Übertrag", aber die "Zwischensumme".

Uebertrag1.JPG


Auf der zweiten Seite und allen nachfolgenden Seiten, auf der die Tabelle ausgegeben wird, wird die Zwischensumme der vorherigen Seite im Kopfbereich der Tabelle als „Übertrag“ angezeigt.

Uebertrag2.JPG

...

Uebertrag3.JPG


Ausnahme die letzte Seite der Tabellendarstellung. Da gibt es zwar noch den Übertrag, aber keine Zwischensumme mehr, sondern die Gesamtsumme der Tabelle.

Uebertrag4.JPG

Globale Variable definieren

Es wird eine globale Variable definiert, mit denen man sehr einfach Werte formularweit speichern kann.

In diesem Fall speichert die Variable den aufsummierten Übertragswert. Während ein Feld den Feldwert in der Eigenschaft „rawValue“ speichert, speichert eine globale Variable den Wert in der Eigenschaft „value“.

Uebertrag11.JPG


Im Menü des LiveCycle Designers „Bearbeiten - Formulareigenschaften“ und hier auf dem Reiter „Variablen“ wird die globale Variable "TransferSum" angelegt. Sie ist initial leer oder könnte den Wert „0“ haben.

Uebertrag10.JPG


Im Hierarchiebaum des LiveCycle Designers wird sie unter „Variablen“ mit dem Namen „TransferSum“ angezeigt.

Uebertrag9.JPG

Kopfzeilen Tabelle definieren (Überschrift und Übertrag)

Hier gibt es 2 Kopfzeilen der Tabelle DOC_AMOUNTS vom Typ Kopfzeile. Einmal "Kopfzeile" und dann "Kopfzeile_ff".

Uebertrag5.JPG


Die zweite Kopfzeile "Kopfzeile_ff" unterscheidet sich von "Kopfzeile" durch die Überschrift „Übertrag“ und den Übertragswert. Dieser Übertrag soll nur auf nachfolgenden Seiten dargestellt werden und nicht auf der ersten Ausgabeseite der Tabelle.

Uebertrag6.JPG


Die Kopfzeilen haben auf der Palette "Objekt" die Registerkarte "Paginierung".

Bei der Kopfzeile „Kopfzeile“ wird nun "Kopfzeile in erster Seite einschließen" markiert, aber nicht "Kopfzeile in aufeinander folgenden Seiten". Diese Kopfzeile wird also nur einmalig auf der Seite ausgegeben, an der die Tabellendarstellung beginnt.

Uebertrag7.JPG


Bei der Kopfzeile "Kopfzeile_ff" ist es genau umgekehrt.

Hier wird "Kopfzeile in erster Seite einschließen" nicht markiert, aber dafür "Kopfzeile in aufeinander folgenden Seiten".

Uebertrag8.JPG

Fußzeilen Tabelle definieren (Zwischensumme und Endbetrag)

Hier gibt es 2 Fußzeilen der Tabelle DOC_AMOUNTS vom Typ Fußzeile. Einmal "Zwischensumme" und dann "Fußzeile".

Uebertrag18.JPG


Uebertrag21.JPG


Diese beiden Fußzeilen werden sehr ähnlich zu den 2 Kopfzeilen entweder am Ende jeder Tabellenseite (mit Ausnahme der letzten Tabellenseite) oder nur auf der letzten Tabellenausgabeseite dargestellt.

Fußzeile "Zwischensumme". Hier wird die Checkbox „Fußzeile in aufeinander folgenden Seiten“ aktiviert.

Uebertrag19.JPG


Fußzeile "Fußzeile" mit Endbeträgen. Nun ist die Checkbox „Fußzeile in letzte Seite einschließen“ aktiviert.

Uebertrag20.JPG


Uebertrag22.JPG

Bei den Endbeträgen ist es nicht nötig mit Scripting zu arbeiten. Diese Daten können bereits im Druckprogramm bestimmt werden und die Felder binden daher auf entsprechende Objekte im Kontext.

$.TEXTE.TXT_TOTAL_AMOUNT
$.GS_SUMNET.SUMNET
$.GS_SUMNET.SUMBTR
$.GS_SUMNET.SUMSKT

Zwischensumme berechnen und ausgeben (Schleife Inhalte Vorseite)

Es wird eine neue Zeile "Zwischensumme" zur Tabelle hinzugefügt vom Typ "Fußzeile".

Uebertrag12.JPG

Uebertrag14.JPG


Entscheidend ist hier v. a. das Feld "Subtotal_NETTOEUR", in dem der Zwischensummenwert dargestellt wird.

Uebertrag15.JPG


In der Zeile gibt es nur einen Text "Zwischensumme" und den Zwischensummenwert.

Uebertrag13.JPG


Im Data-Knoten von DOC_AMOUNTS wird die Tabelle durchlaufen, inklusive dem Feld „WNETT“ (Nettowert von Lastschriften).

Uebertrag16.JPG

Coding

Beim Feld der Zwischensumme „Subtotal_NETTOEUR“ wird nun beim Event "calculate" der Zwischensummenwert mit JavaScript berechnet. Wichtig ist hier nicht das Event „initialize“ zu verwenden, da zu diesem Zeitpunkt die Formularseite noch nicht gerendert wurde und somit nicht bekannt ist, welche Data-Zeilen auf einer Seite ausgegeben werden. Beim Event „calculate“ ist die Formularseite bereits gerendert.

Es werden im Scripting alle Felder der Seite durchlaufen. Aber nur die Feldwerte vom Feld „WNETT“ werden in einer lokalen Variable „total“ summiert durch die If-Bedingung „if (fields.item(i).name == "WNETT")“, und schließlich im eigenen Feld ausgegeben, sowie der globalen Variablen „TransferSum“ zugewiesen.

data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Zwischensumme.Subtotal_NETTOEUR::calculate - (JavaScript, client)
//Beim Ereignis Calculate können Werte in Abhängigkeit von anderen Variablen des Formulars gefüllt werden. Das Formular ist fertig gerendert und die Seitenumbrüche sind somit bekannt, bzw. welche Inhalte auf welcher Seite sind. 

//Der Seiteninhalt der Felder der Vorseite wird einer Variablen „fields“ zugewiesen   
var fields = xfa.layout.pageContent(xfa.layout.page(this)-1, "field", 0);
 
//Initialisierung der Berechnungsvariablen für die Summe eines Feldes der Seite  
var total = 0;  

//Addition der Werte vom Feld WNETT der aktuellen Seite
//Schleife über alle Felder der Seite
for (var i=0; i <= fields.length-1; i++)                   
{      //Abfrage auf das Tabellenfeld WNETT
	if (fields.item(i).name == "WNETT")                 
	{  //Die Summe aller Werte vom Tabellenfeld WNETT wird gebildet
	   total = total + fields.item(i).rawValue;    
	}
}
 
//Die berechnete Summe der Seite wird addiert mit dem vorhergehenden Übertragswert in der globalen Variablen „TransferSum“. Dessen Wert wird mit „value“ angesprochen 
this.rawValue = parseFloat(total) + parseFloat(TransferSum.value);
 
//Die ermittelte Summe wird wieder der globalen Variable zugewiesen   
TransferSum.value = this.rawValue;

Übertrag füllen aus der Zwischensumme

Im Event "calculate" des Übertragfeldes in der Überschrift (bei nachfolgenden Tabellenseiten) wird das Ergebnis der Zwischensumme übernommen.

Das Coding:

data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Kopfzeile_ff.NETTOEUR::calculate - (FormCalc, client)
data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Kopfzeile_ff.NETTOEUR = data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Zwischensumme.Subtotal_NETTOEUR

sollte identisch sein mit:

data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Kopfzeile_ff.NETTOEUR::calculate - (FormCalc, client)
$.rawValue = data.MAIN.BODY.AMOUNTS_TAB.DOC_AMOUNTS.Zwischensumme.Subtotal_NETTOEUR.rawValue

Funktion parseFloat

Mit der globalen Funktion "parseFloat" wird eine Zeichenkette als Zahl interpretiert, damit die Addition explizit Zahlen addiert und nicht Zeichenketten aneinander fügt.

Siehe https://www.mediaevent.de/javascript/string-zu-zahl.html.

Siehe Scripting String-Operationen.

Zugriff auf andere Seiten als aktuelle Seite

Es kann nicht nur auf die aktuelle Seite zugegriffen werden im Coding, sondern z. B. auch auf die Vorseite (in Bezug zur aktuell ausgegebenen Seite).

Dies ist häufig sinnvoll, da man sich nach einem Seitenwechsel für die Inhalte der Vorseite interessiert.

xfa.layout.page(this)-1

Zwei und mehr Übertragsfelder im Event „calculate“

  • In einem anderen Kundenformular war die Anforderung 3 Übertragssummen am Ende einer Seite anzuzeigen. Bruttobetrag, Nettobetrag und Steuerbetrag.
  • Dies hat sich als schwieriger herausgestellt als gedacht. Sofern die Übertragsfelder auf jeder Übertragsseite erneut den kompletten Inhalt des Formulars (bis zur Vorseite) einlesen, hat das Coding die korrekten Ergebnisse gebracht, aber bei großen Ausgabedateien wurde die Geschwindigkeit der Formularausgabe massiv beeinträchtigt - bis hin zum Abbruch der Formularausgabe aufgrund eines Timeouts im ADS bei über 1000 Rechnungspositionen, bzw. ab ca. 35 Ausgabeseiten des Formulars.
  • Wenn die Übertragungsfelder globale Variablen nutzen, hatte es den Effekt, das das Coding des einen Übertragfeldes eine Rückwirkung auf das Ergebnis der anderen Übertragfelder hatte. Alle Übertragsfelder auf der ersten Übertragsseite wiesen einen zu hohen Wert aus. Die Folgeseiten rechneten (unter Beibehaltung des Folgefehlers) korrekt, aber konnten aufgrund der fehlenhaften Werte auf der ersten Übertragsseite nicht genutzt werden.
  • Offensichtlich wurde durch das erneute Einlesen des Seiteninhaltes von jedem Scripting-Code zu oft das Ereignis „calculate“ (auch bei anderen Knoten) ausgelöst.
  • Nach hartem Kampf konnte das Problem gelöst werden, indem das JavaScript-Coding nur in einem Übertragsfeld berechnet wurde. Aber es wurden lokale Variablen gefüllt, die in Abhängigkeit von einer der 3 Tabellenwerte (Bruttobetrag, Nettobetrag, Steuerbetrag) abfragen. Zur Addition über mehrere Ausgabeseiten hinweg wurden nun statt globaler Variablen Funktionen genutzt. Die Berechnung der 3 Übertragsfelder erfolgt lediglich in einem Scriptingcode und 3 Funktionen.
  • Siehe help.adobe.com: calculate event (EN) und help.adobe.com: Sum in calculation event.

Hier gibt es 3 Übertragsfelder zur Anzeige der Summe vom Nettobetrag (NETWR), vom Mehrwertstseuerbetrag (MWSBK) und vom Bruttobetrag (GROSS).

Uebertragsfelder1.JPG

Bei einem Seitenumbruch, der durch die Ausgabe der Tabelle ausgelöst wird, wird das Teilformular "scr_Item_Fuss" ausgegeben.

Uebertragsfelder4.JPG


Dieses Teilformular "scr_Item_Fuss" wird aber nicht auf der letzten Seiten ausgegeben.

data.BODY.scr_Item_Fuss::ready:form - (JavaScript, both)
if (xfa.layout.page(this) == xfa.layout.pageCount())
 {
 this.presence = "hidden";
 }


Uebertragsfelder2.JPG

Das Scripting zur Berechnung der Übertragsfelder befindet sich im Feld scr_UebNETWR.

data.BODY.scr_Item_Fuss.Uebertrag.scr_UebNETWR::calculate - (JavaScript, both)
var lo_fields = xfa.layout.pageContent(xfa.layout.page(this)-1, "field", 0);

var lv_wert_netwr = 0;

var lv_wert_mwsbk = 0;

var lv_wert_gross = 0;

//Addition der Werte vom Feld "NETWR" der aktuellen Seite
for (var s=0; s <= lo_fields.length-1; s++)                        //Schleife über alle Felder der Seite 
{
  if (lo_fields.item(s).name == "NETWR")                           //Abfrage auf Feld für den Nettowert
    {
      lv_wert_netwr = lv_wert_netwr + lo_fields.item(s).rawValue;  //Summe Werte Feld
     }
	
	
  if (lo_fields.item(s).name == "MWSBK")                           //Abfrage auf Feld für den Mehrwertsteuerbetrag
    {
      lv_wert_mwsbk = lv_wert_mwsbk + lo_fields.item(s).rawValue;  //Summe Werte Feld
    }	
	
		
  if (lo_fields.item(s).name == "GROSS")                           //Abfrage auf Feld für den Bruttobetrag
    {
      lv_wert_gross = lv_wert_gross + lo_fields.item(s).rawValue;  //Summe Werte Feld
    }			
}

//Zuweisung Rückgabewert Funktion an Übertragsfelder Steuerbetrag und Bruttobetrag.
scr_UebGROSS.rawValue = Main.FunktionGROSSAdd(lv_wert_gross);
scr_UebMWSBK.rawValue = Main.FunktionMWSBKAdd(lv_wert_mwsbk);

//Zuweisung Rückgabewert Funktion an Übertragsfeld Nettobetrag.
this.rawValue = Main.FunktionNETWRAdd(lv_wert_netwr);

Die Funktionen zur Addition der vorhergehenden Werte vom Nettobetrag, dem Mehrwertsteuerbetrag und dem Bruttobetrag sind im Skriptobjekt "Main", mit den Funktionnamen "FunktionNETWRAdd", "FunktionMWSBKAdd" und "FunktionGROSSAdd".

Uebertragsfelder3.JPG

data.#variables[0].Main - (JavaScript, client)
function FunktionNETWRAdd(Parameter1) 
{  //Wenn statische Variable noch nicht definiert ist, initialisiere sie
  //s. a. https://stackoverflow.com/questions/27509/detecting-an-undefined-object-property
  if ( typeof counter_netwr == 'undefined' )
   {
      counter_netwr = 0;
   }
   
  //Erhöhe den Gesamtwert um den Wert der jeweiligen Ausgabeseite
   counter_netwr = counter_netwr + Parameter1;
   
return counter_netwr;   //Rückgabeparameter mit Gesamtwert inklusive jeweils letzter Ausgabeseite
}


function FunktionMWSBKAdd(Parameter1) 
{  //Wenn statische Variable noch nicht definiert ist, initialisiere sie
  if ( typeof counter_mwsbk == 'undefined' )
   {
      counter_mwsbk = 0;
   }
   
  //Erhöhe den Gesamtwert um den Wert der jeweiligen Ausgabeseite
   counter_mwsbk = counter_mwsbk + Parameter1;
   
return counter_mwsbk;   //Rückgabeparameter mit Gesamtwert inklusive jeweils letzter Ausgabeseite
}


function FunktionGROSSAdd(Parameter1) 
{  //Wenn statische Variable noch nicht definiert ist, initialisiere sie
  if ( typeof counter_gross == 'undefined' )
   {
      counter_gross = 0;
   }
   
  //Erhöhe den Gesamtwert um den Wert der jeweiligen Ausgabeseite
   counter_gross = counter_gross + Parameter1;
   
return counter_gross;   //Rückgabeparameter mit Gesamtwert inklusive jeweils letzter Ausgabeseite
}

Web-Links