![]() | ![]() | ![]() | ![]() |
||||||||||||||
|
Handbuch ProjectForge® 2011 | ![]() | ||||||||||||||||
![]() |
| ![]() |
|||||||||||||||
|
|||||||||||||||||
| 1 | Vollständiges Funktionsmenü (ohne Dokumentationsmenü). |
| 2 | Die vollindizierte Freitextsuche |
| 3 | Erweiterte Suche für Filterung in der Änderungshistorie |
| 4 | Favoriten/Bookmarks in Listenansichten |
| 5 | Favoriten/Bookmarks in Listenansichten |
| 6 | Erstellen des persönlichen Adress- bzw. Telefonbuchs. |
| 7 | Auswahl der Telefonliste für das Snom-Telefon |
| 8 | Import der Telefonliste in das Snom-Telefon |
| 9 | Animierter Nummernzoom zur vereinfachten Telefonwahl |
| 10 | Direktwahl aus dem Addressbuch heraus |
| 11 | Direktwahl aus dem Addressbuch heraus |
| 12 | Wochen- und monatsweises Blättern |
| 13 | Aufgabenhierarchie in ProjectForge® |
| 14 | Auftragsbuch mit E-Mail-Benachrichtigung |
| 15 | Beispiel eines Diagrammexports |
| 16 | Excelimportbeispiel |
| 17 | Datev-Import, Schritt 1: Auswahl der Importdatei |
| 18 | Datev-Import, Schritt 2: Einlesen der Datei |
| 19 | Datev-Import, Schritt 3: Verproben |
| 20 | Datev-Import, Schritt 4: Prüfen, Selektion und Übernahme |
| 21 | Datev-Import, Schritt 5: Abschluss |
| 22 | Excelformat für Datev-Import des Kontenplans |
| 23 | Excelformat für Datev-Import der Buchungssätze |
| 24 | Zeitberichtsschutz für Aufgaben (inkl. Unteraufgaben) |
| 25 | Zuordnung von Kost2-Kostenträgern zu Aufgaben |
| 26 | Zeitberichte anlegen / ändern mit Kost2-Kostenträgern |
| 27 | iReport: Registrieren des ProjectForge®-Reporting-Jars |
| 28 | iReport: Edit Query |

| Abbildung 1: | Vollständiges Funktionsmenü (ohne Dokumentationsmenü). |

| Abbildung 2: | Über das Suchfeld kann eine vollindizierte Freitextsuche gestartet werden. Dabei können auch Teilwörter eingegeben werden, sowie logische Ausdrücke gebildet werden. |
lucene.apache.org/java/2_4_0/queryparsersyntax.html .
Diese Seite ist auch durch Klick auf das Fragezeichensymbol direkt erreichbar.| Ausdruck | Funktion |
|---|---|
| abc | Es werden alle Objekte gesucht in deren Feldern abc als Wortbeginn vorkommt. |
| *abc* | Es werden alle Objekte gesucht in deren Feldern abc als Wortbestandteil vorkommt. |
| meier~ | Phonetische Suche: Es werden sowohl mayer als auch meier gefunden! |
| abc def | Es werden alle Objekte gesucht in deren Feldern "abc" als Wortbeginn und/oder "def" als Wortbeginn vorkommt. |
| abc* def | Es werden alle Objekte gesucht in deren Feldern Worte mit "abc" beginnend und "def" vorkommen kann. |
| +abc -def | Es werden alle Objekte gesucht in deren Feldern "abc" als Wort vorkommt und "def" nicht vorkommt. |
| name:abc def | Es werden alle Objekte gesucht in deren Feld "name" abc als Wort auftaucht und/oder in beliebigen Feldern "def" vorkommen kann. |
Hinweis
Werden nur alphanumerische Worte (zusätzlich sind die Zeichen @._* überall und +- nicht an erster Stelle erlaubt) eingegeben, so fügt ProjectForge® automatisch Wildcards für die Teilwortsuche ein. Für alle anderen Ausdrücke wird die Suchanfrage unverändert an Lucene weitergereicht. Logische Lucene-Schlüsselworte (AND, OR und NOT) werden nicht modifiziert.
| Ausdruck | Automatische Ersetzung für Lucene |
|---|---|
hallo
|
hallo*
|
hallo ProjectForge
|
hallo* ProjectForge*
|
k.reinhard@projectforge
|
k.reinhard@projectforge*
|
hallo AND 2008-11-21 NOT hurz OR test
|
hallo* AND 2008-11-21 NOT hurz* OR test*
(Ausdrücke, die Sonderzeichen wie -+ enthalten, werden nicht um ein '*' expandiert.) |
hallo AND name:hurzel
|
hallo AND name:hurzel
(keinerlei Ersetzung vorgenommen, da ':' vorkommt.) |
+hallo und hurzel
|
+hallo und hurzel
(keinerlei Ersetzung vorgenommen, da mit '+' beginnend.) |

