OCL

Basics of OCL

Product line

Standard

|

Expert

Operating mode

CLOUD ABO

|

ON-PREMISES

Modules

Services & CRM

Budget & Phases

Purchases

Resource Planning

Business Intelligence

Created: 20.06.2003
Updated: 07.12.2024 | Adjusted section OCL operators for Resource Planning.

Einführung
Verwendung von OCL
Session

Member
m:n Verknüpfungen
Listen (derived ObjectList)
Klassenlisten
OCL Variablen

Vergleiche
String-Vergleiche
Bedingungen

Operatoren

Listenoperatoren
Konvertierungsoperatoren
Zahlenoperatoren
Stringbearbeitungsoperatoren
Operatoren auf UserEinträgen
Bearbeiteroperatoren
Operatoren für die Ressourcenplanung
Operatoren für die Berechtigungsprüfung
Operatoren für Projekteinträge
Operatoren für Projektphasen
Operatoren für Links
Leistungssummenoperatoren
Datumsoperatoren
Typ Operatoren (oclType, oclIsTypeOf, oclIsKindOf, oclAsType)
OCL Call Operatoren für Custom Business-Logik

Einführung

Die Navigation und Abfrage im Vertec Objektmodell erfolgt über eine objektorientierte Abfragesprache namens OCL. Eine komplette Sprachdefinition können Sie als PDF-File über folgenden Link downloaden: OCL Manual .

OCL steht für object constraint language und wurde ursprünglich im Rahmen des UML Standards entwickelt, um Gültigkeitsbedingungen für Objektmodelle zu formulieren. Aufgrund seiner objektorientierten Möglichkeiten lässt sich OCL aber auch als Abfragesprache einsetzen.

Der Vertec Kern beinhaltet einen OCL Interpreter, der OCL Ausdrücke als Text verarbeitet und die Ergebnisdaten aus den Vertec Objekten zurückliefert. Der OCL Interpreter benutzt zur Überprüfung und Auswertung von Ausdrücken Informationen aus dem Vertec Modell.

Verwendungen von OCL

OCL wird in Vertec an verschiedensten Orten verwendet:

Eine OCL-Expression wird immer aufgrund eines bestimmten Objekts ausgewertet und liefert ein Ergebnis eines bestimmten Typs. Mögliche Typen von Ergebnissen sind:

  • Zahl
  • String (Zeichenkette)
  • Boolean (logischer bzw. Ja / Nein Wert)
  • Objekt
  • Liste von Zahlen, Strings, Booleans oder Objekten

Für die Anzeige von Ergebnissen, z.B. in Listenspalten, wird das Ergebnis automatisch in einen String verwandelt. Bei Zahlen und Strings ist diese Umwandlung einfach. Booleans werden als "Y" (yes) oder "N" (no) dargestellt. Bei Objekten erscheint die Standard-Stringdarstellung, welche von der Objektklasse abhängig ist (bei Projekten z.B. der Code). Die Darstellung von Listen als String zeigt die Grösse der Liste an.

Bei Expressions in Expression-Ordnern muss der Ergebnistyp zwingend eine Liste von Objekten sein.

Session

Auf die laufende Vertec-Session kann in OCL via

TimSession.allInstances->first

zugegriffen werden. Eine Vertec Session hat folgende Attribute:

Resultat App
.login

Liefert aktuell eingeloggten Bearbeiter zurück. Siehe dazu auch den Artikel Login / aktueller Benutzer.

.instanceName

Eine Datenbank-Section kann im Vertec.ini-File einen Wert namens InstanceName enthalten. Auf der Oberfläche der Vertec Desktop App wird dies dann entsprechend angezeigt, siehe dazu den Abschnitt Instanz-Name zur Kennzeichnung von Test-Installationen.

Für den Zugriff via OCL gibt es dafür das Attribut namens InstanceName:

TimSession.allInstances->first.instanceName
.hasGui

Der Operator hasGui bietet die Möglichkeit, aus OCL Expressions oder Scripts zu bestimmen, ob der Client fähig ist, benutzerspezifische Dialoge anzuzeigen, also ob es sich beim Client um eine der full-featured Apps handelt.

TimSession.allInstances->first.hasGui

Rückgabewert ist entweder

  • True (Desktop App, Cloud App und Web App), oder
  • False (XML Server, Phone App, Outlook App und TaskRunner)

Es ist wichtig, dass Scripts - insbesondere Eventscripts - keine Dialoge anzeigen, wenn dies auf dem verwendeten Client nicht möglich ist, da dies sonst Vertec blockieren kann.

.appType

Ab Version 6.0. Der Operator AppType bietet die Möglichkeit, aus OCL Expressions oder Scripts zu bestimmen, in welcher App man sich befindet.

TimSession.allInstances->first.appType

Liefert einen String zurück mit folgenden möglichen Werten:

.appType Bedeutung
Desktop Desktop App
Cloud Cloud App
Web Web App
XML XML Server
Phone Phone App
Outlook Outlook App
TaskRunner Geplante Aufgaben
In Versionen zwischen 6.4.0.14 und 6.5 wird "WebAPI" anstelle von "Phone" zurückgegeben.
.checkfeature(featurecode: string) Prüft, ob ein bestimmtes Feature lizenziert ist.

TimSession.allInstances->first.checkFeature('fcPhasen')

Die Featurecodes sind gemäss Vertec Featurematrix (z.B. fcPhasen für Phasen).

Rückgabewert ist False oder True.

Member

Ein Member ist eine Eigenschaft eines Objekts. Das ist entweder eine Verknüpfung (association) zu einem oder mehreren anderen Objekten oder ein Datenfeld (attribute) des Objekts.

Ausgehend von einem Objekt kann ein Membername für den Zugriff auf ein Member angegeben werden. Falls eine solche Member-Referenz nicht am Anfang einer Expression steht, muss sie durch einen Punkt abgetrennt werden. Membernamen müssen immer klein geschrieben werden. Beispiele: code in einer Listenexpression einer Projektliste zeigt den Projektcode in der entsprechenden Spalte an; kunde.name, ebenfalls in einer Projektliste, zeigt jeweils den Namen des Kunden an. Hier handelt es sich um eine Verknüpfungsreferenz (kunde) mit anschliessender Attribut Referenz (Attribute name der Klasse Adresseintrag).

Durch Aneinanderreihen von Member-Referenzen in einer OCL-Expression können beliebige Verknüpfungen im Vertec Objektmodell abgefragt werden.

m:n Verknüpfungen

Bei m:n Verknüpfungen gibt es jeweils eine Link-Tabelle. Der Zugriff darauf erfolgt über den kleingeschriebenen Klassennamen der Link-Tabelle. Hier als Beispiel ein Ausschnitt aus dem UML Modell Bearbeiter:

Um herauszufinden, wie die entsprechende Link-Tabelle heisst, sehen Sie bitte im entsprechenden UML Modell nach oder wenden sich an Ihren Vertec Betreuer.

Listen (derived ObjectList)

Eine etwas spezielle Art von Members in Vertec sind berechnete Listen Attribute. Im OCL Editor werden diese als Typ ObjectList dargestellt. Eine sogenannte Derived ObjectList berechnet ihren Wert zu Laufzeit. Sie enthalten im Gegensatz zu Derived Attributes keine einzelnen Werte, sondern geben eine Liste zurück.

Ein Beispiel ist die Liste leistungen auf einem Projekt. Im Modell gibt es auf dem Projekt eigentlich nur zwei Listen: offeneLeistungen und verrechneteLeistungen. Die Liste der leistungen, also alle offenen und verrechneten zusammen, wird zu Laufzeiten berechnet.

Die Listen liefern Typinformationen in OCL und können wie folgt augerufen werden:

<Proj>.leistungen.wertext->sum

Klassenlisten

Eine Klassenliste ist die Liste aller Objekte eines bestimmten Typs (Klasse), z.B. alle Projekte oder alle Bearbeiter einer Vertec Installation.

OCL unterscheidet zwischen Gross- und Kleinschreibung. Alles Grossgeschriebene versucht der OCL Interpreter als Klassennamen (Metatyp) zu verstehen. Auf einer Klasse kennt OCL den Operator allInstances, welcher eine Liste aller Instanzen der Klasse ergibt. Projekt->allInstances liefert z.B. eine Liste aller Projekte.

Da Klassenlisten ziemlich häufig Verwendung finden, gibt es in Vertec eine Abkürzung dafür. Wird ein Klassenname klein geschrieben, dann wird dies direkt als Klassenliste interpretiert. projekt bedeutet daher ebenfalls die Liste aller Projekte.

