Crystal Reports direkt in Salesforce weiterverwenden
mit dem CRGenerator-LWC von Zwernemann Medienentwicklung
Wenn Salesforce-Daten für Geschäftsdokumente verarbeitet werden müssen, reichen klassische PDF-Vorlagen häufig nicht aus.
Crystal Reports ist seit vielen Jahren auf genau solche Anforderungen ausgelegt. Komplexe Formeln, verschachtelte Berichtsstrukturen, Gruppierungen, Unterberichte, laufende Summen, Diagramme und dynamische Seitenlayouts gehören zum klassischen Einsatzbereich von Crystal Reports.
Bei Salesforce-Projekten blieb jedoch meist eine Lücke zwischen den vorhandenen Berichten und den Daten in Salesforce. Entweder mussten Berichte neu entwickelt oder auf externen Reporting-Servern ausgeführt werden.
CRGenerator-LWC schließt genau diese Lücke. Vorhandene Crystal-Reports-Dateien (.rpt) können jetzt direkt in Salesforce ausgeführt werden. Die bestehende Berichtslogik bleibt erhalten, Salesforce liefert die Daten und das Ergebnis ist ein PDF innerhalb des Salesforce-Prozesses.
Warum Berichte oft der schwierigste Teil der Migration sind
In Salesforce-Projekten steht das Berichtswesen selten im Mittelpunkt. Daten, Prozesse und Oberflächen sind geplant, und dann fragt kurz vor dem Go-live jemand, womit die Prüfzeugnisse künftig erzeugt werden.
Dieser Bestand ist selten klein und selten einfach. Über die Jahre haben sich Berichte aufgebaut, die weit mehr tun, als Felder in ein Layout einzusetzen.
Hinzu kommt, dass viele Reporting- und Dokumentengenerierungslösungen nur einen Teil des Funktionsumfangs von Crystal Reports abdecken. Die Herausforderung besteht deshalb oft nicht nur darin, einen Bericht neu zu erstellen, sondern die über Jahre gewachsene Berichtslogik überhaupt wieder abbilden zu können.
Der Ansatz
CRGenerator-LWC führt vorhandene Crystal Reports direkt in Salesforce aus. Die .rpt-Datei bleibt die Berichtsdefinition, Salesforce liefert die Daten, und das Ergebnis ist ein PDF innerhalb des Salesforce-Prozesses.
Dadurch entfallen mehrere typische Integrationsaufgaben gleichzeitig:
- kein externer Reporting-Server
- keine zusätzliche Runtime-Infrastruktur
- keine Übertragung von Berichtsdaten an Drittsysteme
- keine API-basierte Rückübertragung der Ergebnisse
- keine getrennte Benutzer- und Berechtigungsverwaltung
- keine zusätzlichen Betriebs- und Wartungsprozesse
Formeln, Gruppierungen, Unterberichte und Layouts bleiben Bestandteil der ursprünglichen Berichtsdefinition und werden direkt mit Salesforce-Daten ausgeführt.

Das Mapping
Ein Crystal Report wurde gegen ein relationales Datenmodell entwickelt und kennt Strukturen wie CUSTOMER, ORDER oder ORDER_ITEM. In Salesforce heißen dieselben Informationen Account, Order und OrderItem. Die Zuordnung wird außerhalb der Berichtslogik festgelegt:
Customer.Name → Account.Name
Customer.Number → Account.Customer_Number__c
Invoice.TotalAmount → Order.TotalAmount__c
Entscheidend für den Aufwand ist, dass diese Liste nicht geschätzt werden muss: Eine .rpt-Datei enthält die Beschreibung ihrer eigenen Datenquelle, also welche Tabellen, Felder und Verknüpfungen der Bericht tatsächlich verwendet. Sie wird ausgelesen und Zeile für Zeile mit Salesforce-Objekten und -Feldern verbunden, in einem Mapping-Werkzeug, das die ausgelesene Liste anzeigt, statt sie in einer Konfigurationsdatei zu pflegen.
Daraus folgen zwei Dinge, die den Business Case rechenbar machen. Der Aufwand pro Bericht hängt an der Feldzahl, nicht an der Komplexität der Berichtslogik: Formeln, Gruppierungen und Layout sind gar nicht Gegenstand des Mappings, weil sie im Bericht bleiben. Und Berichte auf demselben Datenmodell teilen sich das Mapping. Es werden dreißig Prüfzeugnisse einer Familie einmal zugeordnet, nicht dreißigmal.
Typische Einsatzfelder
Industrie und Maschinenbau
Prüfzeugnisse, technische Dokumentationen und Produktionsberichte.
Kalibrierung und Messtechnik
Kalibrierzertifikate mit Messreihen, Toleranzbändern und Abweichungskurven.
Medizintechnik
Qualitätsdokumentation, Prüfberichte und regulatorische Nachweise.
Labore
Messberichte, Laborprotokolle und Auswertungen.
Qualitätssicherung
Berichte mit komplexen Berechnungen, Gruppierungen und umfangreichen Tabellen.
Wasser- und Umwelttechnik
Messprotokolle, Analysen und Dokumentationsnachweise.