| Abbildung 3: | Über den erweiterten Filter können Objekte anhand von Änderungszeitpunkten gesucht werden. Die erweiterte Suche erscheint, wenn auf "Erweiterte Suche" rechts neben dem Freitextsuchefeld geklickt wird. |

| Abbildung 4: | Die Abbildung zeigt die Favoriten/Bookmark-Funktionalität innerhalb der Listenansichten. In dem Beispiel enthält der erste Link den direkten Aufruf dieser Seite ohne Parameterübergabe. ProjectForge® würde dann den zuletzt vom User verwendeten Filter verwenden. Der zweite Link enthält auch alle Filterangaben, so dass bei Aufruf dieses Links die Seite mit den identischen Filtereinstellungen aufgerufen wird. |

| Abbildung 5: | Die Abbildung zeigt die Favoriten/Bookmark-Funktionalität innerhalb der Editieransichten. In dem Beispiel enthält der erste Link den direkten Aufruf zur Anzeige des aktuellen Zeitberichts. Der zweite Link enthält den Aufruf der Funktion "Zeitbericht anlegen" mit bereits vorbelegten Feldern (aus den Parametern) heraus. |
Hinweis
Bei der Rückwärtssuche am besten die führende "0" weglassen, da diese bei allen Adressen eigentlich durch eine "+49" ersetzt sein sollte. Diese Funktion ist sinnvoll für entgangene Anrufe.
Hinweis
Bitte im externen Adressbuch UTF-8 als Zeichensatz einstellen!

| Abbildung 6: | Die Abbildung zeigt die Möglichkeit, ganze Adressen oder einzelne Telefonnummern in das persönliche Adressbuch oder die persönliche Telefonliste zu übernehmen. |
| 1 2 3 4 5 6 7 8 9 | tell application "Address Book" repeat with thisPerson in every person if (exists (note of thisPerson)) and ((note of thisPerson) contains "CLASS: WORK") then log "Name: " & (name of thisPerson) delete note of thisPerson end if end repeat save end tell |
Hinweis
Telefonlisten können im Snom-Telefon immer wieder überladen werden, die Snom-Software führt die Listen zusammen, so dass Einträge nicht doppelt vorkommen. Wenn alle Adressen aus ProjectForge® übernommen werden, können bestehende Einträge durch Anwahl der Checkbox "Vorher ganzes Adressbuch löschen" gelöscht werden.

| Abbildung 7: | Über "Datei auswählen" kann die von ProjectForge® exportierte Telefonliste importiert werden. Das Format der Telefonliste ist so gewählt, dass die Standardeinstellungen der Snom-Webseite übernommern werden können. |

| Abbildung 8: |
Ein evtl. vorhandenes Adressbuch kann durch Anwahl der entsprechenden Checkbox gelöscht werden. Andernfalls führt die Snom-Software die
Einträge zusammen, so dass Dupletten nach Möglichkeit verhindert werden. Nachträglich können über die Snom-Webseite auch die Einträge
nachbearbeitet werden (z. B. Löschen möglicher Duplette).
Wichtig ist, dass für die erste Spalte "Name" und für die zweite Spalte "Nummer" aus den Comboboxen gewählt wird. |
PF_Finance
(Finanzbuchhaltung) erhalten die komplette Liste. Für Marketingaktionen o. ä. bitte Rücksprache mit der Finanzbuchhaltung nehmen.
Hinweis
Als erste Adresse wird im Export die so genannte Mailingadresse ausgegeben. Diese ist die postalische Adresse, sofern gegeben, ansonsten die geschäftliche Adresse.

| Abbildung 9: | Animierter Nummernzoom zur vereinfachten Telefonwahl |

| Abbildung 10: | Über das Adressbuch kann durch Anklicken einer Telefonnummer direkt in die Direktwahl gesprungen werden. Anschließend die Return-Taste drücken und der Anruf wird ausgelöst. |
Hinweis
Die Direktwahlseite ist für die Benutzung ohne Maus entworfen, d. h. sie lässt sich schnell über Tasten steuern. Die Returntaste löst auch hier (wie in der gesamten ProjectForge®-Applikation) die Standardaktion aus (hier wählen).