Klassenlisten werden vor allem als Ausgangspunkt für Expressions von Expression Ordnern verwendet. Die meisten vordefinierten Expressionordner in Vertec (z.B. Stammdaten Bearbeiter) enthalten eine simple Klassenliste als OCL-Expression.

Achtung: Bei Klassenlisten ist etwas Vorsicht geboten, denn es gibt Vertec Klassen, welche sehr viele Objekte umfassen können. Bei Angabe einer Klassenliste in OCL werden alle Objekte der betreffenden Klasse in den Arbeitsspeicher geladen. Insbesondere bei den Klassen OffeneLeistung oder VerrechneteLeistung kann dies zu hohem Speicherbedarf und schlechter Performance führen.

Operatoren

Die nachfolgenden Operatoren führen gewisse Transformationen auf OCL Werten durch. Ein Operator wird innerhalb einer Expression durch einen vorangestellten Pfeil (->) abgetrennt. Falls keine Verwechslungsgefahr mit einem Member besteht, wird auch ein Punkt als Trennzeichen akzeptiert.

Listenoperatoren

Basierend auf einer Liste existieren in OCL verschiedene Operatoren, welche die Liste modifizieren. Weitere, hier nicht erwähnte Operatoren, erscheinen jeweils in "verfügbare Felder" im OCL-Expression-Editor.

->size Der size Operator liefert die Grösse (Anzahl Einträge) einer Liste, zum Beispiel als Listenspalte in einer Liste von Adresseinträgen gibt projekte->size die Anzahl Projekte eines jeden Kunden an.
->select Der select Operator erlaubt es, den Inhalt einer Liste aufgrund einer Bedingung zu filtern. adresseintrag->select(projekte->size > 0) als Expression eines Expressionordners liefert alle Adressen, die Projekte zugeordnet haben (d.h. Kunden sind). Das Argument des select Operators muss einen logischen (Wahr/Falsch) Wert ergeben.
->reject Der Operator reject ist sozusagen das Gegenteil des select Operators. Es werden damit alle Einträge aus der Liste ausgeschlossen, die der Expression entsprechen. So gibt beispielsweise die Expression
projektbearbeiter->reject(name='Administrator')
eine Liste zurück, die alle Projektbearbeiter ausser dem Administrator enthält.
->first

Der first Operator liefert aus einer Liste den ersten Eintrag. Am häufigsten kommt der first Operator zur Anwendung, wenn aufgrund einer Selektion ein Objekt als Ergebnis verwendet werden soll. Da der ->select Operator eine Liste als Ergebnis liefert, muss darauf noch ->first angewendet werden, damit das Ergebnis ein einzelnes Objekt ist. Beispiel:

phasen->select(code= 'OFFERTE')->first.offeneleistungen->size

zeigt in einer Liste von Projekten die Anzahl offener Leistungen der Phase "OFFERTE" an.

->orderby Mit dem orderby Operator können Listen sortiert werden. adresseintrag->orderby(projekte->size) ordnet die Liste der Adresseinträge nach der Anzahl der Projekte, bei denen sie Kunden sind.
->orderdescending

Mit dem orderdescending Operator können Listen absteigend sortiert werden (sonst gleich wie ->orderby):

adresseintrag->orderdescending(projekte->size)

Anmerkung: Als Expression in einem Expression-Ordner verwendet haben diese Operatoren keine Bedeutung, da die Liste die Sortierung selber vornimmt.

->orderMulti

Der Operator orderMulti erlaubt das Sortieren einer Liste nach verschiedenen Sortierkriterien. Er kann in einer OCL-Expression auf einer Liste angewandt werden und erwartet einen String als Argument. Dieser String enthält die verschiedenen Sortierkriterien als einzelne OCL-Expressions, getrennt durch Semikolons:

projekt->ordermulti('projektleiter.name;code.asstring')

als Expression eines Expressionordners liefert sie eine Liste aller Projekte, sortiert in erster Linie nach dem Namen des Projektleiters, in zweiter Linie nach dem Projektcode. Diese Sortierung wird in der Listenanzeige allerdings nur sichtbar, wenn Sie die Sortierung auf Listenspalten entfernen. Doppelklicken Sie auf eine sortierte Listenspalte, bis diese keinen Sortierpfeil mehr anzeigt.

ordermulti mit Zusatzfeldern

Will man nach Zusatzfeldern sortieren, hat man das Problem, dass man in der Expression keine Hochkommas verwenden kann. Bei den Zusatzfeldern erfordert das einen Umweg über die interne ID des Zusatzfelds (Einstellungen > Zusatzfelder > rechte Maustaste > Eigenschaften > interne ID):

projekt->ordermulti('projektleiter.name;zusatzfelder ->select(metaZusatzfeld.boldID=<interne ID>)->first.wert')

Je nach Feld-Typ können Sie den Wert wie folgt abfragen:

.wert  .wertBlob  .wertBoolean  .wertInteger  .wertCurrency  .wertDatum  .wertObject
->asSet Ausgehend von einer Liste kann auch eine Member-Referenz angegeben werden. Die Member-Referenz wird dann auf jedem Objekt der Liste angewendet. So ist das Ergebnis eine Liste mit Elementen des Member-Typs. Beispiel projekt.kunde liefert in einem Expressionordner eine Liste aller Kunden. Der Nachteil dieser Liste ist, dass die Kunden zum Teil doppelt erscheinen, da die Expression projektweise alle Kunden zusammenträgt. Dies lässt sich durch die Anwendung des asSet Operators beheben, welcher eine Liste in eine Menge (im Sinne der Mengenlehre) umwandelt: projekt.kunde->asSet liefert eine eindeutige (distinct) Liste aller Kunden.
->asSequence Macht aus einem Objekt (oder einer Liste) eine Liste, welche das einzelne Objekt (oder im Falle der Ausführung auf einer Liste die Elemente der Liste) enthält.
->asBag Liefert die Liste mit allen Einträgen, also auch die Doppelten (im Gegensatz zu asSet, siehe oben). Da der Aufruf einer Liste im Vertec sowieso eine Collection mit allen Einträgen zurückliefert, ist die explizite Angabe von asBag unnötig.
->union

Der union Operator erlaubt die Zusammenfassung zweier Listen in einer. Er kann in einer OCL-Expression auf einer Liste angewandt werden und erwartet eine weitere Liste (Collection) als Argument:

offeneLeistungen->union(verrechneteLeistungen)

als Expression auf einem Projekt liefert alle offenen und verrechneten Leistungen des Projekts. Mit dieser Liste kann normal weitergearbeitet werden. Als Typ wird immer die gemeinsame Basisklasse verwendet, dessen Attribute zur Verfügung stehen. Das obige Beispiel liefert also eine Liste mit Einträgen vom Typ Leistung. Bei einer Expression projekt->union(adresseintrag) wäre die gemeinsame Basisklasse z.B. UserEintrag.

->collect Der collect Operator erlaubt es, mittels Variable einen komplexen Teilausdruck nur einmal zu formulieren, aber mehrfach zu verwenden.

Zum Beispiel will man die Summe der Honorarnoten (netto) des jeweils letzten Jahres anzeigen:

rechnungen->select(datum.year=date.year-1)->collect(umsatz+vorschussbetrag-vorschusseffektiv)->sum

ohne den Collect-Operator müsste man die ganze '->select'-Expression für jeden Wert (umsatz, vorschussbetrag etc) wiederholen.

Man kann auch noch einen Schritt weitergehn, indem man den Wert, der aus dem collect resultiert, einer Variable zuweist und damit weiterarbeitet.

Als Beispiel nehmen wir eine Liste von Projekten. Jedes Projekt befindet sich (in diesem Beispiel) entweder in einem Ordner "Kundenprojekte" oder in einem Ordner "Interne Projekte" oder in einem Ordner "Auftragsprojekte". Diese Ordner sind jeweils Unterordner des Ordners "Projektkategorie". In der Liste möchten wir nun entweder 1, 2, oder 3 anzeigen, je nachdem, in welchem Ordner sich das Projekt in der Liste befindet:

ordner->select(parentordner.bezeichnung='Projektkategorie')  ->first.bezeichnung.substring(1,1)->asSet->collect(x|if x ='K'then  '1'else if x='I'then'2'else if x='A'then'3'  else'Keine Angabe'endif endif endif)->first

