Der Chatbot hilft Ihnen bei Fragen rund um das Produkt und die Anpassbarkeit der Software. Wie bei allen AI-generierten Daten sollten die Antworten bei kritischen Informationen verifiziert werden. Nehmen Sie dafür gerne Kontakt mit uns auf. Weitere Informationen zur Verarbeitung der Chat-Daten bieten wir auf der Datenschutzseite.
Die besten Antworten liefert der Chatbot, wenn Ihr Input möglichst viele Informationen enthält. Zum Beispiel:
«Welche Apps stehen im Vertec Cloud Abo zur Verfügung?»
Aktualisiert: 22.01.2024
|
Neue Context-Variable project, phase und opportunity ab Vertec 6.7.0.6.
Dieser Artikel gilt für Vertec Versionen ab 6.5.0.20. Eine Beschreibung für ältere Versionen finden Sie hier. Was sich im Vergleich zu den vorherigen Versionen geändert hat, finden Sie im Artikel Python-Code für Office-Berichte Vorher - Nachher.
Der Dateninhalt eines Office-Berichts wird berechnet durch Python-Code, welcher als Berichts-Definition hinterlegt ist:
Wie dieser Code genau aufgebaut wird, ist hier nachfolgend detailliert beschrieben.
Die Datenlogik eines Office-Berichts basiert auf einer Hierarchie von sogenannten Tables.
Für jede Klasse, die angezeigt werden soll (Projekt, Bearbeiter, Leistungen etc.), wird eine Table angelegt.
Eine Table hat Datenfelder und kann Sub-Tables haben.
Die einzelnen Objekte sind dann die "Zeilen" einer solchen Table: Für jedes Objekt (einzeln oder in der Liste, auf der der Bericht ausgeführt wird) wird zu Laufzeit eine Zeile (row) angelegt.
Jedes Band in Word oder Excel verweist auf eine Table. Die innerhalb des Bands verwendeten Variablen verweisen auf die Felder.
Tables
Eine Tabelle wird wie folgt deklariert:
className(Table):
Der Name kann frei gewählt werden, muss aber innerhalb der Berichtsdefinition eindeutig sein.
# Beispiel eines minimalen Projekt-ReportsclassProjekt(Table):
businessclass = "Projekt"
Auf dieser Table wurden (noch) keine eigenen Felder definiert. Für diese Objekte stehen also einfach alle normalen Vertec-Member zur Verfügung, wie sie auch über OCL verfügbar sind.
Damit der Aufruf der Vertec-Member im Bericht funktioniert, muss die Table einer eindeutigen Businessklasse (Projekt, Projektbearbeiter, Adresseintrag etc.) zugeordnet werden. Diese wird in der Deklaration der Table mittels businessclass= angegeben.
Anmerkung: Wird keine Businessclass angegeben, werden die Werte einfach als Strings ausgegeben. Das funktioniert für einfache Anzeigen, gerechnet werden kann damit aber nicht. Wir empfehlen deshalb, die Businessclass immer anzugeben.
Die Haupttabelle (main_table)
Es gibt immer eine Haupttabelle, von der alles ausgeht. Diese Haupttable wird vom System dadurch identifiziert, dass sie nicht Subtable ist von einer anderen Table.
Werden mehrere Tables verwendet, die keine Übertabelle haben, muss eine davon als Haupttabelle gekennzeichnet werden. Das geschieht mit der Variable main_table:
classProjekt(Table):
businessclass = "Projekt"
main_table = Projekt
Sub-Tables zuweisen (TableField)
Die Zuweisung einer Table als Sub-Table erfolgt über eine Feld-Deklaration. Das genaue Vorgehen ist im Abschnitt Table-Felder (Subtables) beschrieben.
calculate_main_table
Alle Tables ausser der Haupttabelle (main_table) werden als Feld in einer anderen Table angegeben und dabei eine Berechnung mitgegeben. Bei der Haupttabelle, der main_table, ist das nicht so. Dort wird einfach die Liste (rootlist) übergeben, auf der der Bericht ausgeführt wird (ausgeführt auf einem einzelnen Objekt ist das eine Liste mit einem Eintrag).
Möchte man die Haupttabelle vorberechnen (zum Beispiel, um eine Liste zu filtern oder zu sortieren), kann dies mit der Methode calculate_main_table geschehen. Diese gibt es in 2 Varianten:
calculate_main_table ist eine Funktion calculate_main_table ist eine Funktion, welche ein Context-Objekt enthält und eine Table Instanz des richtigen Typs zurückgeben soll. Signatur der Funktion ist calculate_main_table(context), Rückgabewert ist eine Table Instanz.
Beispiel: Der Bericht ist auf einer Liste von Projekten registriert. Sie soll nach Projektcode sortiert werden.
defcalculate_main_table(context):
projektlist = context.rootlist.evalocl("self->orderby(code)")
# Hier können Berechnungen gemacht werdenreturnProjekt(context, projektlist)
calculate_main_table ist ein String calculate_main_table ist ein String. Dieser wird als OCL Expression ausgewertet und muss eine Liste ergeben. Die Expression wird auf der ursprünglichen Liste des Berichts ausgewertet. Beispiel, wie oben, aber als Expression:
self referenziert dabei die übergebene Rootlist. Diese weiss selbst nichts vom Typ ihrer Objekte, deshalb muss diese angegeben werden (.oclAsType(Klasse)).
SingleRowTable (Rahmen für Listenberichte)
Sollen die Objekte einer Liste nicht pro Objekt, sondern in einer Liste angezeigt werden, muss eine übergeordnete Bericht-Tabelle erzeugt werden, welche den Rahmen für die Liste bietet, selbst aber kein Objekt hat.
Dafür kann die Haupttabelle als SingeRowTable deklariert werden. In einer solchen Tabelle wird vom System automatisch genau eine row erzeugt, welche die Liste dann als Subtable enthalten kann.
Auch die SingleRowTable kann bei Bedarf via calculate_main_table vorberechnet werden. Sie hat die gleichen Eigenschaften wie die normale Table, wertet aber kein OCL aus. Es können darauf also keine OCL Felder angelegt und auch die Context-Variablen nicht via OCL verwendet werden, da es kein Objekt gibt, auf dem die Expressions ausgewertet werden könnten.
initialize_row
Für alle Objekte, für die der Bericht ausgeführt wird, wird eine "Zeile" der Table angelegt. Eine Zeile heisst row.
Auf der Tabelle gibt es die Methode initialize_row, um die Objekte zu initialisieren. Darin können Berechnungen gemacht, Felder gefüllt und Context-Variablen gesetzt werden. Die Syntax lautet wie folgt:
definitialize_row(context, row):
Diese Methode wird automatisch für jedes einzelne Objekt aufgerufen.
Tables können auch im Code aufgebaut werden. Dies wird dann benötigt, wenn verschiedene Objekte dargestellt werden sollen, welche nicht zur gleichen Businessklasse gehören, und also nicht automatisch berechnet werden können.
Dafür steht auf der Tabelle eine add_row Methode zur Verfügung, welche ein zeilenweises Aufbauen der Tabelle erlaubt. Die auf der Tabelle definierten Felder stehen als Eigenschaften des row-Objektes zur Verfügung.
Die Anzahl der Objekte einer Tabelle kann über len(table) eruiert werden.
Felder
Als Datenfelder werden die normalen Vertec-Member verwendet. Diese können einfach in der Berichtsvorlage referenziert werden, ohne dass es eine Feld-Deklaration braucht im Code (siehe Office-Berichte - Felder).
Zusätzlich können weitere Felder deklariert und z.B. mit Berechnungen gefüllt werden.
Feld-Typen
Es gibt zwei Arten von Feldern: OCL Felder und einfache Felder. Die OCL Felder berechnen ihren Wert über eine OCL Expression. Bei den einfachen Feldern muss der Inhalt manuell bzw. mit einer Python Funktion abgefüllt werden.
Felder
OCL Felder
Beschreibung
TextField
OclTextField
Stellt einen String-Wert dar
CurrencyField
OclCurrencyField
Stellt eine Fixkomma Zahl dar, wird üblicherweise für Geld-Beträge verwendet. Formatierung gemäss Ländereinstellung.
IntegerField
OclIntegerField
Stellt eine Ganzzahl dar
MinuteField
OclMinuteField
Stellt einen Integer-Wert als Minuten dar. Formatierung gemäss Einstellungen in Vertec.
BooleanField
OclBooleanField
Stellt einen Wahr/Falsch Wert dar
DateField
OclDateField
Stellt ein Datum dar
DateTimeField
OclDateTimeField
Stellt ein Datum mit Zeitanteil dar
ImageField
OclImageField
Stellt ein Bild dar
TableField
OclTableField
Enthält als Wert eine Subtable. Table-Fields erlauben die Darstellung von hierarchischen Datenstrukturen.
OCL Felder
OCL Felder enthalten als ersten Parameter den Feldnamen (der in der Berichtsvorlage referenziert wird), sowie als zweiten Parameter eine OCL Expression für die Berechnung:
Das Resultat der Expression muss vom Datentyp sein, für welchen das Feld deklariert wurde (OclTextField = String, OclIntegerField = Ganzzahl etc.).
Der zweite Parameter ist optional. Entspricht er dem ersten Parameter (z.B. OclTextField("code", "code"), kann er weggelassen werden oder das Feld direkt im Bericht referenziert werden, ohne dass dafür überhaupt ein Feld deklariert werden muss.
Einfache Felder
Einfache Felder (ohne Ocl-Präfix) enthalten ebenfalls als ersten Parameter den Feldnamen:
CurrencyField("offeneLeistungen")
Ohne weitere Angaben stellen diese nicht automatisch berechnete Felder dar, welche beim Berechnen der Table im Code manuell mit Werten gefüllt werden können, zum Beispiel in einem initialize_row:
Name der Table: Das erste Argument enthält wie immer den Namen, mit welchem im Bericht auf dieses Subset zugegriffen werden kann, beispielsweise als Band-Expression.
Name der Table-Deklaration: Mit dem zweiten Argument wird die entsprechende Table-Deklaration übergeben:
Berechnung. Das dritte Argument ist optional und kann wie folgt verwendet werden:
OCL Expression: Mit dem dritten Argument wird angegeben, wie der Inhalt der Sub-Table berechnet wird.
Falls die Berechnung per OCL Expression erfolgt (Deklaration mit Präfix Ocl: OclTableField), muss das Ergebnis der Expression eine Liste von Businessobjekten sein, welche der Table Deklaration entsprechen.
Falls die OCL Expression dem Namen der Table entspricht, so kann diese weggelassen werden. Der Bericht Mechanismus verwendet so den Namen als OCL Expression:
OclTableField("offeneLeistungen", "Leistung")
Python Funktion: Falls die Berechnung per Python Funktion erfolgt (Deklaration ohne Präfix Ocl: TableField), muss die Funktion eine Liste von Businessobjekten zurückgeben, welche der Table Deklaration entsprechen.
context.table
In der Berechnungsfunktion eines Table Fields (3. Argument als Python Funktion) steht ein resultierendes Table Objekt als context.table zur Verfügung. Damit kann auf eine bereits angelegte Table zugegriffen werden, was das Anlegen einer Row via context.table.add_row() ermöglicht.
# Projektliste mit LeistungenclassLeistung(Table):
fields = [
IntegerField("einwert"),
]
classProjekt(Table):
fields = [
TableField("leistungen", Leistung, "calc_leistungen"),
]
defcalc_leistungen(context):
for l in context.evalocl("offeneleistungen"):
row = context.table.add_row(l)
row.einwert = 1234
Manueller Aufbau: Tables können auch von Hand erstellt und gefüllt werden. Ist dies der Fall, kann das dritte Argument weggelassen werden:
TableField("offeneLeistungen", "Leistung")
Das Context-Objekt
Jeder Berechnung im Rahmen der Bericht-Generierung wird das Context-Objekt mitgegeben. Dieses wird so durch alle Berechnungsfunktionen durchgeschlauft und hat folgende Eigenschaften:
context.evalocl
Das Context-Objekt verfügt über die Methode evalocl(<expression>), welche eine OCL Expression auf dem aktuellen Objekt auswertet.
context.evalocl("offeneLeistungen.wertext->sum")
Als optionales zweites Argument neben der Expression kann ein Objekt oder eine Liste übergeben werden. In diesem Fall wird die Expression auf das übergebene Objekt bzw. Liste angewendet.
Mit der Methode context.translate(text) können Texte gemäss Bericht-Sprache (context.language) übersetzt werden.
Der im Code zuletzt gesetzte Wert von context.language wird zur Übersetzung der Texte in der Berichtsvorlage verwendet.
Wird ein unbekannter Sprachcode eingegeben, dann werden die originalen Texte angezeigt. Der Bericht wird also einfach nicht übersetzt.
Übersetzungen von MLString-Feldern
Dieses Übersetzungssystem funktioniert nicht für MLString-Felder, da diese einen anderen Übersetzungsmechanismus haben. Welches MLString-Felder sind und wie diese übersetzt werden, finden Sie im Artikel über die Mehrsprachigkeit mit Vertec beschrieben.
Möchte man solche Begriffe in Office-Berichten übersetzen, muss man auf die OCL-Methode .asstringbylanguage zurückgreifen:
Mögliche Sprachen/Parameter sind 'DE', 'DD' (ab 6.5.0.9), 'FR', 'IT', 'EN' oder 'NV'. Eine Unterscheidung nach Jargon ist bei MLString-Feldern nicht möglich.
Mit context.language[:2] eruiert man die ersten zwei Zeichen des bestehenden Language-Attributs. Da in Berichten die Sprache standardmässig immer mit dem Jargon-Suffix hinterlegt ist (DE0..), und dies bei MLString-Feldern nicht möglich ist (siehe oben), erreicht man so die Übersetzung in die aktuelle Berichts-Sprache.
Context-Variablen
Die folgenden Variablen sind in jedem Bericht definiert:
container
Der Container, auf dem der Bericht ausgeführt wurde.
comment
Ab Version 6.6.0.9. Enthält den Kommentar aus dem Druck-Dialog.
currentobject
Das jeweils aktuelle Objekt der Berechnung.
context.currentobject
currentdate
Das heutige Datum, ohne Zeitteil. context.currentdate
language
Diese Variable enthält die Bericht-Sprache (Oberflächensprache oder Projektsprache, falls Übersetzung aktiviert).
Sie kann auch gesetzt werden, um den Bericht in einer anderen Sprache auszugeben:
context.language="IT"
Es kennt folgende Werte:
– DE: Deutsch (Schweiz)
– DD: Deutsch (Deutschland)
– EN: Englisch
– FR: Französisch
– IT: Italienisch
Soll ein Jargon berücksichtigt werden (Projekt- oder Mandatssprache), dann kann zusätzlich der Suffix 0 (für Projektsprache) bzw. 1 (für Mandatssprache) angegeben werden: DE0, DE1, etc.
Dies beeinflusst die mit translation markierten Texte in der Berichtsvorlage. Für die Übersetzung von Text im Python Code kann die Methode context.translate() verwendet werden.
optarg
Das optionale Adressen-Argument bei Berichten. Um mit dem Objekt weiterzuarbeiten, kann wie folgt darauf zugegriffen werden:
Ab Version 6.7.0.6. Für die Verwendung in Outlook App: E-Mail-Vorlagen. Enthält die in der Outlook App vorausgewählte Opportunität des E-Mails.
Falls keine Opportunität vorausgewählt ist oder bei Aufruf des Berichts ausserhalb der Outlook App ist die Variable None. Das bedeutet, dass im Code geprüft werden muss, ob eine Opportunität vorhanden ist, ansonsten wird beim Zugriff in der Berichtsvorlage ein Fehler geworfen.
phase
Ab Version 6.7.0.6. Für die Verwendung in Outlook App: E-Mail-Vorlagen. Enthält die in der Outlook App vorausgewählte Phase des E-Mails.
Falls keine Phase vorausgewählt ist oder bei Aufruf des Berichts ausserhalb der Outlook App ist die Variable None. Das bedeutet, dass im Code geprüft werden muss, ob eine Phase vorhanden ist, ansonsten wird beim Zugriff in der Berichtsvorlage ein Fehler geworfen.
project
Ab Version 6.7.0.6. Für die Verwendung in Outlook App: E-Mail-Vorlagen. Enthält das in der Outlook App vorausgewählte Projekt des E-Mails.
Falls kein Projekt vorausgewählt ist oder bei Aufruf des Berichts ausserhalb der Outlook App ist die Variable None. Das bedeutet, dass im Code geprüft werden muss, ob ein Projekt vorhanden ist, ansonsten wird beim Zugriff in der Berichtsvorlage ein Fehler geworfen.
reportdef
Ab Version 6.6.0.3. Enthält das Bericht-Objekt, welches den Bericht ausführt. Das ist vor allem für zentralisierten Code nützlich, wenn von mehreren Berichten auf denselben Code zugegriffen wird.
rootlist
Die Liste, auf der der Bericht ausgeführt wurde. Normalerweise ist das die eintraege-Liste des Containers, auf dem der Bericht ausgeführt wurde, beziehungsweise eine Liste mit dem Objekt drin, auf dem der Bericht ausgeführt wurde.
Die Variablen sind nur in OCL Feldern sowie in der context.evalocl Methode verfügbar. Andere OCL Aufrufe wie vtcapp.evalocl() oder die evalocl Methoden auf Listen und Objekten verwenden einen globalen OCL Evaluator und der kennt die Context-Variablen nicht.
Soll beispielsweise eine Context-Variable auf einer Liste angewandt werden, muss evalocl trotzdem auf dem context aufgerufen und die entsprechende Liste als Argument übergeben werden. Statt spesenlist.evalocl(..) schreibt man also:
Via OCL wird nur der Aufruf von OCL-kompatiblen Werten unterstützt (Vertec-Objekte und -Listen, Strings, Integers etc.). Bei inkompatiblen Werten (z.B. Python Dictionaries, Python-Listen, etc) erscheint eine Fehlermeldung.
Kollidieren manuell auf dem Context-Objekt gesetzte Variablen mit Keywords in OCL (self, date, now), erscheint ebenfalls eine Fehlermeldung.
Zugriff auf andere Felder in Feldberechnung
In der Berechnungsmethode eines Feldes kann auf andere Felder derselben Table zugegriffen werden. Dafür gibt auf dem Context eine Methode context.get_fieldvalue(fieldname).
Um vor der Ausführung des Berichts Python-Code ausführen zu können (um beispielsweise Dialoge anzuzeigen und Variablen auf dem Context-Objekt zu setzen), gibt es die Methode before_report(context). Ist diese Methode vorhanden, wird sie automatisch als erstes aufgerufen.
Gibt die Methode False zurück, bricht die Ausführung des Berichts ab. Ansonsten läuft sie weiter (True ist Standard und muss nicht extra angegeben werden).
Python Funktionen
Eine Python Funktion wird wie folgt deklariert:
defFunktionsname(context):
return XY
Funktionen können innerhalb einer Table definiert werden und sind dann für diese Table verfügbar.
Funktionen, die überall verfügbar sein sollen, müssen ausserhalb der Tables deklariert werden.
Referenzen
Referenzen auf Tables und Funktionen können auf zwei Arten angegeben werden:
Referenz als Name: Wird der Referenzname in Anführungszeichen geschrieben, handelt es sich um eine Referenz als Name. In diesem Fall kann die referenzierte Deklaration irgendwo im Code stehen, die Reihenfolge spielt keine Rolle.
Direkte Referenz: Wird der Referenzname ohne Anführungszeichen geschrieben, handelt es sich um eine direkte Referenz. In diesem Fall muss die referenzierte Deklaration oberhalb im Code stehen, also bevor darauf referenziert wird.