| Abbildung 11: | Über das Adressbuch kann durch Anklicken einer Telefonnummer direkt in die Direktwahl gesprungen werden. Anschließend die Return-Taste drücken und der Anruf wird ausgelöst. |
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78import java.text.*
import org.apache.commons.lang.*
import org.hibernate.criterion.*
import org.projectforge.address.*
import org.projectforge.core.*
import org.projectforge.export.*
xls = reportScriptingStorage.getFile("Kunden_Mailing_Inwest_.xls") // Wurde mit diesem Namen hochgeladen.
ExportWorkbook workbook = new ExportWorkbook(xls);// Verwende vorhandene Exceldatei
ExportSheet sheet = workbook.getSheet("Mailing_neu"); // Hole Sheet mit dem angegebenen Namen
rows = sheet.rows; // Hole alle Zeilen
result = "";
QueryFilter filter = new QueryFilter()
filter.add(Expression.eq("deleted", false))
list = addressDao.getList(filter)
DecimalFormat format = new DecimalFormat("#");
for (int i = 2; i < sheet.rows.size; i++) {
row = sheet.getRow(i);
row.addCell(14) // In Spalte 14 kommen die alten Adresswerte rein.
name = row.getCell(1).getStringCellValue().trim(); // Spalte 1
vorname = row.getCell(2).getStringCellValue().trim(); // Spalte 2
firma = row.getCell(4).getStringCellValue().trim(); // Spalte 4
strasse = row.getCell(10).getStringCellValue().trim(); // Spalte 10
if (row.getCell(11).numericCellType == true) {
plz = format.format(row.getCell(11).getNumericCellValue());
} else {
plz = row.getCell(11).getStringCellValue().trim();
}
ort = row.getCell(12).getStringCellValue().trim(); // Spalte 12
country = row.getCell(13).getStringCellValue(); // Spalte 13
oldAddress = firma + "; " + strasse + "; " + plz + " " + ort + "; " + country;
ll = list.findAll{ entry -> (entry.name.equals(name) && entry.firstName.equals(vorname)) }
if (ll.size > 1)
result += "*** " + name + ", " + vorname + " doppelt.\n";
else if (ll.size < 1)
result += "*** " + name + ", " + vorname + " nicht gefunden.\n";
else {
adr = ll.get(0);
changed = false;
if (StringUtils.equals(StringUtils.defaultString(adr.organization).trim(), firma) == false) {
changed = true;
row.getCell(4).setValue(StringUtils.defaultString(adr.organization));
result += name + ", Firma: " + firma + " -> " + adr.organization + "\n";
}
if (StringUtils.equals(StringUtils.defaultString(adr.mailingAddressText).trim(), strasse) == false) {
changed = true;
row.getCell(10).setValue(StringUtils.defaultString(adr.mailingAddressText));
result += name + ", Straße: " + strasse + " -> " + adr.mailingAddressText + "\n";
}
if (StringUtils.equals(StringUtils.defaultString(adr.mailingZipCode).trim(), plz) == false) {
changed = true;
row.getCell(11).setValue(StringUtils.defaultString(adr.mailingZipCode));
result += name + ", PLZ: " + plz + " -> " + adr.mailingZipCode + "\n";
}
if (StringUtils.equals(StringUtils.defaultString(adr.mailingCity).trim(), ort) == false) {
changed = true;
row.getCell(12).setValue(StringUtils.defaultString(adr.mailingCity));
result += name + ", Ort: " + ort + " -> " + adr.mailingCity + "\n";
}
if (StringUtils.equals(StringUtils.defaultString(adr.mailingCountry).trim(), country) == false) {
if (adr.mailingCountry == null || ("Deutschland".equals(adr.mailingCountry.trim()) == false && "D".equals(adr.mailingCountry.trim()) == false)) {
changed = true;
}
row.getCell(13).setValue(StringUtils.defaultString(adr.mailingCountry));
result += name + ", Country: " + country + " -> " + adr.mailingCountry + "\n";
}
if (changed == true) {
result += name + ", " + vorname + " geändert: " + oldAddress + " \n";
row.getCell(14).setValue(oldAddress);
}
}
}
return result;
return workbook;
Hinweis
Merke: Die leeren Zeitberichte (Pausen) werden für jeden Tag berechnet und werden lediglich angezeigt. Diese Zeitberichte werden nicht in der Datenbank gesichert.

| Abbildung 12: | Wochen- und monatsweises Blättern |