Die Expression geht von einem Projekt aus (jedes Projekt in der Liste). ordner bedeutet also die Ordner, in denen sich das Projekt befindet. Wir suchen zuerst den Unterordner des Ordners Projektkategorie. Von diesem nehmen wir den ersten Buchstaben (bezeichnung.substring(1,1)). Das ist nun ein einzelner Buchstabe, entweder "K" oder "I" oder "A". Da der Collect-Operator nur auf einer Liste ausgeführt werden kann, fügen wir ein ->asSet an. Nun kommt der ->collect Operator dran: Anstatt für jede if Abfrage den ganzen ordner->select(...) Abschnitt zu wiederholen, kann einfach die Variable x mehrfach eingesetzt werden. Das x in der Klammer bezieht sich auf den aktuellen Wert. Das ist ja im Moment unser einzelner Buchstabe. Nun können wir über das x diesen Buchstaben abfragen und je nachdem den gewünschten Wert einsetzen. Das Ganze ist nun noch immer eine Liste. Wir möchten aber den einzelnen Wert im Feld anzeigen. Deshalb fügen wir wieder ein ->first an.

->append(obj) Gibt die Liste zurück, die das obj am Schluss noch angehängt hat
->at(i) Gibt das Objekt an der Stelle i zurück. Der Index i beginnt mit 1.
->count(obj) Gibt an, wieviele Male obj in der Liste enthalten ist.
->difference(list2) Gibt die Liste zurück, die der ursprünglichen Liste ohne die Elemente von list2 entspricht.
->excluding(obj) Gibt die Liste zurück, aus der das obj entfernt wurde.
->includes(obj) Gibt an, ob obj in der Liste enthalten ist
->includesAll(list2) Gibt an, ob alle Objekte in list2 in der Liste enthalten sind.
->including(obj) Dasselbe wie ->append
->intersection(list2) Gibt die Schnittmenge der beiden Listen zurück, das heisst eine Liste aller Objekte, die in beiden Listen enthalten sind.
->isEmpty True, wenn keine Liste oder Länge der liste=0, sonst False.
->prepend(obj) Gibt die Liste zurück, bei der das obj am Anfang eingesetzt ist.
->subsequence(start, stop) Gibt eine Liste von Index start bis und mit Index stop zurück. Die Indizes sind 1 basiert und werden automatisch auf gültige Werte korrigiert (d.h. stop kann auch grösser als die Listenlänge sein, ohne dass es Fehler gibt).
->symmetricDifference(list2) Gibt eine Liste mit allen Elementen der Liste, welche nicht in liste2 sind, sowie alle Elemente von liste2, welche nicht in der Liste sind, zurück.
->sum Summiert die Zahlenwerte einer Liste und gibt die Summe zurück.

Die Listenoperatoren ->exists und ->forAll funktionieren nicht.

Konvertierungsoperatoren

Häufig stellt sich die Aufgabe, eine Zeichenfolge in einen Datumswert umzuwandeln, eine Zahl in eine Zeichenfolge umzuwandeln, etc. Nachfolgend eine Liste der verfügbaren Konvertierungsoperatoren:

