Vertec AI Chatbot

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?»

Python-Code für Office-Berichte

Python-Code für Office-Berichte

Produktlinie

Standard

|

Expert

Betriebsart

CLOUD ABO

|

ON-PREMISES

Module

Leistung & CRM

Budget & Teilprojekt

Fremdkosten

Ressourcenplanung

Business Intelligence

Erstellt: 11.04.2022
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.

Übersicht

  • Logischer Aufbau
  • Tables
    • Die Haupttabelle (main_table)
    • Sub-Tables zuweisen (TableField)
    • calculate_main_table
    • SingleRowTable (Rahmen für Listenberichte)
    • initialize_row
    • add_row
    • len(table)
  • Felder
    • Feld-Typen
    • OCL Felder
    • Einfache Felder
    • Table-Felder (Subtables)
  • Das Context-Objekt
    • context.evalocl
    • Context-Variablen
    • Zugriff auf andere Felder in Feldberechnung
  • Before Report Logik

Logischer Aufbau

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:

class Name(Table):

Der Name kann frei gewählt werden, muss aber innerhalb der Berichtsdefinition eindeutig sein.

# Beispiel eines minimalen Projekt-Reports

class Projekt(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:

class Projekt(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.
    def calculate_main_table(context):
        projektlist = context.rootlist.evalocl("self->orderby(code)")
        # Hier können Berechnungen gemacht werden
    
        return Projekt(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:
    calculate_main_table = "self.oclAsType(Projekt)->orderby(code)->asSet"

    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.

# Projektliste mit Reporttable

class Projekt(Table):
    fields = []
    
class Report(SingleRowTable):
    fields = [
        TableField("projekte", Projekt),
    ]
    def initialize_row(context, row):
      row.projekte = Projekt(context, context.rootlist)

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:

def initialize_row(context, row):

Diese Methode wird automatisch für jedes einzelne Objekt aufgerufen.

# Projektliste mit Reporttable
class Projekt(Table):
    fields = []
    
class Report(SingleRowTable):
    fields = [
        TableField("projekte", Projekt),
    ]
    def initialize_row(context, row):
      row.projekte = Projekt(context, context.rootlist)

add_row

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.

class Details(Table):
    fields = [
        TextField("code"),
        CurrencyField("value1"),
        CurrencyField("value2"),
    ]
class Invoice(Table):
    fields = [
        TableField("details", Details, "calculate_details")
    ]
    def calculate_details(context):
        phasen = context.evalocl("phasentotale.phase->asSet")
        for ph in phasen:
            row = context.table.add_row(ph)
            row.value1 = ph.evalocl("sumMinutenInt")
            row.value2 = ph.evalocl("sumWertExt")

len(table)

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:

OclTextField("projektleiter", "projektleiter.kuerzel")

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:

 class Projekt(Table):
    businessclass = "Projekt"
    fields = [
        CurrencyField("offeneLeistungen"),
        CurrencyField("offeneSpesen"),
    ]
    def initialize_row(context, row):
        row.offeneLeistungen = context.evalocl("offeneleistungen.wertext->sum")
        row.offeneSpesen = context.evalocl("offeneSpesen.wertext->sum")

Optional kann als zweites Argument eine Python Funktion angegeben werden, die automatisch zur Berechnung des Feldes aufgerufen wird. Beispiel:

 class Projekt(Table):
    businessclass = "Projekt"
    fields = [
        CurrencyField("offeneLeistungen", "calc_leistungen"),
        CurrencyField("offeneSpesen", "calc_spesen"),
    ]
    def calc_leistungen(context):
        return context.evalocl("offeneleistungen.wertext->sum")
    
    def calc_spesen(context):
        return context.evalocl("offenespesen.wertext->sum")

Es ist auch möglich, dieselbe Funktion in mehreren Feldern zu verwenden, durch Übergabe des fieldnames:

class Projekt(Table):
    businessclass = "Projekt"
    fields = [
        CurrencyField("offeneLeistungen", "calc_summen"),
        CurrencyField("offeneSpesen", "calc_summen"),
    ]
    def calc_summen(context, fieldname):
        if fieldname == "offeneLeistungen":
            return context.evalocl("offeneleistungen.wertext->sum")
        if fieldname == "offeneSpesen":
            return context.evalocl("offenespesen.wertext->sum")

Table-Felder (Subtables)

Etwas anders als die anderen Feld-Typen sind die Table-Felder aufgebaut, also die Felder, mit welchen die Sub-Tables angegeben werden.

Diese Felder haben drei Argumente:

 TableField("leistungen", "Leistungen", "calculate_leistungen")
  1. 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.
  2. Name der Table-Deklaration: Mit dem zweiten Argument wird die entsprechende Table-Deklaration übergeben:
  3. 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.
      OclTableField("leistungen", "Leistung", "offeneLeistungen->orderby(datum)")
      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 Leistungen
      
      class Leistung(Table):
          fields = [
              IntegerField("einwert"),
          ]
      
      class Projekt(Table):
          fields = [
              TableField("leistungen", Leistung, "calc_leistungen"),
          ]
          def calc_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.

context.evalocl("offeneLeistungen.wertext->sum", phasenliste)

context.translate

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:

context.evalocl("typ.text.asStringByLanguage(language)")

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.

Beispiele
class Leistung(Table):
    businessclass = "OffeneLeistung"
    fields = [
        OclTextField("text", "typ.text.asStringByLanguage(language)"),
    ]
    def initialize_row(context, row):
        context.language = "FR"

bzw.

class Leistung(Table):
    businessclass = "OffeneLeistung"
    fields = [
        TextField("text"),
    ]
    def initialize_row(context, row):
        context.language = context.language[:2]
        row.text = context.evalocl("typ.text.asStringByLanguage(language)")

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:

class Projekt(Table): 
    fields = [
        TextField('adresstext', 'calcadresse'),
    ] 

    def calcadresse (context): 
        return context.optarg.adresstext 
opportunity

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.
subject Ab Version 6.6.0.9. Enthält den Betreff der Berichtsregistrierung bzw. aus dem Druck-Dialog.
var<Table>
Für jede übergeordnete Table ist eine Variable mit deren aktuellem Objekt definiert.
var<Table>List
Für jede übergeordnete Table ist eine Variable mit der Liste der Objekte der Table definiert.

Context-Variablen setzen

Weitere Variablen können selbst definiert und dem Context-Objekt zugewiesen werden.

firma = vtcapp.getpropertyvalue('Firma')
if firma:
    context.firma = firma

Via set_image(name, value) kann ein Bild in eine Context-Variable eingelesen werden:

logo = vtcapp.getpropertyvalue('CompanyLogo')
context.set_image('logo', logo)

Die Context-Variablen können auf dem Bericht über eine Context-Expression ausgegeben werden.

Context-Variablen in OCL verwenden

Context-Variablen können auch in OCL verwendet werden. Der Aufruf erfolgt über den Namen der Variablen (ohne context.), hier im Beispiel todate:

class Bearbeiter(Table):
    fields = [
        OclMinuteField("balance", "self->getFerienSaldo(todate)"),
    ]

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:

context.evalocl("self->select(getProjekt=varProjekt)->orderby(code))", spesenlist)

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).

class Projekt(Table):
    fields = [
        OclMinuteField("bdgaufwand", "planminutenint"),
        OclMinuteField("effaufwand", "leistsums->select(projekt=varProjekt)->collect(minutenintoffen+minutenintverrechnet)->sum"),
        MinuteField("restaufwand", "calculate_restaufwand"),
    ]

    def calculate_restaufwand(context):
        return context.get_fieldvalue("bdgaufwand")-context.get_fieldvalue("effaufwand")

Before Report Logik

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.

def before_report(context):

    # Frage den User nach dem Datum
    initValues = {}
    initValues["Stichdatum"] = vtcapp.currentdate()
    dlgDefinition="""
        <Dialog Title="{Translate 'Choose date'}" Width="400">
           <Group Orientation="Vertical">
               <DatePicker Name="Stichdatum" Label="Stichdatum" />
           </Group>
        <Dialog.Buttons>
            <Button Text="OK" IsAccept="True" Command="{Binding OkCommand}" />
            <Button Text="Cancel" IsCancel="True" Command="{Binding CancelCommand}" />
        </Dialog.Buttons>
    </Dialog>
    """

    ok, values = vtcapp.showcustomdialog(dlgDefinition, initValues)
    if not ok:
        return False

    context.stichdatum = values["Stichdatum"]

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:

def Funktionsname(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.

 

Bitte wählen Sie Ihren Standort