| Abbildung 13: | Aufgabenhierarchie in ProjectForge® |
| Feld | Kurzbeschreibung |
|---|---|
| Übergeordnete Aufgabe | Die Aufgabe ist Unteraufgabe der übergeordneten Aufgabe. Hierüber wird ein Aufgabenbaum definiert, wobei die oberste Aufgabe (Knoten) in ProjectForge® der so genannte Wurzelknoten (Root) ist. Außer dieser Aufgabe, haben alle Aufgaben übergeordnete Aufgaben. Angezeigt werden im Aufgabenbaum auf oberster Ebene alle Aufgaben, die den Wurzelknoten als übergeordnete Aufgabe haben. |
| Name | Der Aufgabenname sollte kurz die Aufgabe kennzeichnen. Aufgabennamen müssen nicht eindeutig sein. |
| Referenz | Dieses Feld kann vielseitig verwendet werden, z. B. für Bestellnummern, Auftragsnummern o. ä.. Die Referenz vererbt sich automatisch auf alle Unteraufgaben, sofern sie dort nicht selber definiert sind. Im Export der Zeitberichte wird auch die Referenz zu jedem Zeitbericht (abgeleitet aus der Aufgabe und ggf. der übergeordneten Aufgaben). |
| Status | Nicht begonnen, begonnen oder geschlossen. In der Baumansicht kann über den Filter eingestellt werden, welche Aufgaben eingeblendet werden sollen. |
| Priorität | |
| Kurzbeschreibung | Wird auch in der Baumansicht angezeigt. |
| Beschreibung | Freitextfeld. |
| Fortschritt | Frei-/Infofeld ohne weiterer Funktion. |
| Maximalstunden | Wenn ausgefüllt, so wird der Verbrauch sowohl in der Aufgabenhierarchie als auch beim Buchen eines Zeitberichts angezeigt, s. 5.1 . |
| Verantwortliche(r) | ProjectForge®-User zur Info. |
| Wiedervorlage | Frei-/Infofeld ohne weiterer Funktion. |
| Frist | Frei-/Infofeld ohne weiterer Funktion. |
| Projekt | Wenn ein Projekt zugeordnet wurde, so müssen alle Zeitberichte zu dieser Aufgabe mit einem dem Projekt verknüpften Kostenträger gebucht weren. Das Projekt vererbt sich. |
| Kost2 | Wenn eine Kost2 zugeordnet wurde, so müssen alle Zeitberichte zu dieser Aufgabe mit diesem Kostenträger gebucht weren. Der Kostenträger vererbt sich. |
| Zeitberichtsschutz | Ist dieses Feld gesetzt, so können Zeitberichte zu dieser Aufgabe und jeder Unteraufgabe nur nach diesem Datum gebucht werden. Zeitberichte mit Zeitangaben bis einschließlich zu dem hier angegeben Datum werden abgewiesen. Nur die Mitarbeiter der Buchhaltung können sich über diesen Zeitberichtsschutz für andere Mitarbeiter hinwegsetzen. Eigene Zeitberichte unterliegen auch dem Schutz. |
| Anzeige | Bedeutung | Tooltip |
|---|---|---|
![]() |
Keine Budgetangabe. | Gesamtverbrauch Tage. |
![]() |
Budgetverbrauch 0-80% | Gesamtverbrauch Tage und Prozentwert. als grün angezeigt. |
![]() |
Budgetverbrauch 80%-90% | Gesamtverbrauch Tage und Prozentwert. |
![]() |
Budgetverbrauch 90%-100% | Gesamtverbrauch Tage und Prozentwert. |
![]() |
Budgetverbrauch über 100% | Gesamtverbrauch Tage und Prozentwert. |
| Anzeige | Bedeutung | Tooltip |
|---|---|---|
![]() |
Keine Budgetangabe. | Gesamtverbrauch Tage. |
![]() |
Budgetverbrauch 0-100% | Gesamtverbrauch Tage und Prozentwert. |
![]() |
Budgetverbrauch 100%-110% | Gesamtverbrauch Tage und Prozentwert. |
![]() |
Budgetverbrauch über 110% | Gesamtverbrauch Tage und Prozentwert. |