->asString (auch .asString) Wandelt eine Zahl oder Datumswert in eine Zeichenfolge (String) um.
->dateToFloat Wandelt einen Datumswert in eine Zahl um (die Zahl sagt Ihnen wenig: (Anzahl Tage seit 1.1.1900). Diese Operation wird vor allem für das Rechnen mit Datumswerten verwendet (z.B. 30 Tage zum heutigen Datum dazuzählen, siehe Beispiel weiter unten).
->floatToDate

Wandelt eine Zahl in ein Datum um. Die folgenden Expression zählt zum datum des Eintrags (z.B. einer Leistung) 31 Tage dazu:

(datum->dateToFloat+31)->floatToDate
->strToDate

Wandelt einen String in ein Datum um. Dieser Operator ist dann nützlich, wenn man mit einem Datum arbeiten muss, das vorher nicht bekannt oder nur als String vorhanden ist (z.B. wenn vom Benutzer ein Datum abgefragt wird).

Die Verwendung von strToDate ist heikel, denn es nimmt Bezug auf die aktuellen Ländereinstellungen. Ein strToDate mit einem Stringliteral von '01.09.2020' geht schief, wenn ein Client z.B. ein US Datumsformat verwendet. In der Web App bezieht sich das dann nicht mal auf das lokale Windows, sondern auf die Einstellungen im Web Browser (z.B. "English").

In fixen OCL Expressions sollte deshalb stattdessen der Operator encodeDate verwendet werden, der weiter unten beschrieben wird. Also nicht '01.09.2020'->strToDate, sondern encodeDate(2020,09,01).

->stringToFloat Wandelt eine Zeichenfolge in ein Zahl um. Ist die Zeichenfolge keine Zahl, wird 0 ausgegeben.
->stringToList

Stellt einen String als Liste dar. Einzelne Wörter werden getrennt bei der Wortgrenze oder bei einem Delimeter. Wörter innerhalb doppelter Anführungszeichen gelten als ein Wort.

TimSession.allinstances->first.login.name.stringToList

Gibt den Namen des eingeloggten Bearbeiters als Liste zurück. So kann beispielsweise über

TimSession.allinstances->first.login.name.stringToList->last

nur der Nachname angezeigt werden.

->isEmpty Der Operator ->isEmpty gibt zurück, ob ein Linkmember leer ist. So gibt die Expression projektleiter->isEmpty, ausgeführt auf einem Projekt, mit einem boolschen Wert (wahr, falsch) zurück, ob ein Projektleiter zugeordnet ist (falsch) oder nicht (wahr).
.isNull/.notNull Oft ist es nützlich, einen Nullwert zu erkennen. Ab Version 5.5 muss das nicht mehr über einen String-Vergleich geschehen, sondern kann über die OCL Operatoren isNull und notNull abgefragt werden.

Beispiel: statt

projekt->select(betreffend.asstring='') (alle Projekte ohne Betreffend)

kann man nun

projekt->select(betreffend.isNull)

ausführen.

Anmerkung: Diese Operatoren sind nicht zu verwechseln mit dem isEmpty-Operatoren, welcher eine Verknüpfung abfragt. Um beispielsweise zu wissen, ob ein Projekt einen Kunden zugeordnet hat, kann nicht mit isNull abgefragt werden, sondern mit kunde->isEmpty.
.asnull/.null Ab Vertec 6.2.0.4. Der OCL Null Operator ermöglich es, für beliebige Attribute-Typen Null-Werte zu erhalten.

Dies ist nützlich, um bei Zahlenwerten statt 0 nichts darzustellen, ohne dafür die ganze Expression in einen String umwandeln zu müssen. So können Expressions der Art:

if usespesen then spesenint.asstring else '' endif
durch folgende Expression ersetzt werden:
if usespesen then spesenint else spesenint.asnull endif

Das OCL eine statisch und streng typisierte Sprache ist, müssen auch ein Null-Wert einen Typ haben, damit die Gültigkeit der Expression festgestellt werden kann. Deshalb wurde ein .asnull Operator auf Instanzen und .null auf Typen eingeführt:

  • <typ>.null erstellt aus einem Ocl-Typ einen Null-Value. Unter Verwendung des null Operators auf Type würde  obige Expression wie folgt lauten: if usespesen then spesenint else VtcCurrency.null endif.
  • <value>.asnull erstellt aufgrund eines bestehenden Wertes (Member-Referenz) einen null Value desselben Typs, ohne dass man den korrekten Namen des Typen wissen mus: if usespesen then spesenint else spesenint.asnull endif.
->listToString

Durch diesen Operator können Listen in Strings dargestellt werden. So liefert die Expression:

phasen.code->listToString(',')

ausgeführt auf einem Projekt (z.B. via Listeneinstellungen) die Liste der Phasen-Codes, mit "," getrennt.

.toLower/.toUpper Sehr häufig ist das Resultat einer Expression ein string (Zeichenfolge). Mit dem Operator .toLower wird die Zeichenfolge in Kleinbuchstaben verwandelt, mit dem Operator .toUpper in Grossbuchstaben.
.asHMString Interpretiert eine Zahl als Anzahl Minuten und formatiert sie als Stunden:Minuten. Es werden auch negative Zeitwerte unterstützt.
.asTimeString Interpretiert eine Zahl als Anzahl Minuten und formatiert sie als Tageszeit. Negative Werte werden nicht dargstellt.
.asMinuteString Interpretiert eine Zahl als Anzahl Minuten und formatiert sie gemäss Format in den Systemeinstellungen. Es werden auch negative Zeitwerte unterstützt.
.asStringBy
Language(<Sprache>)

Fragt die entsprechende Sprachversion eines Members ab. Dies gilt für alle MLStrings, das sind Werte, die für die verschiedenen Sprachen jeweils ein eigenes Feld haben (Beispiele sind Tätigkeiten, Spesen- und Auslagetypen). Zum Beispiel bei Auslagetypen auf einer Rechnung: Wenn man die französische Bezeichnung des Typs haben möchte, kann dies mit folgender Expression geschehen:

text.asStringByLanguage('FR')

Mögliche Sprachen / Parameter sind 'DE', 'DD' (ab 6.5.0.9), 'FR', 'IT', 'EN' oder 'NV'.

.pad(Anzahl,Platzhalter)

Der .pad-Operator füllt einen Integer-Wert bis zur Anzahl angegebenen Zeichen mit dem als Platzhalter angegebenen Zeichen auf. Das Ergebnis ist ein String.

Dies ist zum Beispiel dann nützlich, wenn man für eine alphanumerische Sortierung führende Nullen braucht.

6.pad(2,'0') ergibt 06
6.pad(3,'0') ergibt 006
...

Zahlenoperatoren

abs

Dieser Operator gibt den absoluten Wert einer Zahl zurück.

(-2.8).abs = 2.8
(2.8).abs = 2.8

floor

Abrundungsfunktion. Gibt von einer reellen Zahl die nächstliegende kleinere Ganzzahl zurück.

(-2.8).floor = -3
(2.8).floor = 2
2.floor = 2

round

Rundet einen Zahlenwert nach der "round-to-even" Regel auf die nächste Ganzzahl und gibt diese als Resultat zurück.

(-2.8).round = -3
(2.5).round = 2
(2.6).round = 3
(3.5).round = 4

Auf fünf Rappen runden:

(wert * 20)->round / 20

Runden auf zwei Nachkommastellen:

(wert * 100)->round / 100

Aufrunden ab dem 5er:

  • Für positive reelle Zahlen: (wert + 0.5).floor
  • Für negative reelle Zahlen: (wert - 0.5).floor

Siehe zu diesem Thema auch Runden in Scripts.

Stringbearbeitungsoperatoren

length

Dieser Operator gibt die Anzahl Zeichen einer Zeichenfolge zurück. Zum Beispiel gibt die Expression adresseintrag->select(standardplz.length=4) alle Adressen mit einer vierstelligen PLZ zurück.

substring(Anfang, Ende) Dieser Operator schneidet aus einer Zeichenfolge die Zeichen zwischen "Anfang" (beginnend bei 1) und "Ende" aus. So liefert die Expression code->substring(1,1), ausgeführt auf einem Projekt, den ersten Buchstaben des Projektcodes. Ein anderes Beispiel: Sie möchten das Erfassungsjahr des aktuellen Eintrags anzeigen. Vertec speichert das Erfassungsdatum im Member "creationdatetime" ab. Die folgende Expression nimmt das "creationdatetime", wandelt es in einen string um und setzt die hintersten 4 Zeichen: creationdatetime->asstring->substring(7,10). Diese Methode kann natürlich auch für das aktuelle Systemdatum benutzt werden (Expression now, kann z.B. im Zusammenhang mit Speicherpfaden bei Word-Reports wertvoll sein, siehe entsprechende Artikel)
replaceString

Die Syntax lautet wie folgt:

<string>->replaceString(substring, replacement)

Sie geben darin den Teil an, den Sie ersetzen möchten (substring) sowie den Teil, durch den er ersetzt werden soll (replacement). Rückgabewert ist wieder ein String.

Sie möchten beispielsweise in einem Text alle Meyer durch Maier ersetzen:

<text>->replaceString('Meyer', 'Maier')

Der Replace-String ist Case-Sensitiv, das heisst, er beachtet die Gross/Klein-Schreibung.

replaceRegex

Die Syntax lautet wie folgt:

<string>->replaceRegex(template, replacement)

Hier kann ein regulärer Ausdruck, eine sogenannte Regular Expression, angegeben werden, sowohl für den Teil, den Sie ersetzen möchten (template) wie auch für den Teil, der ersetzt werden soll (replacement). Rückgabewert ist wieder ein String.

Ein kleines Beispiel, was damit möglich ist:

In einem Text sind Bezeichnung der Art <Abschnitt>:<Kapitel> vorhanden, z.B. 2:15 oder 3:10. Diese Bezeichnungen sollen getauscht werden, sodass sie als 15:2 bzw. 10:3 dargestellt werden. Dies kann mit folgender Expression geschehen:

<text>->replaceRegex('([0-9]*):([0-9]*)', '$2:$1')
translate

Ab Vertec 6.4.0.20. Übersetzt einen String-Wert in die aktuelle Vertec Oberflächensprache .

Beispiel:

if projekte->size > 0 then 'Client'.translate else 'Address'.translate endif

auf einer Adressliste zeigt in der Spalte folgendes Resultat bei Deutsch:

Operatoren auf User-Einträgen

Auf UserEintrag (alle Objekte, welche in Ordnern abgelegt werden können, z.B. Leistungen, Projekte, Adressen, Bearbeiter, Aktivitäten etc.) gibt es folgende Operatoren:

Operator Beschreibung

->hasBIDataRight: boolean

ab Vertec 6.4.0.14:

->hasBIDataRight('Kennzahl'): boolean

Mit diesem Operator kann überprüft werden, ob der aktuell eingeloggte Benutzer auf dem angegebenen Objekt BI Berechtigung hat.

Mit Einführung der Berechtigungen auf den Kennzahlen mit Version 6.4.0.14 wurde dieser OCL Operator geändert. Ab dann muss als Parameter ein String mit dem internen Namen der Kennzahl angegeben werden. Beispiel:

projekt->hasBiDataRight('MinutesExt')

prüft, ob der aktuell eingeloggte Benutzer auf dem angegebenen Projekt das Recht auf die MinutesExt Kennzahl hat.

Dies ist nicht rückwärtskompatibel. Die entsprechenden Aufrufe müssen angepasst werden.

->hastag(tagname): boolean

Ab Version 6.1.0.10. Fragt ab, ob das Objekt einen Tag dieses Namens gesetzt hat.

Weitere Informationen finden Sie im Artikel über Tags auf User-Einträgen.

->keystring(key): string

->keybool(key): boolean

->keydate(key): datetime oder empty

->keyint(key): integer oder 0

->keycurr(key): currency oder 0.00

Ab Version 6.1.0.10. Operatoren zur typisierten Abfrage von Key-Values auf dem Objekt.

Weitere Informationen finden Sie im Artikel über Key-Values auf User-Einträgen.

Bearbeiteroperatoren

Speziell für die Klasse Projektbearbeiter gibt es folgende Operatoren:

Operator Beschreibung ab Version
->getSollzeit(von, bis)

Sollzeit in der Periode (minuten)

 

->getArbeitszeit(von, bis)

Arbeitszeit in der Periode (minuten). Berechnet aus der Summe aller vorhandenen Leistungen plus der Ferien, die als Abwesenheiten erfasst wurden.

 

->getUeberzeitvortrag(datum)

liefert den Ueberzeitsaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert.

 

->getUeberzeitvortragDatum(datum)

liefert Datum des letzten Ueberzeitvortrags vor Datum

5.4

->getUeberzeitsaldo(datum)

liefert Ueberzeitsaldo per Datum

5.4

->getFerienVorgabe(von,bis)

Ferienguthaben innerhalb Periode

 

->getFerienBezug(von,bis)

Ferienbezug, sowohl Abwesenheiten als auch Ferienleistungen

5.4

->getFerienVortrag(datum)

liefert den Feriensaldo per Datum-1, ausser auf Datum ist ein Vortrag erfasst, dann wird dieser Vortrag geliefert.

 

->getFerienVortragdatum(datum):

liefert Datum des letzten Ferienvortrags vor Datum

5.4

->getFerienStart(datum)

liefert Startdatum für Berechnung des Ferienguthabens. Ist der nächste Ferien-Stichtag nach dem letzen Vortrag

5.4

->getFerienEnd(datum)

liefert Enddatum für Berechnung des Ferienguthabens. Ist das nächst Ferienperiode-Ende

5.4

->getFerienSaldo(datum)

liefert FerienSaldo per Datum

5.4

->getFeriensaldoAbgegrenzt(datum)

Berechnet den abgegrenzten Feriensaldo per Datum unter Berücksichtigung des Ferienguthabens bis zum Datum. Beispiel:

Gegeben ist ein Ferienguthaben von 200 Stunden pro Jahr, vorgegeben von der Gruppe. Der Ferienstichtag ist der 01.01. Auf diesen Stichtag wurde dem Mitarbeiter ein Ferienvortrag von 20 Stunden gutgeschrieben. Das bedeutet: Der Mitarbeiter hat ein gesamtes Ferienguthaben für das Jahr 2013 von 220 Stunden.

Nun möchte ich den Feriensaldo dieses Mitarbeiters berechnen per 31. März 2013. Es gibt folgende Varianten:

  • getFeriensaldo(encodeDate(2013,3,31)): Nimmt den Ferienvortrag (20 Stunden) plus das Ferienguthaben (200 Stunden) und zählt die in im Zeitraum bis zum 31.03.2013 bezogenen Ferien ab. Resultat: 204:00 Stunden. So viele Ferien hat der Mitarbeiter noch zugut.
  • getFeriensaldoAbgegrenzt(encodeDate(2013,3,31)): Nimmt den Ferienvortrag (20 Stunden) plus den Anteil des Ferienguthabens bis zum 31.03.2013 (49:19) und zählt die im Zeitraum bis zum 31.03.2013 bezogenen Ferien ab. Resultat: 53:19 Stunden. So viele Ferien hätte der Mitarbeiter am 31. März 2013 noch zugut gehabt.
5.8
->getLohn(von,bis)

Lohn innerhalb der angegebenen Periode

5.4

->getGemeinkosten(von,bis)

Gemeinkosten innerhalb der angegebenen Periode

5.4

->getSollzeitVorgabe(von, bis)
Berechnet die Sollzeit von, bis nur aufgrund der Vorgaben, ohne Berücksichtigung von Feiertagen. Eintritt / Austritt wird berücksichtigt. 5.4.0.21
->getSollzeitGroupVorgabe(von, bis)
Berechnet die Sollzeit von, bis aufgrund der Gruppen-Vorgaben des Bearbeiters. Das ergibt die Sollzeit, wenn der Mitarbeiter 100% arbeiten würde. 5.4.0.21
->getSollzeitOnlyGroupAbw(von, bis)

Berechnet die Sollzeit eines Mitarbeiters unter Berücksichtigung nur der gruppenbasierten Abwesenheiten (Feiertage etc.).

Abwesenheiten werden im Unterschied zum GetSollzeit Operator nur von den Gruppen berücksichtigt. Auf dem Mitarbeiter erfasste Abwesenheiten werden nicht berücksichtigt. Der Beschäftigungsgrad des Mitarbeiters wird berücksichtigt.

5.8
->getBeschaeftigungsgrad(datum)
Liefert den Beschäftigungsgrad des Mitarbeiters zu einem bestimmten Datum.
Die Berechnung des Beschäftigungsgrads erfolgt unabhängig davon, ob der Mitarbeiter am Stichdatum Sollzeit hat oder nicht. Ausschlaggebend ist das Verhältnis der Wochensollzeiten von Bearbeiter und Gruppe.
5.4.0.21
->getAbwesenheitFrei(Abwesenheitstyp, von, bis)

Operator zum Bestimmen der Frei-Zeit eines bestimmten Abwesenheitstyps. Beispiel:

Bearbeiter->getAbwesenheitFrei('Feiertag', encodedate(2013, 1, 1), encodedate(2013, 1, 31))

Die Berechnung geschieht wie folgt:

  1. Berechnung der Sollzeit für die angegebene Periode ohne Berücksichtigung von Abwesenheiten.
  2. Berechnung der Sollzeit unter Berücksichtigung nur der Frei-Abwesenheiten des angegebenen Typs.
  3. Das Resultat ist die Differenz der beiden Werte in Minuten (Integer).

Wird ein nicht existierender oder ein falscher (nicht Frei) Abwesenheitstyp angegeben, ist das Resultat 0.

Versionen vor 5.8

Zur Abfrage des Abwesenheitstyps wird in Versionen vor 5.8 die (sprachabhängige) Bezeichnung verwendet.

Werden am gleichen Tag mehrere Abwesenheiten erfasst, kann Vertec den Einfluss der einzelnen Abwesenheit nicht eindeutig bestimmen, da die Abwesenheitstypen keine Sortierung bezüglich Wichtigkeit kennen. Wenn man also am Ostermontag ("Feiertag") auch noch krank ist ("Krankheit"), dann stimmt zwar die Sollzeit, aber dieser Operator gibt sowohl bei "Feiertag" als auch bei "Krankheit" jeweils 0 an, da der andere Abwesenheitstyp auch den ganzen Tag belegt.

Versionen ab 5.8

Zur Abfrage des Abwesenheitstyps wird in Versionen ab 5.8 der (sprachunabhängige) Code verwendet.

Ab dieser Version haben Abwesenheitstypen ein Attribut Priorität. Dieses wird im Falle von überlappenden Abwesenheiten beachtet. Es werden beliebig viele überlappende Einträge berücksichtigt und die "Sichtbarkeit" der in Frage kommenden Abwesenheiten bestimmt sich durch den Prioritätswert auf ihrem Typ.

Falls die Prioritäten gleich sind, werden die folgenden Prioritätsregeln angewendet:

  1. Bei Minutenabwesenheiten mit unterschiedlichen Typen gewinnt die Abwesenheit mit dem grösseren Minutenwert.
  2. Bei Minuten- und ganztägiger Abwesenheit gewinnt die ganztägige.
  3. Falls eine Abwesenheit auf dem Bearbeiter und eine auf der Benutzer-gruppe definiert ist, gewinnt die auf dem Bearbeiter.
  4. In allen anderen Fällen gewinnt die Abwesenheit mit der höheren ID, also die, welche später erfasst wurde.
5.7
->getFerienbezugAbw(von, bis)

Operator für die Berechnung des Ferienbezugs unter Berücksichtigung von nur als Abwesenheiten erfassten Ferien. Beispiel:

Bearbeiter->getFerienbezugAbw(encodedate(2012, 1, 1), encodedate(2012, 1, 31))

Als Resultat werden die Abwesenheiten der Art Ferien in der entsprechenden Periode zurückgeliefert, in Minuten (Integer).

Für die normale Ferienberechnung kann der Operator
->getFerienBezug(von,bis) verwendet werden.

5.7
->getSollzeitGroup(von, bis)

Dieser Operator liefert die Sollzeit für die Gruppe (100%), unter Berücksichtigung von Abwesenheiten auf der Gruppe. Beispiel:

Bearbeiter->getSollzeitGroup(encodedate(2012, 1, 1), encodedate(2012, 1, 31))

Als Resultat wird die entsprechende Sollzeit zurückgeliefert, in Minuten (Integer).

5.7
->currentAbwesenheiten(datum)

Dieser Operator liefert eine Liste von Abwesenheiten, die für den angegebenen Tag zur Anwendung kommen. Beispiel:

Bearbeiter->currentAbwesenheiten(encodedate(2012,6,11))

liefert eine Liste der für diesen Bearbeiter für den 11.06.2012 erfassten Abwesenheiten.

5.7
->getTrackingUsers

Der Operator getTrackingUsers liefert für einen Bearbeiter eine Liste aller Bearbeiter, für die er Leistungen, Spesen und Auslagen erfassen darf.

Das wird im Bearbeiter-Auswahlfeld auf Leistungen, Spesen und Auslagen verwendet und kann auch über OCL abgefragt werden.

Beispiel:

TimSession.allinstances->first.login->getTrackingUsers

Liefert für den aktuell eingeloggten Bearbeiter die Liste aller Bearbeiter, für die er erfassen darf.

6.0
getPresenceEntries(datum)

Gibt eine Liste der Präsenzzeit-Einträge eines Tages für den Bearbeiter aus.

bearb.getPresenceEntries(date)

6.2

OCL Operatoren für Ressourcenplanung

OCL Operatoren sind eine Art, mit Ressourcenplandaten zu arbeiten. Es gibt jedoch eine Vielzahl von weiteren Möglichkeiten. Diese sind im Artikel OCL, Python, Custom Renderer und List Controller rund um die Ressourcenplanung beschrieben. 

.getResPlanMinuten(Datum von, Datum bis)

Steht auf Projekt- und Planungsbearbeitern zur Verfügung. Gibt die verplante Zeit für den Bearbeiter für die angegebene Periode in Minuten zurück.

Ein Beispiel finden Sie hier .

.getResRsrcMinuten(Datum von, Datum bis)

Steht auf Projekt- und Planungsbearbeitern zur Verfügung. Gibt die Ressourcenzeit für den Bearbeiter für die angegebene Periode in Minuten zurück.

Das ist nicht die noch verfügbare Zeit, sondern die gesamte Ressourcenplan-relevante Sollzeit. Der Unterschied zur Sollzeit ist, dass nur Abwesenheiten vom Typ "Frei" die Sollzeit beeinflussen, von der Ressourcenzeit hingegen werden alle Arten von Abwesenheiten (Frei, Ferien, Kompensation) abgezogen (siehe dazu auch die Tabelle über die Arbeitszeit-Ausnahmen im Artikel Abwesenheiten).

Ein Beispiel finden Sie hier

Berechnung der Kompensationszeit für einen Zeitraum

Sollen die effektiven Kompensationsabwesenheiten pro Bearbeiter für einen bestimmten Zeitraum ermittelt werden, kann dies wie folgt geschehen:

getSollzeit(von, bis) - getResRsrcMinuten(von, bis) - getferienbezug(von, bis)

So werden die arbeitsfreien Tage (Samstag, Sonntag, Feiertage etc.) automatisch mitberücksichtigt.

Beispiel

Beispiel für die Ermittlung der Kompensationszeit für den Monat Juli:

self.getSollzeit(encodeDate(2013,07,01),encodeDate(2013,07,31))
- self.getResRsrcMinuten(encodeDate(2013,07,01),encodeDate(2013,07,31))
- self.getFerienbezug(encodeDate(2013,07,01),encodeDate(2013,07,31))

Erklärung

Abwesenheiten vom Typ Frei beeinflussen die Sollzeit (Minus).

Abwesenheiten vom Typ Frei, Ferien und Kompensation sowie die als Leistungen erfassten Ferien beeinflussen die Ressourcenzeit (Minus).

Die Abwesenheiten vom Typ Frei heben sich somit auf. Es bleiben Ferien und Kompensation übrig. Darum müssen noch die Ferien abgezogen werden. Der Zeitunterschied ist die Kompensationszeit.

OCL Operatoren für die Berechtigungsprüfung (checkright)

Es gibt ab Version 6.0 OCL Operatoren für die Abfrage von Berechtigungen. Grundsätzlich gibt es 3 Arten von Berechtigungen:

  • Member-Rechte (read, write), können für ein einzelnes Member abgefragt werden.
  • Klassen- bzw. Objekt-Rechte (create, delete, execute, view), können für einen Klassentyp oder für ein Objekt abgefragt werden.
  • User-Rechte (Standard Benutzerrechte) können auf einem Abstractuser (Benutzergruppe oder Projektbearbeiter) abgefragt werden.

Die folgenden Operatoren für Berechtigungsabfragen liefern einen Boolean (Wahr/Falsch) Wert zurück.

Member-Rechte

Die Rechte auf einzelnen Members werden auf dem Objekt abgefragt und der Name des Members als Argument übergeben:

Operator Rechtname
Object->isMemberReadable(memberName) rtRead
Object->isMemberWritable(memberName) rtWrite

 

Klassen- bzw. Objekt-Rechte

OperatorRechtname
Class->isCreatablertCreate
Object->isDeletablertDelete
Object->isExecutablertExecute (Reports und Scripts)
Object->isViewablertSingleForm (darf das Objekt in eigenem Fenster gezeigt werden?)

User-Rechte

Bei der Abfrage der User-Rechte muss der Name des entsprechenden Rechts übergeben werden:

User->hasRight(rightname)
Rechtnamen für hasRight Standard Benutzerrecht
'admin' Super
'supervisor' Projekt Administrator
'manager' Projekt Leiter
'selftracking' Projekt Zeiterfasser
'folderlinks_admin' Ordner-Links Administrator
'folderlinks_user' Ordner-Links User
'address_admin' Adress Administrator
'address_user' Adress User
'benchmarking' Benchmarking
'treeview' Baumansicht
'systemproperties' Systemeinstellungen
'trackingcontroller' Projekt Fremderfasser
'book' Rechnungen buchen
'book_creditor' Kreditoren buchen
'benchmarking_no_users' Benchmarking ohne Bearbeiterzahlen
'teamleader' Teamleiter
'export' Exportieren
'sqlquery' SQL Query

Falls ein unbekannter Recht-Namen angegeben wird, gibt der hasRight-Operator False zurück.

OCL Operatoren für Projekteinträge

Projekteinträge ist der Sammelbegriff für Leistungen, Spesen und Auslagen. Diese wiederum teilen sich auf in offen und verrechnet. Die Zuordnungen zu Projekten, Phasen und Bearbeitern ist im Modell jeweils auf der untersten Ebene definiert, also auf den offenen oder verrechneten Leistungen bzw. Spesen oder Auslagen.

Für den einfachen Zugriff auf Projekt, Phase und Bearbeiter gibt es ab Version 5.7 deshalb folgende Operatoren:

Operator Beschreibung
getProjekt
Liefert das Projekt zurück, auf welches die Leistung, Spese oder Auslage erfasst wurde.
getPhase
Liefert die Projektphase zurück, der die Leistung, Spese oder Auslage zugeordnet ist.
getBearbeiter
Liefert den Projektbearbeiter zurück, welcher die Leistung, Spese oder Auslage erfasst hat.

Beispielsweise eine Liste von Bearbeitern aufgrund von Leistungen einer Rechnung:

leistungen.getBearbeiter->asSet

Bei Vertec Versionen vor 5.7 sind beim Zugriff auf eine Liste mit allgemeinerem Typ (Leistung, Spesen, Auslagen) Casts notwendig. Beispielsweise eine Liste von Bearbeitern aufgrund von Leistungen einer Rechnung:

leistungen->collect(if oclIsTypeOf (VerrechneteLeistung) then oclAsType
 (VerrechneteLeistung).bearbeiter else oclAsType(OffeneLeistung).bearbeiter endif)->asSet

OCL Operatoren für Projektphasen

phaseGetProjekt

In Versionen vor 6.3 haben die Subphasen einer Projektphase keine direkte Verbindung zum Projekt, dem sie zugehören. Der OCL Operator phaseGetProjekt liefert für eine beliebige Phase oder Subphase das Projekt:

self.phaseGetProjekt

Ab Vertec 6.3 kann dafür auch das Member owningProjekt verwendet werden.

Operatoren für Links

usereintrag->getLinks(rolle)Gibt eine Liste von Objekten zurück, die unter dieser Rolle mit dem Eintrag verlinkt sind.
Projektbearbeiter->getLinks('archiveintraege')

Leistungssummenoperatoren

Für die Optimierung von kundenspezifischen Auswertungen mit Expressionordnern und Listenspalten oder zur Verwendung in benutzerdefinierten Berichten steht die beschleunigte Summierung und Gruppierung in Form eines OCL Operators groupLeistungen zu Verfügung. Alle Informationen zu den Leistungssummen-Operatoren finden Sie im Artikel über Leistungssummen.

Datumsoperatoren

date
der date Operator liefert das aktuelle Datum.
now
der now Operator liefert das aktuelle Datum inkl. Zeit
dateToFloat
verwandelt einen Datum/Zeit Wert in eine Fliesskommazahl. Der ganzzahlige Anteil ist die Anzahl Tage seit dem 30.12.1899. Der Bruchteil gibt die Uhrzeit an.
floatToDate
verwandelt eine Zahl in einen Datum/Zeit Wert.
dateToStrGerman
Ab Vertec 6.2. Gibt das Datum in deutschem Datumsformat als String zurück.

Es braucht an gewissen Orten manchmal Datumswerte im deutschen Format, unabhängig von aktuellen Regionaleinstellungen (siehe z.B. von/bis-Argumente bei groupLeistungen Operatoren).

argobject.eval('creationdatetime.datetostrgerman')
year
berechnet das Jahr eines Datumswertes.
month
berechnet den Monat (1-12) eines Datumswertes.
day
berechnet den Tag des Monats eines Datumswertes.
hours
gibt die Stunden des Zeitwertes als integer zurück.
minutes
gibt die Minuten des Zeitwertes als integer zurück.
seconds
gibt die Sekunden des Zeitwertes als integer zurück.
milliseconds
gibt die Millisekunden des Zeitwertes als integer zurück.
incMonth(anzahl)

zählt Anzahl Monate zu einem Datum hinzu. Man kann damit auch retour zählen: date.incMonth(-1) zählt zum Beispiel vom aktuellen Datum einen Monat zurück.

Hinweis: Liegt das Datum am Monatsende und haben die jeweiligen Monate unterschiedliche Anzahl Tage, wird der letzte Tag des gesuchten Monats genommen.

Beispiel: incmonth(-1) auf dem 31.03.2021 ausgeführt ergibt den 28.02.2021.

incDay(anzahl)
zählt Anzahl Tage zu einem Datum hinzu. Man kann damit auch retour zählen: date.incDay(-10) zählt zum Beispiel vom aktuellen Datum zehn Tage zurück.
firstOfYear
berechnet für ein Datum das Datum des ersten Tag des Jahres (1. Januar).
lastOfYear
berechnet für ein Datum das Datum des letzten Tag des Jahres (31. Dezember).
firstOfQuarter
berechnet den ersten Tag des Quartals.
lastOfQuarter

berechnet den letzten Tag des Quartals. Beispiel:

self->groupleistungenP(date.firstOfQuarter.asstring,  date.lastOfQuarter.asstring, '')->collect(minutenintoffen+minutenintverrechnet)->sum
als Spaltenexpression in einer Projektliste zeigt den erfassten Aufwand (offen) im aktuellen Quartal an.
firstOfMonth
berechnet den ersten Tag des Monats.
lastOfMonth
berechnet den letzten Tag des Monats.
mondayOfWeek
berechnet das Datum des Montags einer Woche.
encodeDate
(year, month, day)

berechnet ein Datum aufgrund von Zahlenwerten für Jahr, Monat und Tag. Beispiel: Ordner mit allen Rechnungen, die im Jahr 2012 erstellt wurden:

rechnung->select((datum >= encodeDate(2012,01,01)) and (datum <= encodeDate(2012,12,31)))
formatdatetime
(formatstring)
Formatiert Datum und Zeit gemäss Formatstring (ab Version 5.2.0.15).

Beispiel:

creationdatetime.formatdatetime('c')-> '16.10.2010 15:24:31'

Der Formatstring kann folgendes enthalten:

  • c: Zeigt das Datum im globalen Format Kurzes Datum (ShortDateFormat), gefolgt von der Zeit im globalen Format Lange Uhrzeit (LongTimeFormat). Wenn es keinen Zeitwert hat, erscheint nur das Datum.
  • d: Tag als Zahl ohne vorangestellte 0 (1-31).
  • dd: Tag als zweistellige Zahl (01-31).
  • ddd: Tag als Abkürzung (Mo-So) gemäss globalen Einstellungen (ShortDayNames).
  • dddd: Tag als Wort (Montag-Sonntag) gemäss globalen Einstellungen (LongDayNames).
  • m: Monat als Zahl ohne vorangestellte 0 (1-12). Wenn m direkt auf h oder hh folgt, wird es als Platzhalter für Minuten statt für den Monat interpretiert, und es werden die Minuten angezeigt.
  • mm: Monat als zweistellige Zahl (01-12). Wenn mm direkt auf h oder hh folgt, wird es als Platzhalter für Minuten statt für den Monat interpretiert, und es werden die Minuten angezeigt.
  • mmm: Monat als Abkürzung (Jan-Dez) gemäss globalen Einstellungen (ShortMonthNames).
  • mmmm: Monat als Wort (Januar-Dezember) gemäss globalen Einstellungen (LongMonthNames).
  • yy: Jahr als zweistellige Zahl (00-99).
  • yyyy: Jahr als vierstellige Zahl (0000-9999).
  • h: Stunden ohne vorangestellte 0 (0-23).
  • hh: Stunden als zweistellige Zahl (00-23).
  • n: Minuten ohne vorangestellte 0 (0-59).
  • nn: Minuten als zweistellige Zahl (00-59).
  • s: Sekunden ohne vorangestellte 0 (0-59).
  • ss: Sekunden als zweistellige Zahl (00-59).
  • z: Millisekunden ohne vorangestellte 0 (0-999).
  • zz: Millisekunden als dreistellige Zahl (000-999).
  • t: Zeitwert im Format der kurzen Uhrzeit (ShortTimeFormat), z.B. 11:37.
  • tt: Zeitwert im Format der langen Uhrzeit(LongTimeFormat), z.B. 11:37:40.
  • /: Datumstrennzeichen gemäss globalen Einstellungen (DateSeparator).
  • :: Zeittrennzeichen gemäss globalen Einstellungen (TimeSeparator).
  • xx: Andere Buchstaben und Zeichen werden nicht formatiert, sondern so dargestellt wie eingegeben, z.B. hh...mm ergibt 11...37. Ausnahme: e, g.

OCL Variablen

An gewissen Orten gibt es OCL Variablen, mit welchen auf bestimmte Objekte zugegriffen werden kann. Es sind dies die folgenden:

OCL Variable Verwendung
varLogin
In Expressions auf Berechtigungen kann auf das aktuelle Login über die Variable varLogin zugegriffen werden.
varContainer

Ab Vertec 6.4.0.21. Zugriff in OCL Expressions in Listen auf den Container (Ordner oder LinkContainer).

Neben den Spalten-Expressions in der Liste haben auch die ListExpression und GhostRowListExpression eines Controls Zugriff auf diese Context-Variable.

varContext

Ab Vertec 6.6.0.1. Zugriff in OCL Expressions zur Anpassung von Listeneinstellungen. Enthält den aktuell im Baum ausgewählten Eintrag. Für Container ist der Wert identisch mit varContainer (siehe oben).

Die Variable ermöglicht insbesondere in der Ressourcenplanung die Anpassung von Listen in Abhängigkeit davon, ob eine Ressourcenplanungsansicht für Einzelobjekte oder Listen angezeigt wird.

Sie steht auch in sowie List Controllern und Custom Renderern zur Verfügung. Damit die OCL Variable hier einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert.

varParent

Ab Vertec 6.4.0.21. Zugriff in OCL Expressions in Listen auf das Objekt, dem der Container gehört (Parent-Objekt des Link-Containers).

Neben den Spalten-Expressions in der Liste haben auch die ListExpression und GhostRowListExpression eines Controls Zugriff auf diese Context-Variable.

varStartDate Ab Vertec 6.6.0.1 für die Verwendung in Ressourcenplanungstabellen. Enthält das Start-Datum der aktuellen Ressourcenplanungsansicht:
  • Zeittabelle: Start-Datum des ersten Intervalls in Periode
  • Pivottabelle: Start-Datum des Intervalls

Sie ist verfügbar in Ressourcenplanungsansichten und den zugehörigen List Controllern sowie in den Custom Renderern.

Damit die OCL Variable in List Controllern und Custom Renderern einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert.

Die Container Variablen varContainer und varParent enthalten im Fall eines Einzelobjekts null.

varEndDate Ab Vertec 6.6.0.1 für die Verwendung in Ressourcenplanungstabellen. Enthält das End-Datum der Ressourcenplanungsansicht:
  • Zeittabelle: End-Datum des letzten Intervalls in Periode
  • Pivottabelle: End-Datum des Intervalls

Sie ist verfügbar in Ressourcenplanungsansichten und den zugehörigen List Controllern sowie in den Custom Renderern.

Damit die OCL Variable in List Controllern und Custom Renderern einfach verwendet werden kann, steht bei beiden die self.evalocl() Methode zur Verfügung, welche diesen spezifischen OCL Evaluator verwendet. Die OCL Variable ist nur in diesem Evaluator definiert.

Die Container Variablen varContainer und varParent enthalten im Fall eines Einzelobjekts null.

varView
Ab Vertec 6.6.0.1. Gibt die Art der Listenansicht an. Mögliche Werte sind:
  • default: eine Standard Listenansicht (Container)
  • resources: eine Ressourcenplanungs-Ansicht (Container oder Usereintrag, via Ressourcenplanungsansicht (siehe 2.5) konfiguriert)
  • bi eine BI (Business Intelligence) Ansicht.
Die Variable kann in der Bedingung von Scripts verwendet werden, um zu steuern, in welchen Ansichten das Script im Menü erscheint, z.B. (varView='default') or (varView='bi').
var<Feldname>
Ab Vertec 6.1. Zugriff auf Abfrageparameter in Spalten von SQL- und Expression Ordnern .

Vergleiche

Vergleiche von 2 Werten (meist eine Member-Referenz und eine Konstante) kommen in OCL-Expressions häufig vor, meist als Bedingung in einem select Operator.

Die einfachste Form eines Vergleichs ist der Identitätsvergleich in Form eines "=" Zeichens:

projekt->select(code='ABC')

liefert eine Liste aller Projekte, deren Code genau dem String ABC entspricht. Normalerweise sollte diese Liste nur ein Projekt umfassen.

Weitere Möglichkeiten für Vergleiche bieten die bekannten Operatoren für grösser, kleiner oder ungleich (<, >, <>). Vergleiche lassen sich mit Strings und mit Zahlen durchführen.

Auch Booleans (Wahr/Falsch Werte) können verglichen werden.

Will man einen Boolean Wert auf true abfragen, dann geschieht dies implizit (if aktiv then.. oder bearbeiter->select(aktiv) etc.)

Die folgenden Boolean-Operatoren geben alle oder zurück und dienen dazu, Werte abzufragen, Listen zu filtern etc.

and

Logisches UND, das heisst, beide Elemente, die mit AND zusammengehängt werden, müssen erfüllt sein.

rechnung->select((datum >= encodeDate(2012,01,01)) and (datum <= encodeDate(2012,12,31)))

or

Logisches OR, das heisst, mindestens eines der beiden Elemente, welche mit OR zusammengehängt werden, muss erfüllt sein.

xor

Kontravalentes OR, das heisst, genau eines der beiden Elemente ist erfüllt, entweder das eine oder das andere; weder sind beide zugleich wahr noch beide zugleich falsch.

not

Mit dem not Operator werden Boolean-Elemente auf false abgefragt.

bearbeiter->select(not aktiv)

implies

Ergibt true, wenn das erste Element true und das zweite Element false ist. In jedem anderen Fall gibt dieser Operator false zurück.

String-Vergleiche

Für Stringvergleiche (oder auch: Zeichenketten-Vergleiche) gibt es zusätzlich die Möglichkeit, Teilstrings zu berücksichtigen. Zu diesem Zweck gibt es die folgenden Vergleichs-Operatoren:

sqlLike
Er hat eigentlich nichts mit SQL zu tun, ausser dass das Format des Musterstrings der Konvention im SQL Standard entspricht. sqllike verwendet für den Vergleich einen Musterstring, der Platzhalterzeichen umfassen kann. Das folgende Beispiel liefert alle Projekte, deren Code mit "AB" beginnt:

projekt->select(code->sqllike('AB%'))
sqlLikeCaseInsensitive
Ist gleich wie der vorherige sqllike, jedoch ohne die Gross-/Kleinschreibung zu beachten.

Als Platzhalter können folgende Zeichen verwendet werden:

  • '%': Ersetzt einen beliebig langen String. Z.B. AA% beschreibt alle Strings, die mit AA beginnen.
  • '_': Ersetzt einen einzelnen Buchstaben. Z.B. AA_ beschreibt alle Strings, die mit AA beginnen und danach genau einen beliebigen Buchstaben enthalten.
regExpMatch
Ist der universellste Operator der drei. Er erwartet eine sogenannte Regular Expression (Regulärer Ausdruck). In Vertec können die folgenden grundlegenden Elemente verwendet werden, Gross-/Kleinschreibung wird dabei nicht beachtet:

., *, +, [, ], ^, $, -, \

Bedingungen

Eine OCL-Expression kann auch Bedingungen enthalten. Da eine Expression aber immer einen bestimmten Wert haben muss, sind im Gegensatz zu Programmiersprachen nur if ... then ... else ... endif Konstruktionen möglich. Ein Beispiel für eine if Bedingung folgt im nächsten Abschnitt über Typ Operatoren.

Typ Operatoren (oclType, oclIsTypeOf, oclIsKindOf, oclAsType)

Um herauszufinden, von welchem Typ (Klasse) ein Objekt ist, kann oclType verwendet werden. In einer Listenspalte zum Beispiel kann so der Typ des jeweiligen Eintrags angezeigt werden. Ein Beispiel dafür ist die Spalte Datentyp in der Standardsuche von Vertec.

Fragt man oclType in Expressions oder einem Script ab, muss oclType.asstring abgefragt werden, da der oclType selbst None ist. Die Listenspalten machen das automatisch, an anderen Orten muss dies jedoch explizit geschehen.

Eine ganze Reihe von Operatoren in OCL dient zur Konvertierung von Objekttypen. Natürlich kann der Typ eines Objekts nicht wirklich verändert werden, OCL ist ausschliesslich eine Abfragesprache. Es kann jedoch sein, dass eine Typkonvertierung angegeben werden muss, damit eine OCL-Expression gültig ist.

Ein Beispiel dafür sind Listen von Adresseinträgen. Die Klasse Adresseintrag ist die Basisklasse für die Klassen Person, Paar, Firma, Kontakt, EinfacheAdresse. In den meisten Fällen sind Listen von Adresseinträge vom Typ Collection(Adresseintrag). Nun soll in einer Adressliste das Vornamen-Attribut eines Personen Objekts dargestellt werden. Die OCL-Expression vorname in den Spalteneinstellungen einer Adressliste führt zur Fehlermeldung "vorname is not a member of Adresseintrag".

Um die gewünschte Information (allerdings nur bei Personen) trotzdem anzuzeigen, könnte folgende Expression angegeben werden:

if oclIsTypeOf(Person) then oclAsType(Person).vorname else '' endif

Die Expression bezieht sich auf das jeweilige Objekt in der Liste und enthält gleich zwei Typoperatoren. oclIsTypeOf prüft, ob das Objekt von einem bestimmten Typ ist, und oclAsType bringt den OCL Interpreter dazu, diesen Adresseintrag als Person zu betrachten und das Member vorname zu akzeptieren.

Möchte man wissen, ob ein Objekt ein Adresseintrag ist (egal, ob Person, Firma etc.), dann kann man das abfragen mit oclIsKindOf. Zum Beispiel möchte man in einer Liste mit gemischten Objekten den Namen anzeigen, wenn es eine Adresse ist:

if oclIsKindOf(Adresseintrag) then name.asstring else '' endif

OCL Call Operatoren für Custom Business-Logik

Ab Vertec Version 6.3.0.12. Mit den OCL Call Operatoren können bestimmte Python Methoden aus OCL aufgerufen werden. Das ermöglicht es, Ergänzungen zur Business-Logik in Python zu schreiben und diese an verschiedenen Orten anstelle der fest eingebauten Business-Logik verwenden zu können, z.B. in Scripts und für die Darstellung in Berichten.

Da OCL statisch und streng typisiert ist, braucht es für jede benötigte Kombination aus Rückgabewert und Argumenten einen separaten OCL Operator. Folgende stehen zur Verfügung:

  • callString (-> string)
  • callCurr (-> currency)
  • callCurrDate (date -> currency)
  • callCurrDateDate (date, date -> currency)
  • callStringString (string-> string)
  • callCurrString (string -> float)
  • callCurrDateDateString (date, date, string -> float)

Die OCL Operatoren werden auf BusinessclassesRoot angewendet und haben alle als erstes Argument den Namen der implementierenden Python-Funktion. Dieser Name wird in der Form <Modul>.<Funktionsnamen> angegeben.

Beispiel

Es wird ein Script-Modul namens customlogic angelegt, darin eine Funktion mit der Signatur

def percentofcompletion(project, eff_date)

Der Aufruf in OCL würde dann wie folgt aussehen:
proj->callCurrDate('customlogic.percentofcompletion', somedate), das Ergebnis der OCL Expression ist ein Currency Wert.

Der Name des verwendeten Call Operators enthält den Typ des Rückgabewertes und der Argumente (Rückgabewert Currency "Curr", Argument "Date").

Wichtige Hinweise

Wichtig zu wissen ist, dass es sich bei den Call Operatoren um Abfragen handelt, welche zum Zeitpunkt der Abfrage den ensprechenden Python Code ausführen und dann das Resultat anzeigen. Ändern sich im Hintergrund die Daten, dann hat dies keinen Effekt auf die Resultate der Call Operatoren. Diese werden nicht automatisch neu berechnet, das angezeigte Resultat ist also nur zum Zeitpunkt der Ausführung sicher gültig.

Das führt dazu, dass die Call Operatoren nicht geeignet sind an Orten, wo mit dynamischen Daten gearbeitet werden soll, z.B. zur Anzeige in einer Seite.

Für Listenspalten empfehlen wir, anstelle von Call Operatoren die Custom Renderer zu verwenden, welche subscribed sind, auch Schreibzugriffe erlauben sowie die Möglichkeit bieten, eine Vielzahl von Parametern zu setzen.

Die Call Operatoren eignen sich in folgenden Fällen:

  • In Office-Berichten
  • Via COM Schnittstelle
  • Via XML Abfragen (um z.B. zu erreichen, dass eine externe Applikation die genau gleichen Daten hat)

Zudem sollen mittels Call Operatoren keine Daten verändert, sondern nur Daten gelesen werden. Sie dienen nicht dazu, Vorgänge auszulösen wie beispielsweise in einem Eventscript, sondern rein für den Lesezugriff.

Bitte wählen Sie Ihren Standort