Der Weg nach Salesforce
Ob sich ein Crystal-Reports-Bestand mit CRGenerator-LWC übernehmen lässt, wird vorab anhand der echten Berichte analysiert. Sie liefern lediglich die .rpt-Dateien. Das genügt für eine technische Analyse.
Sie erhalten eine Auswertung Ihres Bestands mit Umfang, Datenmodellen, Sonderfällen, gemeinsam nutzbaren Mappings und einer Einschätzung des Übernahmeaufwands.
Anschließend wird CRGenerator-LWC in Ihrer Salesforce-Org bereitgestellt. Die Crystal-Reports-Dateien werden in Salesforce gespeichert und bleiben weiterhin die Berichtsdefinitionen, aus denen die PDFs erzeugt werden.
Sobald dieses Mapping eingerichtet ist, können vorhandene Crystal Reports direkt mit Salesforce-Daten ausgeführt werden. Neue Berichte können später jederzeit ergänzt werden. Berichte auf demselben Datenmodell nutzen dabei das vorhandene Mapping weiter.
Funktionsumfang
Unterstützt werden insbesondere:
- vollständige Formelbibliothek
- Crystal-Syntax
- Basic-Syntax
- mehrstufige Gruppierungen
- laufende Summen
- Zwischensummen
- Unterberichte
- Parameterverknüpfungen
- Shared Variables
- bedingte Formatierungen
- Datensatzauswahl
- Datensatzsortierung
- Diagramme
- eingebettete Grafiken
- Mehrspaltigkeit
- Textumbruch mit echten Schriftmetriken
- Seitenumbrüche
- dynamische Layouts
Grenzen
Crystal Reports ist über Jahrzehnte gewachsen. Nicht jede Besonderheit jeder Version kann ohne Prüfung zugesichert werden.
Im Einzelfall analysiert werden insbesondere:
- User Function Libraries (UFL) werden unterstützt; die jeweilige Bibliothek des Kunden wird vorab analysiert
- spezielle Exportformate außerhalb PDF
- eingebettete Metafile-Grafiken aus älteren Berichten
- sehr alte Berichte mit historisch gewachsenen Sonderkonstruktionen
Die üblichen produktiven Funktionen sind abgedeckt. Sonderfälle werden vor Projektbeginn identifiziert und bewertet.
Technischer Hintergrund
CRGenerator-LWC liest Crystal-Reports-Dateien nativ.
Eine .rpt-Datei ist kein XML, sondern ein binärer Container im OLE2-Format. Darin liegen mehrere Datenströme, jeder verschlüsselt und komprimiert, und der Bericht steht darin als Folge typisierter Datensätze. CRGenerator-LWC arbeitet diese Struktur in fünf Schritten ab: Container öffnen; Ströme entschlüsseln, wofür Crystal eine eigene Rijndael-Variante mit unterschiedlichen Schlüsseln für Berichtsdefinition und Datenquellenbeschreibung verwendet; entpacken; die Datensätze dekodieren und daraus Berichtsdefinition und Formelbäume aufbauen; und den Bericht schließlich ausführen und auf dem Papierformat paginieren, das in seinen eigenen Druckereinstellungen steht.
Unterberichte sind dabei keine eigenen Dateien, sondern vollständige Berichte in eigenen Speicherbereichen derselben .rpt-Datei, gelesen von demselben Code. In einem der Zertifikate, an denen die Engine entwickelt wurde, steckt praktisch der gesamte Inhalt in 31 solchen Unterberichten.
Drei Eigenschaften sind dabei prüfbar statt zugesichert.
Vollständigkeit
Der Anspruch war nicht, dass ein Parser fehlerfrei durchläuft, sondern dass jeder Datensatz der RPT-Datei vollständig interpretiert wird. Der Nachweis ist ein Bericht, der eingelesen und wieder geschrieben wird und dabei byteidentisch mit dem Original bleibt. Was nicht verstanden wäre, ginge dabei verloren.
Formelsprache
Alle 525 Funktionen der Crystal-Funktionsbibliothek sind implementiert, und zwar in beiden Dialekten: Crystal-Syntax und die häufig als „VBA-Formeln” bezeichnete Basic-Syntax.
Plattformneutralität
Kein eval, kein new Function, kein DOM, kein Canvas, keine Browser- oder Server-spezifischen Objekte. Der XML-Leser ist eigen geschrieben, Text wird über echte Schriftmetriken gemessen. Eine automatische Prüfung geht bei jeder Änderung über jede Quelldatei und bricht den Build ab, sobald eines davon auftaucht. Genau das ist die Voraussetzung dafür, dass die Engine unter der Content-Security-Policy von Salesforce überhaupt lädt, eine Formel wird deshalb als Syntaxbaum ausgewertet und nicht zu JavaScript übersetzt.
Grundsätzliches
Nein. CRGenerator-LWC ist eine eigenständige Neuentwicklung, die das Dateiformat und die Ausführungslogik von Crystal Reports nachbildet. Es läuft keine Crystal-Runtime mit, es wird keine SAP-Komponente installiert und es besteht keine Verbindung zu einem Crystal-Reports-Server. Ihre vorhandenen .rpt-Dateien bleiben unverändert und dienen weiterhin als Berichtsdefinition.
Für die Ausführung in Salesforce nicht. CRGenerator-LWC führt die Berichte selbst aus und benötigt dafür weder eine installierte Crystal-Runtime noch einen Lizenzserver noch native Komponenten auf einem Server. Eine Designer-Lizenz brauchen Sie nur dann, wenn Sie Berichte weiterhin selbst gestalten oder ändern möchten.
Nein. Die vorhandene .rpt-Datei bleibt die Berichtsdefinition und wird unverändert ausgeführt. Angepasst wird nicht der Bericht, sondern die Zuordnung zwischen den Feldern, die der Bericht erwartet, und den Objekten und Feldern in Salesforce. Formeln, Gruppierungen, Unterberichte und Layout bleiben so, wie sie sind.
Sie bleibt erhalten und wird weiter ausgeführt. Gerade bei Prüfzeugnissen und Zertifikaten steckt die fachliche Logik im Bericht selbst: Berechnungen, Toleranzprüfungen, bedingte Darstellungen, mehrstufige Gruppierungen. Genau dieser Teil müsste bei einer Neuentwicklung rekonstruiert und fachlich neu abgenommen werden. Bei CRGenerator-LWC entfällt das, weil der ursprüngliche Bericht ausgeführt wird.
Technik und Salesforce
Nativ, direkt aus der Binärdatei. Eine .rpt-Datei ist kein XML, sondern ein Container im OLE2-Format, in dem mehrere Datenströme liegen — jeder verschlüsselt und komprimiert, und der Bericht darin als Folge typisierter Datensätze. CRGenerator-LWC öffnet den Container, entschlüsselt und entpackt die Ströme, dekodiert die Datensätze und baut daraus die vollständige Berichtsdefinition samt Formelbäumen auf. Anschließend wird der Bericht ausgeführt und auf dem Papierformat paginiert, das in seinen eigenen Druckereinstellungen hinterlegt ist.
Es werden echte .rpt-Dateien gelesen, so wie sie aus dem Crystal Reports Designer kommen. Ein Zwischenformat, ein Export oder eine Konvertierung ist nicht nötig. XML kommt an einer ganz anderen Stelle vor, nämlich als eine von mehreren möglichen Datenquellen eines Berichts.
Die Berichtsverarbeitung läuft nicht in Apex, sondern als JavaScript in der Lightning Web Component. Damit betreffen das CPU-Zeitlimit einer Apex-Transaktion, die Apex-Heap-Grenze und die Grenzen von Batch-Apex die Berichtsausführung nicht, weil an dieser Stelle kein Apex rechnet. Apex wird für die Datenbeschaffung per SOQL gebraucht, und dort gelten die üblichen Grenzen wie Zeilenzahl je Transaktion und Heap-Größe. Praktisch heißt das: Der Skalierungspunkt ist die Datenmenge, nicht die Komplexität des Berichts.
Nein. Es gibt keinen externen Rendering-Dienst, an den Berichtsdaten übertragen werden. Die Berichtsdefinition liegt in der Org, die Daten kommen aus der Org, und die Verarbeitung findet innerhalb der Salesforce-Anwendung statt. Damit entfallen auch die Begleitfragen einer externen Reporting-Anbindung: Schnittstellenabsicherung, getrennte Benutzer- und Berechtigungsverwaltung und der Nachweis, wo Prüfdaten unterwegs waren.
In der Größenordnung von Sekunden, auch bei anspruchsvollen Dokumenten. Ein Zertifikat mit 31 Unterberichten, mehreren hundert platzierten Objekten und über hundert Formelauswertungen benötigt für einen vollständigen Durchlauf rund zwei Sekunden. Der weitaus größte Teil davon entfällt auf das Ausführen der Berichtslogik, nicht auf das Zeichnen der Seiten.
Keines davon wird verwendet. Salesforce setzt in Lightning Web Components eine strenge Content-Security-Policy durch, unter der Code, der zur Laufzeit weiteren Code erzeugt, nicht ausgeführt wird. Eine Berichtsformel wird deshalb als Syntaxbaum ausgewertet statt nach JavaScript übersetzt, der XML-Leser ist eigen geschrieben statt den DOMParser zu nutzen, und Text wird über echte Schriftmetriken gemessen statt über Canvas. Eine automatische Prüfung geht bei jeder Änderung über den gesamten Quellcode und bricht den Build ab, sobald eines dieser Konstrukte auftaucht.
In Salesforce selbst. Die Berichtsdateien werden in der Org gespeichert und bleiben die Definitionen, aus denen die PDFs erzeugt werden. Ein Bericht wird also weiterhin gepflegt, indem die .rpt-Datei ausgetauscht wird, und nicht, indem Code geändert wird.
Migration und Aufwand
Ein Crystal Report wurde gegen ein relationales Datenmodell entwickelt und erwartet Strukturen wie CUSTOMER, ORDER oder ORDER_ITEM; in Salesforce heißen dieselben Informationen Account, Order und OrderItem. Die Zuordnung wird außerhalb der Berichtslogik festgelegt, etwa Customer.Name auf Account.Name. Entscheidend dabei ist, dass sich nichts erraten lässt: Welche Tabellen, Felder und Verknüpfungen ein Bericht tatsächlich verwendet, steht in der .rpt-Datei selbst und wird ausgelesen. Diese Liste wird anschließend Zeile für Zeile mit Salesforce-Objekten und -Feldern verbunden.
Von der Anzahl der Felder, die ein Bericht verwendet, und nicht von seiner Komplexität. Formeln, Gruppierungen, Unterberichte und Layout sind gar nicht Gegenstand der Zuordnung, weil sie im Bericht bleiben und dort ausgeführt werden. Ein Bericht mit anspruchsvoller Rechenlogik, aber überschaubarem Feldbedarf ist deshalb schnell angebunden.
Weniger, als die Zahl vermuten lässt, weil Berichte sich die Zuordnung teilen. Berichte, die auf demselben Datenmodell aufsetzen, werden einmal zugeordnet und nicht einzeln: Dreißig Prüfzeugnisse einer Familie brauchen eine Zuordnung, nicht dreißig. Welche Ihrer Berichte sich so gruppieren lassen, ist eines der Ergebnisse der Bestandsanalyse.
Benötigt werden ausschließlich die .rpt-Dateien: kein Datenbankzugang, keine Installation, kein Zugriff auf Ihr System und keine Produktivdaten. Eine Berichtsdatei enthält ihre Logik und die Beschreibung ihrer Datenquelle selbst, deshalb genügt sie für eine technische Analyse. Zurück erhalten Sie eine Auswertung Ihres Bestands mit den Berichten und ihrem Umfang, den erkannten Datenmodellen, den gemeinsam nutzbaren Zuordnungen, den benannten Sonderfällen und einer Einschätzung des Übernahmeaufwands.
Ja, für die Nutzung fällt eine jährliche Lizenz je Salesforce-Org an. Dafür entfällt auf Ihrer Seite der gesamte Betrieb einer externen Reporting-Infrastruktur: kein Server, der betrieben, aktualisiert und lizenziert werden muss, keine Schnittstelle zwischen Salesforce und einem Reporting-System, die zu pflegen und abzusichern ist, und keine getrennte Benutzer- und Berechtigungsverwaltung. Der Vergleich, der im Gespräch zählt, ist deshalb nicht die Lizenz allein, sondern die Lizenz gegen die heutigen Betriebskosten Ihres Berichtswesens.
Ja, jederzeit. Ein neuer Bericht wird hinzugefügt, indem seine .rpt-Datei bereitgestellt und seine Felder zugeordnet werden. Setzt er auf einem Datenmodell auf, das bereits zugeordnet ist, entfällt auch dieser Schritt weitgehend.
Funktionsumfang und Grenzen
Unterstützt wird der Funktionsumfang, der in produktiven Berichten den Ausschlag gibt: die vollständige Formelbibliothek in beiden Dialekten, mehrstufige Gruppierungen, laufende Summen und Zwischensummen, Unterberichte samt Parameterverknüpfungen und Shared Variables, bedingte Formatierungen, Datensatzauswahl und Datensatzsortierung, Diagramme, eingebettete Grafiken, Mehrspaltigkeit, Seitenumbrüche, dynamische Layouts und Textumbruch anhand echter Schriftmetriken.
Ja, einschließlich der Parameterverknüpfungen und der berichtsübergreifenden Shared Variables. Ein Unterbericht ist technisch keine eigene Datei, sondern ein vollständiger Bericht in einem eigenen Speicherbereich derselben .rpt-Datei, und wird von derselben Engine ausgeführt. Wie tragfähig das ist, zeigen Dokumente, in denen praktisch der gesamte Inhalt in Unterberichten steckt: Bei einem der Zertifikate, an denen die Engine entwickelt wurde, sind es 31.
Ja. Crystal Reports kennt zwei Formeldialekte, die Crystal-Syntax und die Basic-Syntax, und beide werden unterstützt. Die Basic-Syntax ist das, was in der Praxis meist als VBA-Formel bezeichnet wird. Die Funktionsbibliothek steht in beiden Dialekten vollständig zur Verfügung.
Eine UFL ist keine Crystal-Funktion, sondern eine externe Bibliothek, die der Berichtsautor auf seinem Rechner installiert hatte; ohne sie kann auch Crystal Reports selbst den betreffenden Bericht nicht ausführen. CRGenerator-LWC hat dafür einen definierten Einhängepunkt: Eine UFL wird je Bibliothek nachgebildet und registriert, und für eine reale UFL aus einem Kundenbestand ist das bereits umgesetzt. Ob und welche UFLs Ihr Bestand aufruft, ist eine der Fragen, die die Bestandsanalyse beantwortet.
Das wird nicht behauptet, sondern gemessen. Für die Entwicklung liegt ein reales Zertifikat vor, zusammen mit dem PDF, das Crystal Reports selbst daraus erzeugt. Beide Ausgaben werden automatisch verglichen, Textstelle für Textstelle mit ihren Koordinaten, und dieser Abgleich läuft bei jeder Änderung an der Engine erneut. Für Ihre eigenen Berichte lässt sich derselbe Vergleich anhand Ihrer vorhandenen Crystal-Ausgaben führen; das ist Teil dessen, was ein Pilotbericht zeigt.
Beides wird im Einzelfall geprüft statt pauschal zugesichert. Die Ausgabe erfolgt als PDF; weitere Exportformate werden anhand Ihres tatsächlichen Bedarfs bewertet. Dasselbe gilt für eingebettete Metafile-Grafiken aus sehr alten Berichten und für Berichte, die über viele Crystal-Generationen fortgeschrieben wurden und Konstruktionen enthalten, die selbst der Designer nur noch aus Kompatibilitätsgründen kennt. Der Grundsatz lautet: Die üblichen produktiven Funktionen sind abgedeckt, Sonderfälle werden vor Projektbeginn identifiziert und bewertet.