| Abbildung 14: | Auftragsbuch mit E-Mail-Benachrichtigung |
Beispiel
Es kann demnach die vollständige Hibernate-Criterion-API verwendet werden. Da der Rückgabewert eine Zeichenkette ist, wird diese einfach ausgegeben.
1
2
3
4
5
6
7
8import org.hibernate.criterion.*
import org.projectforge.core.*
QueryFilter filter = new QueryFilter() // Definiere eine Query
filter.addOrder(Order.asc("username")) // Setze das Sortierkriterium
List userList = userDao.getList(filter) // Hole die Benutzeriste
return "Es wurden " + userList.size + " User gefunden."
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import org.projectforge.core.*
import org.projectforge.timesheet.*
import org.projectforge.common.*
DateHolder date = new DateHolder() // Using the user's current time zone
TimesheetFilter tf = new TimesheetFilter()
date.setDate(2009, Calendar.JANUARY, 01, 00, 00, 00)
tf.setStartTime(date.date)
date.setDate(2009, Calendar.JANUARY, 31, 23, 59, 59)
tf.setStopTime(date.date)
tf.setUserId(17)
List timesheetList = timesheetDao.getList(tf)
return "Es wurden " + timesheetList.size + " Zeitberichte gefunden."
DateHolder.
Beispiel
1
2
3
4
5
6
7
8
9
10
11import org.projectforge.common.*
DateHolder date = new DateHolder() // user's current time zone / locale
date.setDate(2009, Calendar.JANUARY, 01) // CET: 01.01.2009 00:00
String result = "UTC: " + date.date // UTC: Wed Dec 31 23:00:00 UTC 2008
date.setDate(2009, Calendar.APRIL, 01, 17, 03) // CEST: 01.04.2009 17:03
result += ", UTC: " + date.date // UTC: Wed Apr 01 15:03:00 UTC 2009
return result
ExportWorkbook
zurück, so wird für diese Workbook direkt eine Exceldatei erzeugt und zum direkten Download weitergeleitet.
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import org.hibernate.criterion.*
import org.projectforge.core.*
import org.projectforge.export.*
QueryFilter filter = new QueryFilter() // Definiere eine Query
filter.addOrder(Order.asc("username")) // Setze das Sortierkriterium
List userList = userDao.getList(filter) // Hole die Benutzeriste
ExportWorkbook workbook = new ExportWorkbook();// Erzeuge ein neues Workbook
ExportSheet sheet = workbook.addSheet("Users") // Erzeuge ein Tabellenblatt
sheet.contentProvider.colWidths = [10, 20] // setze die Spaltenbreiten auf Zeichenlänge 10 bzw. 20.
sheet.propertyNames = ["username", "lastname"] // Definiere die Properties, die dann die
sheet.addRow().setCapitalizedValues(sheet.propertyNames) // Füge die Kopfzeile hinzu
sheet.addRows(userList) // einzelnen Zeilen füllen
return workbook
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import org.projectforge.core.*
import org.projectforge.export.*
import org.projectforge.timesheet.*
import java.text.SimpleDateFormat
TimesheetFilter tf = new TimesheetFilter()
SimpleDateFormat df = new SimpleDateFormat("dd.MM.yyyy HH:mm")
tf.setStartTime(df.parse("01.01.2009 00:00"))
tf.setStopTime(df.parse("31.01.2009 23:59"))
tf.setUserId(17)
List timesheetList = timesheetDao.getList(tf)
ExportWorkbook workbook = new ExportWorkbook();
ExportSheet sheet = workbook.addSheet("Timesheets")
sheet.contentProvider.colWidths = [10, 20, 15, 10]
sheet.contentProvider.putFormat(java.sql.Timestamp.class,"DD.MM.YYYY hh:mm") // Definiere Format für alle Timestamps
sheet.contentProvider.putFormat("stopTime","hh:mm") // Definiere Format für Property 'stopTime'
sheet.addRow().setValues("Username", "Beschreibung", "StartDate", "StopDate", "fakturiert")
sheet.propertyNames = ["user.username", "description", "startTime", "stopTime", "kost2.kost2Art.fakturiert"]
sheet.addRows(timesheetList)
return workbook
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43import org.fibu.*
import org.fibu.kost.*
import org.projectforge.export.*
import org.projectforge.core.*
class JoinedObject {
BuchungssatzDO satz
EmployeeDO employee
}
// Laden der Liste mit den Buchungsätzen
BuchungssatzFilter filter = new BuchungssatzFilter();
filter.setFrom(2008, 0) // Januar
filter.setTo(2008, 11) // Dezember
def buchungssaetze = buchungssatzDao.getList(filter)
buchungssaetze = buchungssaetze.findAll{ satz -> (5000..5999).contains(satz.konto.nummer) }
// Laden der Liste mit den Usern
def employees = employeeDao.getList().findAll{it.kost1 != null}
def result = new ArrayList()
buchungssaetze.each{bs ->
el = new JoinedObject()
el.satz = bs
el.employee = employees.find{employee -> employee.kost1Id == bs.kost1.id}
result.add(el)
}
// Generieren eines ExcelWorkbooks
ExportWorkbook workbook = new ExportWorkbook();
ExportSheet sheet = workbook.addSheet("Ergebnis")
sheet.contentProvider.colWidths = [10, 10, 8, 8, 10, 10, 20, 20]
sheet.addRow().setValues("Datum", "Betrag", "Konto", "Gegen-konto", "Kost1", "Kost2", "Name")
sheet.contentProvider.putFormat("satz.datum", "DD.MM.YYYY")
sheet.contentProvider.putFormat("satz.betrag", "#,##0.00$;[Red]-#,##0.00$") // English format
sheet.contentProvider.putFormat("satz.konto.nummer", "0")
sheet.contentProvider.putFormat("satz.gegenKonto.nummer", "0")
sheet.propertyNames = ["satz.datum", "satz.betrag", "satz.konto.nummer", "satz.gegenKonto.nummer",
"satz.kost1.formattedNumber", "satz.kost2.formattedNumber", "employee.user.fullname"]
sheet.addRows(result)
return workbook
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import org.projectforge.calendar.*
import org.projectforge.common.*
import org.projectforge.core.*
import org.projectforge.export.*
ExportWorkbook workbook = new ExportWorkbook();// Erzeuge ein neues Workbook
ExportSheet sheet = workbook.addSheet("Test") // Erzeuge ein Tabellenblatt
sheet.contentProvider.colWidths = [20, 20, 20]
sheet.addRow().setValues("Typ", "Precision", "Value")
sheet.addRow().setValues("DayHolder", "Day", new DayHolder())
sheet.addRow().setValues("DateHolder", "Day", new DateHolder().setPrecision(DatePrecision.DAY))
sheet.addRow().setValues("DateHolder", "Minutes", new DateHolder().setPrecision(DatePrecision.MINUTE))
sheet.addRow().setValues("DateHolder", "Seconds", new DateHolder().setPrecision(DatePrecision.SECOND))
sheet.addRow().setValues("DateHolder", "Millis", new DateHolder().setPrecision(DatePrecision.MILLISECOND))
return workbook
Hinweis
ProjectForge®
verwendet standardmäßig auch die Genauigkeit der DateHolder-Objekte. Wenn beim DateHolder Sekunden als Genauigkeit eingestellt sind, so
werden auch die Sekunden ausgegeben. Bei DayHoldern oder einer Genauigkeit von Tagen, so wird nur das Datum ausgegeben.
Alle unterstützten
Genauigkeiten sind:
DAY, HOUR_OF_DAY, MINUTE_15, MINUTE, SECOND, MILLISECOND.
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import org.hibernate.criterion.*
import org.projectforge.core.*
import org.projectforge.export.*
QueryFilter filter = new QueryFilter() // Definiere eine Query
filter.addOrder(Order.asc("username")) // Setze das Sortierkriterium
List userList = userDao.getList(filter) // Hole die Benutzeriste
xls = reportScriptingStorage.getFile("MeinReport.xls") // Wurde mit diesem Namen hochgeladen.
ExportWorkbook workbook = new ExportWorkbook(xls);// Verwende vorhandene Exceldatei
ExportSheet sheet = workbook.addSheet("Users") // Erzeuge ein Tabellenblatt
sheet.contentProvider.colWidths = [10, 20] // setze die Spaltenbreiten auf Zeichenlänge 10 bzw. 20.
sheet.propertyNames = ["username", "lastname"] // Definiere die Properties, die dann die
sheet.addRow().setCapitalizedValues(sheet.propertyNames) // Füge die Kopfzeile hinzu
sheet.addRows(userList) // einzelnen Zeilen füllen
return workbook
Beispiel
DD.MM.YYYY hh:mmZeitstempel mit Minuten DD.MM.YYYY hh:mm:ssZeitstempel mit Sekunden 0Normale Zahlendarstellung ohne Tausendertrennzeichen. #,##0.00$Währungsdarstellung (Dollar) #,##0.00$;[Red]-#,##0.00$Währung in Dollar mit roter Darstellung von negativen Zahlen.
| 1 2 3 | BigDecimal duration = new BigDecimal(durationInMillis / 1000); // Seconds duration = duration.divide(new BigDecimal(60 * 60 * 24), 8, RoundingMode.HALF_UP); // Fraction of day (24 hours) double excelDuration = duration.doubleValue(); |
"[h]:mm"
verwendet werden.

