An meiner neuen Arbeit musste ich den Berichtsgenerator von FastReport .Net untersuchen. Früher beschäftigte ich mich mit den anderen Berichtssystemen, wie Crystal Reports und Microsoft Reporting Services. Funktionalität diesen Systemen passte mir, so lange bis ich mit FastReport kennengelernt habe.
Wirklich, ein sehr schönes Produkt mit der stark verbreiteten Funktionalität. Eine der mir besonders gefallenen Features von FastReport .Net ist eine Möglichkeit, Berichten gerade aus dem Code von der Benutzers Anwendung zu erstellen. In diesem Artikel geht es um diese Feuture. Es ist wirklich bequem, wenn man keine große Menge der Dateien braucht, die man mit dem exe-Datei liefert. Außerdem, man kann selbst völlig die Berichtserstellung kontrollieren, wenn man die Aussicht des Objekts nach der Logik der Anwendung ändert.
Bevor alles, erkläre ich, den Unterschied zwischen den Berichterstellung aus dem Code der Benutzers Anwendung und klassischen Berichtsentwicklung im speziellen Designer.
Üblich, der Berichtsgenerator stellt einen speziellen Designer für die Berichtsentwicklung zur Verfügung. Das kann eine IDE Komponente oder einfach ein äußeres Programm sein. Der Entwickler setzt Datenkomponenten auf der Berichtsseite an und bestimmt Eigenschaften der Komponenten. Das sieht gleich aus, wenn man eine Anwendungsform im Windows Forms Projekt konstruiert.
Außer klassischem Verfahren der Berichtserstellung bietet FastReport solche Berichterstellung, wenn man bei der Benutzung gleichen Komponenten den inneren Kode des Berichts verwendet, was für Programmierer viel mehr gewöhnlich ist. Man erstellt zuerst eine Berischtsklasse, in die edie Berichtkomponenten hinzugefügt werden. Weiter bestimmt man eine Datenquelle. Nach einiger Erfahrung wird die Berichterstellung aus dem Code nicht so mehr Zeit als im visuellen Designer dauern. Was interessant ist, kann die Berichtsschablone im visuellen Designer angesehen und gespeichert werden.
Also, betrachten wir jetzt ein Beispiel.
Erstellen wir eine Windows Forms Anwendung auf C# (natürlich soll FastReport .Net zu dieser Zeit installiert werden)
Auf der Form erstellen wir eine Taste, die unseren Bericht starten wird. Später zeigen wir den Bericht nicht nur auf dem Bildschrim, sondern auch wird der Bericht ins PDF exportiert. Dazu hinzugefügen wir auch einen CheckBox.
Erstellen wir einen Eventbearbeiter für einen Tastendruck. Hier wird der ganze Code unserer Anwendung,
Zuerst hinzugefügen wir einen Link auf unsere Bibliothek FastReport.dll (die im Ordner FastReport .Net ist)
Fügen wir Bibliotheken FastReport, FastReport.Utils und FastReport.Data in den using ein.
Erstellen wir ein Examplar der Klasse Report.
1 2 3 4 5 |
private void RunBtn_Click(object sender, EventArgs e) { //Create instance of class Report Report report = new Report(); } |
In unserem Bericht werden die Daten vom Datenlager aufgenommen, dann brauchen wir eine Verbindung mit der Datenquelle:
1 2 3 |
//load data DataSet ds = new DataSet(); ds.ReadXml(AppFolder + "\\nwind.xml"); |
Den Datenlager nahm ich von der Lieferung FastReport .Net im Ordner Reports.
Jetzt braucht man die Datenquelle zu registrieren:
1 2 |
//Register data source report.RegisterData(ds); |
Um die Tabelle aus der registrierten Datenquelle zu benutzen, muss man die einschalten:
1 2 |
//Enable data table report.GetDataSource("Products").Enabled = true; |
Ich denke, dass die Vorbereitungsarbeit fertig ist. Beginnen wir jetzt eine Erstellung der Berichtsschablone. Erstellen wir die Berichtsseite:
1 2 |
//Add report page ReportPage page = new ReportPage(); |
Und fügen die in den Bericht hinzu:
1 |
report.Pages.Add(page);
|
Alle Berichtsobjekten brauchen nur seine einmaligen Namen. Man kann die selbst erstellen und die Eigenschaft „Name“ einsetzen oder man kann die Funktion benutzen, die selbst einen einmaligen Name generiert:
1 |
page.CreateUniqueName();
|
Also, die Berichtsseite ist zur Erfüllung bereit. Erstellen wir einen Band „Gruppentitel“:
1 2 |
//Create GroupHeader band GroupHeaderBand group = new GroupHeaderBand(); |
Fügen wir einen erstellten Band auf die Seite hinzu.
1 2 |
page.Bands.Add(group); group.CreateUniqueName(); |
Erstellen wir die Höhe des Bandes:
1 |
group.Height = Units.Centimeters * 1;
|
Die Bedingungen zu den Gruppierung und Anordnung der Sortierung.
1 2 |
group.Condition = "[Products.ProductName].Substring(0,1)"; group.SortOrder = FastReport.SortOrder.Ascending |
Jetzt braucht man den erstellten Band mit den Daten zu erfüllen. Dazu muss ein Textobjekt mit dem Link auf den Feld von der Datenquelle erstellt werden:
1 2 |
// create group text TextObject groupTxt = new TextObject(); |
Wichtiger Parameter „Parent“, der auf den Band zeigt, in dem ein Textobjekt erstellt wird:
1 2 |
groupTxt.Parent = group; groupTxt.CreateUniqueName(); |
Bestimmen wir jetzt die Größe und Umrandung des Textobjekts:
1 |
groupTxt.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 1);
|
Und, eigentlich, der Text selbst:
1 |
groupTxt.Font = new Font("Arial", 14, FontStyle.Bold);
|
Andere Anstellungen betreffen zur Aussicht des Textes:
1 2 3 |
groupTxt.Text = "[[Products.ProductName].Substring(0,1)]"; groupTxt.VertAlign = VertAlign.Center; groupTxt.Fill = new LinearGradientFill(Color.LightGoldenrodYellow, Color.Gold, 90, 0.5f, 1); |
Und, das, was am interessantesten ist – Erstellung des Bandes „Daten“:
1 2 |
// create data band DataBand data = new DataBand(); |
Setzen wir diesen Gruppenband eine Gruppe ein:
1 2 |
group.Data = data; data.CreateUniqueName(); |
Bestimmen wir eine Datenquelle für den Band „Daten“:
1 2 |
data.DataSource = report.GetDataSource("Products"); data.Height = Units.Centimeters * 0.5f; |
Hier können wir eine Banden Filtration mit Hilfe von der Eigenschaft Filter einsetzen. Jetzt erfüllen wir den Band mit Hilfe vom Textobjekt:
Der Gruppenkeller wird für ein bestimmtes Gruppenexemplar erstellt. Es ist sehr bequem, weil man nichts vermischen kann, wenn es mehrere Gruppentitel im Bericht gibt. So, erstellen wir einen Gruppenkeller:
1 2 3 4 |
// create group footer group.GroupFooter = new GroupFooterBand(); group.GroupFooter.CreateUniqueName(); group.GroupFooter.Height = Units.Centimeters * 1; |
Damit der Keller nicht leer wird, fügen wir in ihn eine Endsumme hinzu, die die Zahl der Lebensmittel in der Gruppe darstellt:
1 2 3 |
// create total Total groupTotal = new Total(); groupTotal.Name = "TotalRows"; |
Bestimmen wir einen Rechnenmethode, einen Band, für den das Rechnen durchgeführt wird, und einen Band, in dem das Ergebnis dargestellt wird. Weil wir nach der Zahl von Elementen suchen, brauchen wir keinen bestimmten Feld zum Rechnen (man macht mit Hilfe von groupTotal.Expression).
1 2 3 |
groupTotal.TotalType = TotalType.Count; groupTotal.Evaluator = data; groupTotal.PrintOn = group.GroupFooter; |
Man soll gefundene Endsumme in den Katalog von Berichts Endsummen hinzugefügen. Sozusagen, um zu registrieren.
1 |
report.Dictionary.Totals.Add(groupTotal);
|
Wie andere beliebige Formeln, die einen Ausdruck brauchen, wird die Endsumme durch einen Textobjekt dargestellt:
1 2 3 4 5 6 7 8 |
// show total in the group footer TextObject totalText = new TextObject(); totalText.Parent = group.GroupFooter; totalText.CreateUniqueName(); totalText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f); totalText.Text = "Rows: [TotalRows]"; totalText.HorzAlign = HorzAlign.Right; totalText.Border.Lines = BorderLines.Top; |
Also, der Bericht ist fertig. Jetzt können wir ihn etweder darstellen oder im Designer starten. Oder können wir ihn sofort ins gebrauchte Datenformate exportieren. Verwenden wir unseren Checkbox, den wir auf die Form hinzugefügt haben:
Wenn CheckBox eingeschaltet ist, wird das Dialogfenster für das Speichern von der PDF-Datei gezeigt. Sonst wird der Bericht in der Vorschauregime gestartet. Hier soll man merken, dass man Export ohne Darstellung des Dialogfensters machen. Sozusagen, „Speichern in der verstecken Regime”. Dann Export sieht so aus:
1 |
export.Export(report, @"C:\Temp\ReportFromCode.pdf");
|
hier das erste Examplar – Berichtersexamplar, und das zweite – Datei mit den Endsummen.
Was haben wir am Ende:
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 78 79 80 81 82 |
//Create instance of class Report Report report = new Report(); //load data DataSet ds = new DataSet(); ds.ReadXml(AppFolder + "\\nwind.xml"); //Register data source report.RegisterData(ds); //Enable data table report.GetDataSource("Products").Enabled = true; //Add report page ReportPage page = new ReportPage(); report.Pages.Add(page); page.CreateUniqueName(); //Create GroupHeader band GroupHeaderBand group = new GroupHeaderBand(); page.Bands.Add(group); group.CreateUniqueName(); group.Height = Units.Centimeters * 1; group.Condition = "[Products.ProductName].Substring(0,1)"; group.SortOrder = FastReport.SortOrder.Ascending; // create group text TextObject groupTxt = new TextObject(); groupTxt.Parent = group; groupTxt.CreateUniqueName(); groupTxt.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 1); groupTxt.Text = "[[Products.ProductName].Substring(0,1)]"; groupTxt.Font = new Font("Arial", 14, FontStyle.Bold); groupTxt.VertAlign = VertAlign.Center; groupTxt.Fill = new LinearGradientFill(Color.LightGoldenrodYellow, Color.Gold, 90, 0.5f, 1); // create data band DataBand data = new DataBand(); group.Data = data; data.CreateUniqueName(); data.DataSource = report.GetDataSource("Products"); data.Height = Units.Centimeters * 0.5f; // create product name text TextObject productText = new TextObject(); productText.Parent = data; productText.CreateUniqueName(); productText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f); productText.Text = "[Products.ProductName]"; // create group footer group.GroupFooter = new GroupFooterBand(); group.GroupFooter.CreateUniqueName(); group.GroupFooter.Height = Units.Centimeters * 1; // create total Total groupTotal = new Total(); groupTotal.Name = "TotalRows"; groupTotal.TotalType = TotalType.Count; groupTotal.Evaluator = data; groupTotal.PrintOn = group.GroupFooter; report.Dictionary.Totals.Add(groupTotal); // show total in the group footer TextObject totalText = new TextObject(); totalText.Parent = group.GroupFooter; totalText.CreateUniqueName(); totalText.Bounds = new RectangleF(0, 0, Units.Centimeters * 10, Units.Centimeters * 0.5f); totalText.Text = "Rows: [TotalRows]"; totalText.HorzAlign = HorzAlign.Right; totalText.Border.Lines = BorderLines.Top; if (PDFCheckBox.Checked) { report.Prepare(); FastReport.Export.Pdf.PDFExport export = new FastReport.Export.Pdf.PDFExport(); export.Export(report); //export.Export(report, @"C:\Temp\ReportFromCode.pdf"); } else report.Show(); |
Und der Bericht selbst:
Und Schlußfolderungen. FastReport .Net erfreut mit noch einem Feature – Berichterstellung aus dem Code. Wann kann das nützlich sein? Wenn Sie keine Lust haben, viele kleinen Dateien mit den Berichtsschablonen zu erstellen. Oder Sie möchten die Schablone innen des Programs verstecken, wenn Sie den Schaden oder unerwünschte Veränderung der Schablone zu verweiden brauchen. Auch es ist bequem, während der Arbeit Ihrer Anwendung die Schablone zu verändern. Das gibt den Berichten eine große Flexibilität und eine gute Möglichkeit nur eine Schablone zu benutzen und sie nach der Programms Logik zu verändern.
Was mich angeht, ist für mich gewöhnlich und bequem, die Berichten im Code zu verwenden. In diesem Fall gibt es nur einen kleinen Unterschied, wenn man den Bericht erstellt oder den Hauptcode einer Windows Anwendung schreibt.