| Abbildung 15: | Beispiel eines Diagrammexports |
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import org.jfree.chart.*
import org.jfree.chart.plot.*
import org.jfree.data.general.*
import org.jfree.util.*
import org.projectforge.export.*
DefaultPieDataset dataset = new DefaultPieDataset()
dataset.setValue("Linux", 15)
dataset.setValue("Mac", 8)
dataset.setValue("Windows", 70)
dataset.setValue("Others", 7)
JFreeChart chart = ChartFactory.createPieChart3D("Users on www.heise.de", dataset, true, true, false)
PiePlot3D plot = (PiePlot3D) chart.getPlot()
ExportJFreeChart export = new ExportJFreeChart(chart, 800, 600)
return export
| 1 2 | sheet.propertyNames = ["user.username", "description", "startTime", "stopTime", "kost2.kost2Art.fakturiert"] |
kost2Art
ein Property von
kost2
und
fakturiert
wiederum ein Property von
kost2Art.
users[3].name
oder
result.userList[0].

| Abbildung 16: | Excelimportbeispiel |
Beispiel
The output is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21import java.text.*;
import org.projectforge.export.*
NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.UK);
xls = reportScriptingStorage.getFile("import-example.xls") // Wurde mit diesem Namen hochgeladen.
ExportWorkbook workbook = new ExportWorkbook(xls);// Verwende vorhandene Exceldatei
ExportSheet sheet = workbook.getSheet("Sheet-1"); // Hole Sheet mit dem angegebenen Namen
rows = sheet.rows; // Hole alle Zeilen
result = "";
total = 0.0;
for (int i = 1; i < sheet.rows.size; i++) {
row = sheet.getRow(i);
no = row.getCell(0).getNumericCellValue();
name = row.getCell(1).getStringCellValue();
amount = row.getCell(2).getNumericCellValue();
total += amount;
result += (int)no + ". The amount of " + name + " is: " + nf.format(amount) + "\n";
}
result += "The total amount is: " + nf.format(total);
return result;
| 1. The amount of Susan is: £50.23 2. The amount of Hugo is: £17.00 3. The amount of Lisa is: £15.00 4. The amount of Mona is: £10.00 The total amount is: £92.23 |

| Abbildung 17: | Datev-Import, Schritt 1: Auswahl der Importdatei |

| Abbildung 18: | Datev-Import, Schritt 2: Einlesen der Datei |

| Abbildung 19: | Datev-Import, Schritt 3: Verproben |

| Abbildung 20: | Datev-Import, Schritt 4: Prüfen, Selektion und Übernahme |

| Abbildung 21: | Datev-Import, Schritt 5: Abschluss |

| Abbildung 22: | Excelformat für Datev-Import des Kontenplans |

| Abbildung 23: | Excelformat für Datev-Import der Buchungssätze |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import org.projectforge.core.* import org.projectforge.export.* import java.text.* year = 2009; month = 4; if (month < 10) monthString = "0" + month else monthString = "" + month NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMANY); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); xls = reportScriptingStorage.getFile("2009-Gehaltslisten.xls") // Wurde mit diesem Namen hochgeladen. ExportWorkbook workbook = new ExportWorkbook(xls);// Verwende vorhandene Exceldatei ExportSheet sheet = workbook.getSheet(year + "-" + monthString); // Hole Sheet mit dem angegebenen Namen rows = sheet.rows; // Hole alle Zeilen String result = ""; for (int i = 4; i < sheet.rows.size; i++) { row = sheet.getRow(i); kost1String = row.getCell(0).getStringCellValue(); employeeName = row.getCell(1).getStringCellValue(); bruttoMitAgAnteil = row.getCell(2).getNumericCellValue(); tantieme_zv = row.getCell(3).getNumericCellValue(); sonderzahlung = row.getCell(4).getNumericCellValue(); kfz = row.getCell(5).getNumericCellValue(); bemerkung = row.getCell(7).getStringCellValue(); gesamt = new BigDecimal(bruttoMitAgAnteil + tantieme_zv + sonderzahlung + kfz).setScale(2, java.math.RoundingMode.HALF_UP); if (employeeName != null) employee = employeeDao.getByName(employeeName); if (kost1String == null) break; kost1 = kost1Dao.getKost1(kost1String); if (kost1 == null) { result += "\n-- **********" + kost1String; } else if (kost1.getDescription().equals(employeeName) == false) { result += "\n-- **********" + kost1.getDescription() + " != " + employeeName; } else if (employee == null) { result += "\n-- ********** Employee '" + employeeName + "' not found."; } else { text = "Excel-Import Kai"; if (tantieme_zv > 0) text += "; Tantieme/Zielvereinbarung/Ueberstunden o. ae.: " + nf.format(tantieme_zv); if (sonderzahlung > 0) text += "; Sonderzahlung: " + nf.format(sonderzahlung); if (kfz > 0) text += "; KFZ: " + nf.format(kfz); if (bemerkung != null && bemerkung.trim().size() > 0) text += "; " + bemerkung; result += "\ninsert into t_fibu_employee_salary (pk,created,last_update,deleted,brutto_mit_ag_anteil,month,type,year,comment,employee_id) values (nextval('hibernate_sequence'),now(), now(),false," + gesamt + ", " + (month - 1)+ ", 'GEHALT', " + year + ",'" + text + "'," + employee.id + ");"; } } return result; |
Hinweis
Mitarbeiter, die nachträglich solche Aufgaben bebuchen möchten, müssten die Zeitberichte unter einer anderen Aufgabe verbuchen und sammeln, und der Buchhaltung das "Umziehen" der Zeitberichte mitteilen. Die Buchhaltung kann dann diese Zeitberichte in den geschützten Bereich verschieben und dies in Nachtragsrechnungen bei Kunden o. ä. berücksichtigen.

| Abbildung 24: | Zeitberichtsschutz für Aufgaben (inkl. Unteraufgaben) |

| Abbildung 25: | Zuordnung von Kost2-Kostenträgern zu Aufgaben |
Hinweis
Wenn Kostenträger fehlen, können diese einem Projekt neu zugeordnet werden (dabei sollte der Status auf "ACTIVE" gesetzt werden.
Wenn Kostenträger nicht mehr erscheinen sollen, so kann dieser entweder aus dem Feld "Kost2" der betroffenen Aufgabe entfernt oder als Projektkostenträger auf "INACTIVE" oder "ENDED" gesetzt werden.

| Abbildung 26: | Zeitberichte anlegen / ändern mit Kost2-Kostenträgern |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <ReportObjective title="Customer ACME" id="ACME" suppressOther="true" suppressDuplicates="true"> <kost1-include>3.*</kost1-include> <kost1-exclude>*.01</kost1-exclude> <kost1-exclude>*.12</kost1-exclude> <kost2-include>5.*</kost2-include> <kost2-exclude>*.02</kost2-exclude> <kost2-exclude>*.11</kost2-exclude> <ReportObjective title="Project ACME-WEB-Portal" id="ACME-WEB-Portal"> <kost2-include>5.020.01.*</kost2-include> </ReportObjective> <ReportObjective title="Project ACME-Java-Migration" id="ACME-Java-Migration"> <kost2-include>5.020.02.*</kost2-include> </ReportObjective> </ReportObjective> |
String.matches(regExp)
für die Auswertung der regulären Ausdrücke verwendet. Die Dokumentation der regulären Ausdrücke ist in der Klasse
java.util.regex.Pattern
zu finden. Zur einfacheren Eingabe modifiziert ProjectForge®
automatisch die Ausdrücke. Alle Punkte werden maskiert und die Wildcards durch
".*" ersetzt. Die Ersetzung kann unterdrückt werden, indem ein
einfaches Hochkomma vorangestellt wird, also beispielsweise "'^5\.510.*" bleibt
(fast) unverändert: es wird lediglich das führende Hochkomma
entfernt.
Hinweis
Ein Child-ReportObjective kann die Buchungssätze des Eltern-ReportObjectives immer nur subselektieren, d. h. die Buchungssätze bilden immer eine Untermenge!Auf die Buchungssätze der Report-Objectives kann direkt zugegriffen werden.
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39import org.fibu.*
import org.fibu.kost.*
import org.projectforge.export.*
import org.projectforge.core.*
class JoinedObject {
BuchungssatzDO satz
EmployeeDO employee
}
// Laden der Liste mit den Buchungsätzen
def buchungssaetze = reportStorage.getCurrentReport().getBuchungssaetze() // Kann über Report-Objectives gewählt werden.
buchungssaetze = buchungssaetze.findAll{ satz -> (5000..5999).contains(satz.konto.nummer) }
// Laden der Liste mit den Usern
def employees = employeeDao.getList().findAll{it.kost1 != null}
def result = new ArrayList()
buchungssaetze.each{bs ->
el = new JoinedObject()
el.satz = bs
el.employee = employees.find{employee -> employee.kost1Id == bs.kost1.id}
result.add(el)
}
// Generieren eines ExcelWorkbooks
ExportWorkbook workbook = new ExportWorkbook();
ExportSheet sheet = workbook.addSheet("Ergebnis")
sheet.contentProvider.colWidths = [10, 10, 8, 8, 10, 10, 20, 20]
sheet.addRow().setValues("Datum", "Betrag", "Konto", "Gegen-konto", "Kost1", "Kost2", "Name")
sheet.contentProvider.putFormat("satz.datum", "DD.MM.YYYY")
sheet.contentProvider.putFormat("satz.betrag", "#,##0.00$;[Red]-#,##0.00$") // English format
sheet.contentProvider.putFormat("satz.konto.nummer", "0")
sheet.contentProvider.putFormat("satz.gegenKonto.nummer", "0")
sheet.propertyNames = ["satz.datum", "satz.betrag", "satz.konto.nummer", "satz.gegenKonto.nummer",
"satz.kost1.formattedNumber", "satz.kost2.formattedNumber", "employee.user.fullname"]
sheet.addRows(result)
return workbook
org.projectforge.reporting.Buchungssatz
erstellen, s. Abb.
27
. Die Dokumentation der Entitäten ist als
Java-Api-Doc hier
zu finden.

| Abbildung 27: | Das Jar sollte erstmalig und bei jeder Änderung registriert werden. |

| Abbildung 28: |
Die Abfrage kann anhand des Beans
org.projectforge.reporting.Buchungssatz
erstellt werden.
|
| Variable | Typ | Kurzbeschreibung |
|---|---|---|
reportStorage
|
ReportStorage |
Der geladene ReportStorage mit allen Buchungssätzen zugeordnet zu den ReportObjectives in dem gewählten Zeitraum.
Package: org.fibu.kost.reporting
|
app
|
String |
Kennung der Applikation:
ProjectForge V. <verstion>
|
appVersion
|
String | Version der Applikation |
appRelease
|
String | Release-Datum der aktuellen Applikationsversion als Text. |
reportList
|
ReportGeneratorList |
Liste der Reports, die mit JasperReport erzeugt werden sollen. Diese Liste wird vom GroovyScript befüllt.
Package: org.fibu.kost.reporting
|
scriptResult.
output
|
String | Wenn ein Ausdruck oder ein Ergebnis noch zusätzlich ausgegeben weden soll. Diese Funktion ist obsulet, wenn gleichzeitig ein Report heruntergeladen wird. |
*Dao
|
ScriptingDao |
Über die ScriptingDaos, wie beispielsweise
timesheetDao
oder
userDao
kann auf die ProjectForge®-Entitäten
direkt zugegriffen werden. Es findet eine volle Zugriffskontrolle durch ProjectForge®
statt.
|
Beispiel
1
2
3
4
5
6
7
8
9
10
11
12
13list = reportStorage.getCurrentReport().getBuchungssaetze(); // Kann über Report-Objectives gewählt werden.
result = list.findAll{ satz -> satz.kost2.kost2Art.fakturiert == false }
report = reportList.addReport()
report.addParameter("test", "hurzel")
report.setBeanCollection(result)
report.addBwa(result)
//scriptResult.output=app + " " + list.size() + " " + result.size()
//return "Umsatzerloese: " + report.getParameter("umsatzErloese")
return reportList
ExportWorkbook
zurück, so wird aus diesem Workbook direkt Excel erzeugt und heruntergeladen. Wie es funktioniert, wird unter
7.4
beschrieben.