ReportViewer-Tutorial für Anfänger

    • VB.NET

    Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von VB1963.

      ReportViewer-Tutorial für Anfänger

      Dieses Tutorial beschreibt Mittel und Wege, wie man seine Daten zu Papier oder in eine PDF-Datei etc. bringt.
      Hierbei wird mit VS2010-Professional und in der WinForms-Umgebung gearbeitet und es werden nur lokale Berichte behandelt.
      Dieses Tutorial wird sich kurz und bündig über mehrere Kapitel erstrecken...

      Bitte Fragen zum Tutorial im Fragethread stellen...

      (Teil 1) Allgemeines und Einführung
      (Teil 2) Berichtsparameter und Formelausdrücke
      (Teil 3) Datenbindung und Erstellen einer Tabelle
      (Teil 4) Gruppieren einer Tabelle
      (Teil 5) Unterberichte und Co.
      (Teil 6) Verwenden von Bildern im Report
      (Teil 7) Anwenden eines Hyperlink und Lesezeichens im Report
      (Teil 8) Einbinden eines benutzerdef. Assembly (Formelerweiterung)
      (Teil 9) Direktes Drucken ohne ReportViewer-Steuerelement (neue Version! 11.08.2022)

      VS2010-Express: (für neuere Versionen lese weiter unten...)
      Der ReportViewer wird mit der Express-Version nicht mitgeliefert.
      Hier muss man den ReportViewer nachrüsten...(ReportViewer VS2010 SP1 und Update)
      Der Berichtsdesigner ist in Visual Studio 2010 Express leider auch nicht enthalten und man kann daher keine Berichte via Designer erstellen.
      Es gibt zwar einen umständlichen Ausweg: man erstellt sich den Bericht im Visual Studion Web Developer Express
      und fügt dann den Bericht (.rdlc-Datei) nachher in das VS-Express-Projekt händisch ein.
      Ich bin mir hier nicht sicher, was es dann mit der ReportParametübergabe und der Datenanbindung auf sich hat? - ich habe es auch nie mit der Web Developer Express ausprobiert!
      Besser wäre hier, man kauft sich ein VS-Professional oder höher und man hat damit keine Umstände mehr.

      Allgemeines:
      Zunächst einmal überprüfen wir, ob der Reportviewer überhaupt im VisualStudio integriert ist.
      Man kann in der Toolbox für den Formdesigner nachschauen, ob im Menüknoten Berichterstellung der ReportViewer angeführt ist.

      Wenn er da nicht angezeigt wird, kann man direkt in der Toolbox einfach mit der rechten Maustaste den Menüpunkt Elemente auswählen aufrufen
      und dort im Dialog Toolboxelemente auswählen den ReportViewer anhacken und mit Ok bestätigen.
      In den Projekt-Eigenschaften/Verweise kann man ebenso nachprüfen, ob der ReportViewer vorhanden ist:
      Wenn der ReportViewer niergends zu finden ist, muss er nachinstalliert werden...(ReportViewer VS2010 SP1 und Update)
      Es handelt sich dabei um folgende 5 Microsoft.ReportViewer.xxx.dll's, die für die Entwicklungsumgebung zur Verfügung gestellt werden:
      Die ersten drei Erweiterungen genügen für Basisanwendungen:

      1) Microsoft.ReportViewer.Common.dll
      2) Microsoft.ReportViewer.WinForms.dll (gilt nur für WinForm-Anwendungen)
      3) Microsoft.ReportViewer.WebForms.dll (gilt nur für WebForm-Anwendungen)
      4) Microsoft.ReportViewer.ProcessingObjectModel.dll (sollte die Zielumgebung keinen ReportViewer aufweisen, ist diese .dll noch zusätzlich mit der Anwendung mit zu liefern)
      5) Microsoft.ReportViewer.DataVisualization.dll (wenn in den Berichten noch Diagramme angezeigt werden sollen, wird diese .dll zusätzlich noch gebraucht)
      Die beiden zuletzt angeführten Erweiterungsdateien sind etwas schwierig bereit zu stellen, die stecken etwas tief im Systemordner.
      Mit folgenden Befehlen im Command-Prompt-Fenster findet man diese Erweiterungsdateien für den ReportViewer
      und kopiert sie in einen bekannten Ordner zur Weitergabe für die Zielumgebung:
      cd c:\windows\assembly\GAC_MSIL\Microsoft.ReportViewer.ProcessingObjectModel\ (System Win7 64Bit)
      dir (hier nimmt man dann die höhere Version des ReportViewers)
      cd 10.0.0.0__b03f5f7f11d50a3a\ (so in meinem Fall)
      copy *.dll PfadDenDuKennst
      Bei der DataVisualization.dll geht man genau so vor...

      Reportviewer mit VS2017 Comunity:
      Hier wird das Visual Studio leider auch ohne ReportViewer und Berichtsdesigner ausgeliefert und muss daher manuell nachinstalliert werden...

      Zuerst installieren wir uns den Berichtsdesigner:
      1) Menü: Extras/Extensions und Updates...
      2) im Dialog den Reiter Online auswählen
      3) rechts oben in der Suchmaske rdlc eingeben und danach suchen lassen
      4) den Vorschlag mit Microsoft Rdlc Report Designer for Visual Studio auswählen
      5) den ausgewählen BerichtsDesigner installieren...


      Danach nehmen wir uns den ReportViewer vor:
      1) Als erstes muss ein neues Win-Forms-Projekt erstellt werden (sonst schlägt die Installation fehl!)...
      2) ist bereits ein alter Reportviewer (kleiner Version 14.0.0.0) vorhanden, entfernen wir diesen aus der Tollbox!
      3) Menü: Extras/NuGet-Paket-Manager/Paket-Manager-Konsole
      4) in der Konsole-Befehlszeile PM> Install-Package Microsoft.ReportingServices.ReportViewerControl.WinForms ausführen
      5) nach erfolgreicher Installation folgenden Ordner öffnen: C:\Users\DuAlsUser\.nuget\packages\microsoft.reportingservices.reportviewercontrol.winforms\140.1000.523\lib\net40
      dort findet man dann all die .dll, wie oben abgebildet, mit der Version 14.0.0.0 oder höher...
      6) die Datei Microsoft.ReportViewer.WinForms.dll (Version 14.0.0.0 oder höher) auswählen und kopieren Strg + C
      7) und dann einfach mit der Maus in der Toolbox die gewünschte Rubrik auswählen und den ReportViewer dann dort mit Strg + V ablegen...
      8) das erstellte Projekt kann man dann wieder verwerfen...

      Gegenüber den früheren Versionen kommt nun zusätzlich folgende .dll dazu und auf das sollte man noch genau achten:
      Microsoft.ReportViewer.Design.dll
      Diese Datei ist Zuständig, dass der Reportviewer auf der Form dargestellt wird!
      Früher konnte man ohne Weiteres den Reportviewer von der Toolbox in die Form ziehen und Gut war es.
      Mit VS 2017 muss man zuerst den Verweis auf diese .dll (vlt. noch ein Bug im VS?) richten und dann passt es auch.
      Die Microsoft.ReportViewer.Common.dll und Microsoft.ReportViewer.WinForm.dll werden bei der Übertragung in die Form
      automatisch zu den Verweisen hinzu gefügt...

      Reportviewer mit VS2019 Comunity:
      Wie oben schon erwähnt, war das Installieren ab VS2017 etwas vermurkst...
      Jetzt braucht man ab FW 4.6
      nur mehr bei einem neuen Projekt über die NuGet-Paket-Manager-Konsole folgenden Befehl vorgehen:
      Konsole-Befehlszeile PM> Install-Package Microsoft.ReportingServices.ReportViewerControl.WinForms
      Und schon hat man alle nötigen .dll's und das Control mit den Berichtsdesigner vom richtigen Reportviewer installiert und kann loslegen!
      Das gilt sogar bei VS2017. Siehe dazu näheres
      hier
      Ich werde unten in den Beispielprojekten neben den VS2010 Versionen auch eine Version mit VS2019 anhängen, damit das Tutorial UpToDate bleibt...

      Das ReportViewer-Steuerelement im Designmodus:
      Das ReportViewer-Steuerelement wird in einer Form angewendet indem man ihn von der Toolbox direkt in die Form zieht.
      Das Steuerelement kümmert sich im Designmodus um die Verwaltung aller Berichte, die im Projekt vorhanden sind.
      Seine Aufgaben werden rechts oben im Control (Kästchen mit schwarzen kleinen Pfeil mit weissen Hintergrund) angewählt:
      • Bericht auswählen (beim Öffnen der Form in der Laufzeitumgebung wird sofort der ausgewählte Bericht im ReportViewer angezeigt)
      • Datenquellen auswählen (DataSet und Bindingsouces werden in die Form integriert)
      • Datenquellen erneut binden
      • neuen Bericht entwerfen (es muss eine Datenquelle vorhanden sein...die Assistenten erzeugen sofort eine Datenanbindung an den Bericht)
      Die Berichte können dann im Anschluss mit dem Berichtsdesigner auf die eigenen Wünsche verändert werden.
      (dazu kommen wir aber erst später)

      Das ReportViewer-Steuerelement in der Laufzeitumgebung: (selbsterklärende Symbolleiste)
      Das Steuerelement unterteilt sich in zwei Bereiche:
      [*]Symbolleiste
      [*]Berichtsvorschau-Bereich


      • Seitennavigation
      • Stoppen und Aktualisieren des ausgewählten Berichtes
      • Drucken
      • Zoomfunktion
      • Seite einrichten
      • Suchfunktionen
      • Exportfunktionen (Ein lokaler Bericht kann in eine Excel-, PDF-oder Word-Datei exportiert werden.)
      Sämtliche Funktionen der ReportViewer-Symbolleiste können im Designmodus
      beim Eigenschaftenfenster in der Kategorie Symbolleiste beliebig eingestellt werden.

      Einen leeren Bericht zum Projekt hinzufügen:
      Mit der Maus auf den Projektnamen im Projektmappenexplorer zeigen und dann die rechte Maustaste drücken, danach den Menüpunkt Hinzufügen/Neues Element... auswählen.

      Es erscheint der Dialog Neues Element hinzufügen, wo die leere Berichtsvorlage ausgewählt werden kann.
      Den Bericht (leerer datenungebundener Bericht) auswählen und unten in der Textbox noch einen sinnigen Namen für den Bericht vergeben.
      Anschließend mit OK die Auswahl bestätigen. Der Bericht erscheint dann sofort in der Projektmappe und kann dann mit dem Berichtsdesigner behandelt werden.
      (Bemerkung: Der Berichtsassistent erzeugt einen datengebunden Bericht ... wie oben bei den ReportViewer-Aufgaben im Designmodus beschrieben)

      Wie werden die Einstellungen des Berichtes gespeichert?
      Wenn ein leerer Bericht, wie oben beschrieben, ausgewählt wird, generiert sich automatisch eine leere Berichtsdefinitionsdatei (Report.rdlc) zum Projekt. In dieser Datei werden dann alle Einstellungen des Berichtes gespeichert:
      • eine vollständige Beschreibung aller Datenquellenverbindungen
      • alle Abfragen zum Abrufen von Daten
      • alle Formelausdrücke, die im Ausdrucksgenerator gebildet wurden
      • sämtliche Parameter, eingebettete Bilder, Textfelder und der übrigen Entwurfszeitelemente
      • alle Tablixsteuerelemente wie Tabellen, Matrixelemente und Listen
      • sämtliche Eigenschaften der Berichtselemente und des Berichtslayoutes
      Diese Definitionen und Einstellungen werden als XML-Format in Form der Berichtsdefinitionssprache (RDL, Report Definition Language) in die Berichtsdefinitionsdatei gespeichert. In dieser Datei stehen dann alle Informationen, die dann zum Rendern des Berichtes zur Laufzeit benötigt werden.

      Einfache ReportParameter definieren:
      Die Reportparameter ermöglichen für Berichte noch eine weitere Methode, um Daten für den Bericht bereit zu stellen.

      • man öffnet zuerst den Bericht mit dem Berichtsdesigner
      • dann drückt man Strg+Alt+D oder wählt Menü/Ansicht/Berichtsdaten
      • das Berichtsdaten-Fenster erscheint

      • wie links oben das Bild zeigt, wählt man Neu/Parameter... oder Ordner Parameter mit der rechten Maustaste Parameter hinzufügen... auswählen
      • der Dialog Berichtsparametereigenschaften öffnet sich

      • dort kann man dann die Berichtsparameter definieren, mit sinnigen Namen vergeben und den Datentyp bestimmen
      • Bearbeiten... und Löschen (ohne Kommentar)

      Einfachen Bericht mit dem Berichtsdesigner erstellen:
      Hier wird der leere Bericht mit dem Berichtsdesigner geöffnet und die Toolbox für die Berichtserstellung mit Strg+Alt+X bereitgestellt...


      Die Oberfläche des Berichtsdesigners besteht aus 3 Teilen:
      • Kopfzeile (kann hinzugefügt werden)
      • Textkörper (wird standardmäßig als Grundberichtsfäche angezeigt)
      • Fußzeile (kann hinzugefügt werden)

      Die Berichtsbestandteile: (Textauszug aus MSDN)
      Die Berichtstoolbox stellt Bausteine zum Entwerfen einer Client-Berichtsdefinitionsdatei (RDLC-Datei) in einer visuellen Umgebung bereit.
      Die folgenden Elemente können in einem Bericht verwendet werden.
      • Ein Textfeld wird verwendet, um Daten einer einzelnen Instanz anzuzeigen.
        Textfelder können beliebig in einem Bericht platziert werden und können Bezeichnungen,
        Felder oder berechnete Daten enthalten. Daten in Textfeldern werden mithilfe von Ausdrücken definiert.
      • Eine Tabelle ist ein Datenbereich, den Sie verwenden, um Tabellenberichte zu erstellen oder Tabellenstrukturen zu einem Bericht hinzuzufügen.
      • Eine Matrix ist ein Datenbereich, bei dem Daten in Spalten und Zeilen angeordnet sind, die sich an bestimmten Datenpunkten schneiden.
        Matrizen stellen eine ähnliche Funktionalität wie Kreuztabellen und PivotTables bereit. Während eine Tabelle jedoch einen statischen Satz von Spalten aufweist,
        können Matrixspalten dynamisch sein. Sie können Matrizen definieren, die statische und dynamische Zeilen und Spalten aufweisen.
      • Ein Diagramm ist ein Datenbereich, den Sie verwenden, um visuelle Daten zu erstellen. Sie können eine Vielzahl von Diagrammtypen erstellen.
      • Ein Bild wird verwendet, um binäre Bilddaten in einem Bericht anzuzeigen.
        Sie können externe, eingebettete oder Datenbankbilder im BMP-, JPEG-, GIF- und PNG-Format verwenden.
      • Ein Unterbericht wird verwendet, um einen Bericht in einen anderen einzubetten.
        Dies kann ein vollständiger Bericht sein, der eigenständig ausgeführt wird, oder aber ein Bericht, der am besten wirkt,
        wenn er in den Hauptbericht eingebettet wird. Beim Definieren eines Unterberichts können Sie auch Parameter zum Filtern der Daten im Unterbericht definieren.
      • Eine Liste ist ein Datenbereich, den Sie verwenden, um sich wiederholende Zeilen von Daten für ein einzelnes Feld anzuzeigen.
        Sie kann auch andere Berichtselemente enthalten.
      • Ein Rechteck wird als grafisches Element oder als Container für andere Berichtselemente verwendet.
        Wenn Sie Berichtselemente in einem Rechteck platzieren, können Sie sie zusammen mit dem Rechteck verschieben.
      • Eine Linie ist ein grafisches Element, das Sie an einer beliebigen Stelle auf einer Seite platzieren können. Diesem Element sind keine Daten zugewiesen.
      Allen Elementen in einem Bericht, wie Datengruppen, Tabellen- und Matrixspalten und -zeilen, Berichtselementen sowie dem Bericht selbst sind Eigenschaften zugewiesen.
      Diese Eigenschaften steuern die Darstellung und das Verhalten des jeweiligen Elements.

      Wir bleiben zunächst einmal bei den einfachen Berichtssteuerelementen, wie Textfeld, Linie, Rechteck und ziehen uns nacheinander die Steuerelement auf den leeren Textkörper. Es funktioniert eigentlich fast identisch, wie beim Forms-Designer. Man wählt die Steuerelemente an, kann sie ziehen, schieben und im Eigenschaftenfenster einstellen... Mit der rechten Maustaste kann man ein eigenes Eigenschaftenfenster des angewählten Steuerelementes aufrufen und dort die wichtigsten Eigenschaften einstellen. Wenn man auf den Textkörper klickt und mit der rechten Maustaste auf Einfügen geht, kann man sich dort auch die Berichtssteuerelemente einzeln holen.
      Tipp: Oder man bedient sich am einfachsten mit der oben eingeblendeten Menü-Symbolleiste. Dort werden die wichtigsten Eigenschaften auch angeboten. Da ist man schneller...
      Tipp: Man kann auch nur beliebigen Text direkt in die Textfelder eingeben...
      Tipp: Mit Rechtsklick auf den Textkörper kann man auch die Kopf- und Fußleiste des Berichtes einstellen...
      Tipp: Ich kann nur empfehlen, hier kräftig zu spielen, damit man sich auf die Umgebung eingewöhnt hat...

      Wie bekommt man die definierten Reportparameter in ein Textfeld-Steuerelement:

      [*]mit der rechten Maustaste das Textfeld anklicken und fx Ausdruck... wählen
      [*]es erscheint dann folgender Dialog Ausdruck
      [*]hier links nur mehr auf Parameter gehen und rechts den gewünschten Reportparameter mit Doppelklick auswählen und mit OK bestätigen

      Wenn man zum Beispiel die Executiontime des Reports in ein Textfeld wieder geben will, wählt man oben die integrierten Felder aus...
      Tipp: auch hier wieder kräftig spielen...

      Der nächste Thread zeigt ein Beispiel, wie man einfache Berichts-Parameter benutzen kann.

      Dieser Beitrag wurde bereits 46 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial (Beispiel Berichtsparameter)

      Projekt Verwendung einfacher Berichtsparameter:
      (Ergänzung für den 1.Teil ... ich konnte dort leider die Anhänge nicht mehr bearbeiten)

      In dem angehängten Projekt kann man in der Form Daten vorgeben und in der ReportViewer-Symbolleiste mit Aktualisieren sofort die Daten übertragen...
      In diesem Projekt wurden nur die oben im 1.Kapitel beschriebenen Methoden angewendet...

      Beschreibung des angehängten TestProjektes:
      • Erstellen eines leeren Berichtes
      • einfache Berichtsparameter definieren
      • Kopf- und Fußzeile einstellen
      • Bericht mit Berichtselementen versehen und beliebig formatieren
      • Formelausdrücke für die Berichtsparameter eingeben
      • Dann wurde in der Form ein vertikaler Splitcontainer eingefügt und die Splitterdistanz positioniert und fixiert.
      • Das ober Panel wurde fixiert und die erforderlichen Steuerelemente eingefügt
      • Im unteren Panel wurde der ReportViewer eingefügt und an den übergeordneten Container angedockt
      • Der erstellte Bericht wurde im ReportViewer ausgewählt...
      • Die Symbolleiste des ReportViewers wurde für die Anwendung angepasst


      Ich glaube, der Code erklärt sich von selbst...
      Ein Danke an @ErfinderDesRades: -> Sein Hinweis, dass die beiden Befehle Me.SuspendLayout() und Me.ResumeLayout() in diesem Zusammenhang keine Wirkung haben - und gleich weg mit den beiden! :)

      VB.NET-Quellcode

      1. Option Strict On
      2. Imports Microsoft.Reporting.WinForms
      3. Public Class Form1
      4. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
      5. Aktualisieren()
      6. End Sub
      7. Private Sub Aktualisieren()
      8. 'Me.SuspendLayout()
      9. 'Berichtsparameter an den Report übergeben
      10. Dim pAlter As New ReportParameter("rpAlter", nudAlter.Value.ToString)
      11. Dim pVorName As New ReportParameter("rpVorName", tbxVorname.Text)
      12. Dim pNachName As New ReportParameter("rpNachName", tbxNachName.Text)
      13. With prtReportViewer
      14. .LocalReport.ReportEmbeddedResource = "ReportViewerTutorial.Report_MeinersterBericht.rdlc"
      15. .LocalReport.SetParameters(New ReportParameter() {pAlter, pVorName, pNachName}) ' Parameterübergabe
      16. .RefreshReport()
      17. End With
      18. 'Me.ResumeLayout()
      19. End Sub
      20. Private Sub prtReportViewer_ReportRefresh(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles prtReportViewer.ReportRefresh
      21. Aktualisieren()
      22. End Sub
      23. End Class

      Hinweis: Manchmal kommt es vor, dass die Berichtsparameter nicht mehr aufgelistet werden. Mit der Reset-Methode des Reportviewersteuerelementes prtReportViewer.Reset() kann man hier vorbeugen.
      Dateien

      Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (2.Teil)

      noch mehr über Berichtsparameter:
      Im vorigen Beispiel wurden einfache Berichtsparameter verwendet.
      Aber diese Parameter können noch mehr:
      • man kann in einen Parameter mehrere Werte zuweisen (Array)
      • wenn beim ersten Aufruf keine Werte vorhanden sind kann man auch Standardwerte vorgeben
      Zur Definition eines neuen Berichtparameters ruft man, wie im 1.Teil schon beschrieben wurde, den Dialog Berichtsdaten auf.
      Dann vergibt man bei Allgemein einen sinnigen Namen für den Parameter und stellt den erforderlichen Datentyp dazu ein.
      Die beiden Checkboxen
      • Leeren Wert ("") zulassen
      • Mehrere Werte zulassen
      anhacken...
      Danach das Feld links unten Standardwerte auswählen und die Option Werte angeben vorwählen.
      Mit dem Befehl Hinzufügen kann man dann die gewünschten Standardwerte vorgeben.
      Mit dem Button Ok die Eingaben bestätigen. (siehe die nächsten Bilder...)


      Rechnen mit Formeln und Berichts-Parameter:
      Der Zugriff zu den erstellten Berichtsparameter geschieht im Dialog Ausdruck, dort können auch beliebige Formeln (ähnlich wie im Access) erstellt werden.
      Dieser Dialog wird, wie bereits im 1.Teil geschildert wurde, mit rechter Maustaste über einem Berichtssteuerelement angeklickt und wählt fx Ausdruck...
      Der mehrwertige Berichtsparameter wird immer in folgender Form aufgerufen:

      VB.NET-Quellcode

      1. =Parameters!NameDesParameters.Value(x) 'x ist der 0-basierte Array-Index


      Der Ausdruckseditor besteht aus folgenden Elementen:
      • Ausdrucksfenster
      • Befehls-Kategorie-Liste
      • Befehls-Element-Liste (mit Doppelklick wird der Befehl oben im Ausdrucksfenster eingefügt...)
      • einer Befehlsbeschreibung
      • Beispielanzeige
      In der Kategorie Konstanten erscheinen nur dann Elemente zur Auswahl, wenn bei einer Eigenschaft, die konstante Werte inne hat, der Ausdruckgenerator fx Ausdruck... aufgerufen wurde. (z.B. Hintergrundfarbe eines Textfeldes - hier werden alle Hintergrundfarben mit dem Colorpicker vorgeschlagen)



      Siehe Genaueres über Ausdrücke in Reports hier

      Tipp: in diesem Editor kann man die angebotenen Befehle beliebig im Ausdruck versuchen und miteinander verknüpfen - keine Angst: hier passiert ausser einer Fehlermeldung im Bericht bzw. VS nichts! Dann macht man den Versuch halt wieder rückgängig... Hier empfehle ich auch wieder ausgiebig zu üben, bis das Gespür für dieses Werkzeug gekommen ist.
      Tipp: wenn man umfangreichere Formeln zur Berechnung hat, die bereits die Übersicht einschränken, kann man Teile der Formel oder die Ganzes Formel in den Berichtsvariablen ausgliedern.
      Dazu außerhalb des Berichtkörpers mit der rechten Maustaste auf den Bericht klicken und den Dialog Berichtseigenschaften auswählen.
      Das unterste Feld Variablen anwählen und die Variablen entsprechend definieren (siehe Bild...)
      Diese Variablen kann man dann im Ausdruckseditor fx Ausdruck... wieder weiterverwenden!

      Tipp: Wer mit dem Formelumfang noch nicht das Auskommen hat, der kann sich auch seine eigenen benutzerdefinierten VisualBasic-Funktionen erstellen. Dabei geht man via Bericht/Berichtseigenschaften auf die Option Code und gibt dort im Fenster seine Funktion im VisualBasic-Dialekt ein. Man kann dort genauso Kommentare einfügen, wie es im VisualBasic üblich ist.

      Die Funktion wird dann nach der Angabe des globalen Code-Elementes hinten angestellt und aufgerufen...

      VB.NET-Quellcode

      1. =Code.WochenMo(Now)

      Tipp: Es gibt noch eine weitere Methode zur Befehlserweiterung, die im Kapitel 8 beschrieben wird.

      Man kann auch in anderen Berichtselementen Formeln anwenden. Zum Beispiel das Bild in einem Bildsteuerelement umschalten, wenn ein Schwellwert überschritten wurde.
      Hierzu geht man wieder in die Berichtsdaten und wählt dieses mal Neu/Bild... und sucht sich im Öffenendialog ein Bild aus.
      Dieses Bild wird dann im Bericht eingebettet und steht dann zur Verfügung.
      Mit der rechten Maustaste das Bildsteuerelement anklicken und Allgemein/Bildeigenschaften... wählen.
      Danach mit fx bei Dieses bild verwenden den Ausdruckseditor wieder aufrufen (siehe Bild)

      Hier steht in der Formel Green und Red jeweils für ein zuvor eingebettetes Bild.

      VB.NET-Quellcode

      1. =IIf(Parameters!rpMehrereWerte.Value(2)>18,"Green","Red")

      Überall wo in den Eigenschaften (Sichtbarkeit, Umschaltungen, Größen-, Farb, -Rahmenveränderungen etc.) fx angeführt ist,
      kann man Berechnungen anwenden, die meistens als Rückgabewert ein True oder False erwarten.
      Oder es wird sowieso eine Aktion vorgeschlagen.
      Unten ein Formelausdruck, der die Sichtbarkeit eines Bildes z.B. einstellt...

      VB.NET-Quellcode

      1. =IIF(Parameters!rpMehrereWerte.Value(2)>5 And Parameters!rpMehrereWerte.Value(2)<100,False,True)

      Anbei habe ich wieder ein kleines Beispiel für den 2.Teil des ReportViewer-Tutotials angehängt.
      Hier werden obige Themen gezeigt:
      • Berechnungen mit den Berichtsparametern und den Standardwerten
      • eine Bildumschaltung bei einem Schwellwert (>18) Lebensjahren
      • eine Sichtbarkeitsregel des Bildes (>5 und <100) Lebensjahren

      Der Code ist selbsterklärend und dient zum Probieren und Austesten...

      VB.NET-Quellcode

      1. Option Strict On
      2. Imports Microsoft.Reporting.WinForms
      3. Public Class ReportMitPatameterArray
      4. Dim Werte As New List(Of String)
      5. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
      6. Aktualisieren(Werte)
      7. End Sub
      8. Private Sub prtReportViewer_ReportRefresh(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles prtReportViewer.ReportRefresh
      9. Werte.Clear()
      10. Werte.Add(tbxVorname.Text) '1.Wert
      11. Werte.Add(tbxNachName.Text) '2.Wert
      12. Werte.Add(nudAlter.Value.ToString) '3.Wert
      13. Aktualisieren(Werte)
      14. End Sub
      15. Sub Aktualisieren(Werte As List(Of String))
      16. Dim pParameter As New ReportParameter("rpMehrereWerte", Werte.ToArray) ' Parameter als Array übergeben
      17. With prtReportViewer
      18. .LocalReport.ReportEmbeddedResource = "ReportViewerTutorial.Report_ParameterArray.rdlc"
      19. .LocalReport.SetParameters(New ReportParameter() {pParameter}) ' Parameterübergabe
      20. .RefreshReport()
      21. End With
      22. End Sub
      23. End Class
      Dateien

      Dieser Beitrag wurde bereits 20 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (3.Teil)

      Datenbindung an einen Bericht:
      Die ersten beiden Teile behandelten nur grundlegende Begriffe zur Handhabung eines Berichtes
      und wie man mit dem Ausdruckseditor, der Reportparameter, den einfachen Elementen des Berichtes etc. umgeht.
      Man konnte damit bereits einfache Reports erstellen...

      Dieser Teil versucht zu erklären, wie man eine Datatable an den Bericht bindet und sie dort darstellt.
      Hier in diesem Teil wird auch vorausgesetzt, das bereits ein Dataset mit mindestens einer Tabelle im Projekt vorliegt!
      (dazu verweise ich zu den Tipps zur DB-Programmierung von @ErfinderDesRades:)

      Es gibt jetzt verschiedene Wege, wie man eine Tabelle an einen Bericht bindet...

      1. Der klassische Weg: Man erstellt eine neue Form und zieht den ReportViewer in die Form und arbeitet mit seinen Aufgaben...
        Mit der Aufgabe Neuen Bericht entwerfen... gelangt man zum Dialog Dataseteigenschaften.
        Hier einen sinnigen Namen für die Dataseteigenschaften des Berichtes vergeben. Das hat jetzt nichts mit dem Namen des Dataset vom Projekt zu tun - dieses Dataset wird nicht umbenannt oder dergleichen Dinge, es wird nur für den Bericht ein Namen für seine Datenquelle hinzugewiesen. Diese Quellenbezeichnungen werden dann in den ReportViewer-Aufgaben bei Datenquelle auswählen aufgelistet. Man kann es schon bei der nächsten Combobox-Auswahl sehen, da wird die Datenquelle für den Bericht verlangt. In der Auflistung werden sämtliche Datasets aufgelistet (in normalen Fällen gibt es nur ein Dataset zu Auswahl). Also, nochmals kurz wiederholt: für das Dataset des Projektes ist die Datenquelle eine externe Datenbank (wie Access-DB, SQl-Server, usw.) und für den Bericht ist die Datenquelle das Dataset vom Projekt. Sollte noch kein Dataset für das Projekt angelegt sein, kommt man mit Neu... zum Assistent zum Konfigurieren von Datenquellen... (siehe Bild oben rechts)
        Bei der nächsten Combobox kommt die Verwirrung. Hier haben sich die Herren in Redmond bei der Benamung sauber vertan. Da wird nicht 'Verfügbare Datasets' gemeint, sondern es ist 'Verfügbare Tabellen' gemeint, man sieht es im Inhalt der Auflistung von der Combobox. Und nebenbei in der Listbox werden dann alle Spalten mit Datatypnamen der Tabelle aufgelistet. Ja, wenn nun alles richtig ausgewählt wurde, kann man für den Bericht die Datenquelle bestätigen und zuweisen. Hier wird dann in der Komponentenleiste des Formdesigners sofort ein Dataset, eine Bindingsource und ein Tableadapter, soferne das Dataset mit einer externen DB verknüpft ist, angelegt.
      2. Projekt/Hinzufügen/Berichts-Assistent. Hier gelangt man auch gleich in den Dialog Dataseteigenschaften.
        Es sei denn, es gibt noch kein Dataset im Projekt, dann wird sofort zum Dialog Assistent zum Konfigurieren von Datenquellen... durchgereicht, oder besser gesagt - dieser Dialog drängt sich einfach vor...
      3. Projekt/Hinzufügen/Neues Element... einen neuen leeren Bericht mit sinnigen Namen hinzufügen.
        Von der Toolbox zieht man dann das Tabellensteuerelement in den leeren Report und hier gelangt man auch gleich zum Dialog Dataseteigenschaften.
        Nach den Eingaben im Dialog und deren Bestätigung wird eine 3-spaltige leere Tabelle als Rohform im Bericht dargestellt.
        Es wird nur eine Kopfzeile im leichten Grau und darunter eine Datenzeile dargestellt.

      4. Projekt/Hinzufügen/Neues Element... einen neuen leeren Bericht mit sinnigen Namen hinzufügen.
        Mit Berichtsdaten(Strg+Alt+D)/Neu/Dataset... gelangt man wieder in den Dialog Dataseteigenschaften und dann ein Tabellensteuerelement in den leeren Bericht ziehen...
      Der bessere und übersichtlichere Weg ist der 1. beschriebene Weg, der via Aufgaben des ReportViewers ausgewählt werden kann. Hier ist alles schön beisammen, was man braucht wenn man datengebundene Reports erstellen will.

      Nochmals zu den Aufgaben des ReportViewers:(siehe 3.Bild oben rechts)...
      • Bericht auswählen... (bei Auswahl eines datengebunden Reports, werden die Datenquellen, wenn noch nicht vorhanden, in der Komponentenleiste des Formdesigners sofort generiert)
      • Datenquellen auswählen...(hier wird die Möglichkeit geboten, die vom ausgewählten Report mitgegebenen Datenquellen nochmals zu ändern.)
      • Datenquelle nochmals binden...(die geänderte Datenquelle wird neu angebunden)
      • neuen Bericht entwerfen... (haben wir oben schon teilweise besprochen, unten geht es gleich mit einer Tabelle weiter...)

      Kurzbeschreibung für den Assistenten zum Konfigurieren von Datenquellen...
      Dieser Assistent erscheint nur wenn noch kein typisiertes Dataset im Projekt vorhanden ist und versucht immer eine Verbindung zu einer externen Datenbank herzustellen...
      Man braucht im Groben und Ganzen nur nacheinander folgende Punkte abhandeln und man hat eine Verbindung zu einer DB hergestellt:
      • Datenquellentyp auswählen (hier Datenbank) und Weiter...
      • DataSet auswählen und Weiter...
      • Neue Verbindung...
      • Ändern...
      • deinen Datenanbieter auswählen und OK
      • mit Suche... die Datenbankdatei auswählen und OK (hiermit ist die Verbindungszeichenfolge zur DB bestimmt) Weiter...
      • Tabelle auswählen, Dataset mit sinnigen Namen benennen und fertigstellen...

      Die oben beschriebenen Möglichkeiten zur Datenbindung eines Reports beruhen auf Assistenten, wo es immer ein Dataset mit einer DataTable zur Auswahl gibt.
      Via Code kann man auch eine Bindingsource zwischen Tabelle und Bericht schalten. Mit dieser Bindingsource kann man die Filtereigenschaft setzen und für den Bericht die Daten vorfiltern.
      Eine weitere Möglichkeit besteht darin ein LINQ-aktiviertes DataView an den Bericht zu hängen...

      Das angehängte Test-Projekt zeigt hier die verschiedenen Möglichkeiten der Reportdataenanbindung und eine Möglichkeit, wie man mit mehreren Reports im ReportViewer umgehen kann:
      Es gibt im Testprojekt zwei unabhängige Berichte zum auswählen. Nebenbei kann man dem ausgewählten Bericht noch einen ganz einfachen Filter setzen...
      Die bindReport-Methode bindet aus einer Combobox den ausgewählten Report (DataName) an eine mitgegebene Datenquelle (Datasource).
      Damit es nicht zu Zuordnungsverwechslungen von Bericht zu Datenquelle kommen kann, ist noch eines zu erwähnen und wichtig, dass der Datenquellenname den gleichen Namen trägt wie der Report-Teilname...

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Private Sub cbx_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) _
      2. Handles cbxBerichte.SelectedIndexChanged,
      3. cbxLand.SelectedIndexChanged,
      4. cbxOrt.SelectedIndexChanged
      5. Dim Bericht As String = getItem(cbxBerichte)
      6. Select Case True
      7. Case sender Is cbxBerichte
      8. Select Case Bericht
      9. Case Is = "Personal"
      10. Me.cbxOrt.Enabled = True
      11. Me.cbxLand.Enabled = False
      12. Me.PersonalBindingSource.RemoveFilter()
      13. bindReport(Bericht, Me.PersonalBindingSource) 'Bindingsource zuweisen
      14. Case Is = "Kunden"
      15. Me.cbxLand.Enabled = True
      16. Me.cbxOrt.Enabled = False
      17. bindReport(Bericht, DtsNordwind.Kunden) 'Tabelle zuweisen
      18. End Select
      19. Case sender Is cbxOrt
      20. Dim Ort = getItem(cbxOrt)
      21. If String.IsNullOrEmpty(Ort) Then
      22. Me.PersonalBindingSource.RemoveFilter()
      23. Else
      24. Me.PersonalBindingSource.Filter = String.Concat("Ort = '", Ort, "'"c)
      25. End If
      26. bindReport(Bericht, PersonalBindingSource) 'gefilterte Bindingsource zuweisen
      27. Case sender Is cbxLand
      28. Dim Land = getItem(cbxLand)
      29. If String.IsNullOrEmpty(Land) Then
      30. bindReport(Bericht, DtsNordwind.Kunden) 'Tabelle zuweisen
      31. Else
      32. bindReport(Bericht, (From x In DtsNordwind.Kunden Where x.Land = Land).AsDataView) ' DataView zuweisen
      33. End If
      34. End Select
      35. End Sub
      36. Private Sub bindReport(DataName As String, Datasource As Object)
      37. Dim rds As ReportDataSource = New ReportDataSource()
      38. rds.Name = DataName 'Name der Berichtsdatenquelle (ist auch ein Teil des Reportnamens)
      39. rds.Value = Datasource
      40. With Me.prtReportViewer
      41. .LocalReport.DataSources.Clear()
      42. .LocalReport.DataSources.Add(rds)
      43. .LocalReport.ReportEmbeddedResource = String.Concat("ReportViewerTutorial.Report_", DataName, ".rdlc") 'in Resource eingebetteter Bericht
      44. .RefreshReport()
      45. End With
      46. End Sub

      Es gibt noch eine weitere Möglichkeit einen Bericht an Daten zu binden. Man entwirft selbst ein benutzerdefiniertes Datenobjekt und bindet das erstellte Objekt der Klasse an den Bericht.
      Damit man das Datenobjekt für den Bericht auswählen kann, muss zuvor das ganze Projekt im Menü Erstellen neu erstellt werden.

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Class Tonnage
      2. Public Sub New(Schicht As String, Meister As String, AnzahlMA As Integer, Produktion As Double, Datum As DateTime)
      3. Me.Schicht = Schicht
      4. Me.Meister = Meister
      5. Me.AnzahlMA = AnzahlMA
      6. Me.Produktion = Produktion
      7. Me.Datum = Datum
      8. End Sub
      9. Public Property Schicht() As String
      10. Public Property Meister() As String
      11. Public Property AnzahlMA() As Integer
      12. Public Property Produktion() As Double
      13. Public Property Datum() As DateTime
      14. End Class
      15. Public Class Produktion
      16. Dim rnd As New Random
      17. Private Produktion As List(Of Tonnage)
      18. Public Sub New()
      19. Produktion = New List(Of Tonnage)()
      20. Dim rnd As New Random
      21. For i = 0 To 364
      22. For j = 0 To 2
      23. Dim sch = Convert.ToChar(65 + j)
      24. Dim ma = rnd.Next(10, 21)
      25. Dim pr = rnd.Next(700, 1100) / 13
      26. Produktion.Add(New Tonnage(sch, "Meister" & sch, ma, pr, DateTime.Today.AddDays(i)))
      27. Next
      28. Next
      29. End Sub
      30. Public Function loadProduktion() As List(Of Tonnage)
      31. Return Produktion
      32. End Function
      33. End Class

      VB.NET-Quellcode

      1. Option Strict On
      2. Imports Microsoft.Reporting.WinForms
      3. '
      4. Public Class DruckeDenBericht
      5. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Shown
      6. Dim objData = New Produktion
      7. bindReport("Produktion", objData.loadProduktion())
      8. End Sub
      9. Private Sub bindReport(BerichtName As String, Datasource As Object)
      10. Dim rds As ReportDataSource = New ReportDataSource()
      11. rds.Name = "DataSet1"
      12. rds.Value = Datasource
      13. With Me.prtReportViewer
      14. .LocalReport.DataSources.Clear()
      15. .LocalReport.DataSources.Add(rds)
      16. .LocalReport.ReportEmbeddedResource = String.Concat("ReportViewerTutorial.", BerichtName, ".rdlc") 'in Resource eingebetteter Bericht
      17. .RefreshReport()
      18. End With
      19. End Sub
      20. End Class

      Die folgenden Schritte müssen mit den Assistenten durchgeführt werden:

      Im Dialog Dataseteigenschaften bei Auswahl der Datenquelle den Butten Neu... drücken. Der Dialog Assistent zum Konfigurieren von Datenquellen wird geöffnet. Hier wird aber nicht, wie oben gezeigt wurde, die Datenbank sondern Objekt ausgewählt. Danach kann man sein eigens erstelltes Datenobjekt anhacken und für die Berichtsanbindung verwenden. (siehe oben das rechte letzte Bild...)
      Mit diesen Einstellungen kann man dann genauso fortfahren wie im nächsten Abschnitt weiter beschrieben wird.
      Dateien

      Dieser Beitrag wurde bereits 16 mal editiert, zuletzt von „VB1963“ ()

      :) Unsere erste Tabelle in einem Bericht:

      Nach erfolgter Datenanbindung an den Bericht gibt es wieder zwei verschiedene Vorgehensweisen, wie die Tabelle im Bericht erstellt wird:
      1. Wenn wie oben beim 1. + 2. beschriebenen Weg vorgegangen wurde, erscheint nach der Datenanbindung der Berichtsassistent von selbst und erstellt automatisch die Tabelle im Bericht.
        Die Bilder unten zeigen nacheinander die Informationen, die der Assistent zum Erzeugen der Tabelle braucht:
        Felder anordnen
        Hier ziehen wir links von den verfügbaren Feldern der ausgewählten Tabelle im Dataset die gewünschten Elemente in den Kasten rechts unten.
        Wie man sieht, werden nummerische Felder in Form der Funktion Summe abgelegt. Dieses sollte uns jetzt nicht stören, das macht der Assistent selbst?
        Layout auswählen
        Auf dieser Seite des Dialoges kann man Gruppierungen (dazu kommen wir später noch detailiert) vornehmen, aber auf Grund unserer Elementanordnung ist hier nichts zu ändern.
        Format auswählen
        Hier kann man noch das Aussehen der Tabelle mit vorgefertigten Formaten auswählen...


        Mit Fertig stellen >> wird dann die Tabelle im Bericht vom Assistenten generiert.

        Die erzeugte Summenformel können wir nachher im Berichtsdesigner ganz einfach umändern (siehe Bild rechts unten) indem man in die betroffene Zelle klickt und ganz einfach in der Tabelle das richtige Spaltenelement nochmals auswählt.


      2. Wenn wie oben bei 3. + 4. beschriebenen Weg vorgegangen wurde, haben wir nur eine Rohtabelle im Bericht.
        Diese Tabelle im Bericht müssen wir einstellen und entsprechend formatieren. Zuerst weisen wir alle Spalten, die wir dazu brauchen, der Tabelle hinzu indem wir einfach die Spalten vom Berichtsdatenfenster in die Rohtabelle des Berichtsdesigners verschieben. Oder wir fügen, wie im Bild unten gezeigt wird, die fehlende Spalten unmittelbar links oder rechts hinzu und danach können wir wieder die Zelle mit Rechtsklick anwählen bzw. das blaue rechteckige Zeichen anklicken und das gewünschte Spaltenelement auswählen und der Spalte zuordnen. Wenn alle Spalten in der Tabelle positioniert und zugeordnet sind, wählen wir rechts am grauen Zeilenheader die ganze Zeile aus und bestimmen mit der Menüsymbolleiste für Berichtformatieren die Hintergrundfarbe etc.

      Mit dem Dialog Tablix-Eigenschaften kann man noch einige Eigenschaften der Tabelle ändern.
      So gelangt man zum Dialog: mit der rechten Maustaste über dem linken oberen Eck, grauen oberen Spalten- oder Zeilenkopf klicken und den Dialog Tablix-Eigenschaften... aufrufen (siehe die nächsten beiden Bilder)


      Unser Report ist jetzt lauffähig!
      Er hat aber noch einen Schönheitsfehler. Wenn nämlich die Daten nicht auf eine Seite passen, wird die Spaltenheader-Zeile der Tabelle bei der nächsten neuen Seite nicht angezeigt, obwohl rechts oben in den Tablix-Eigenschaften der Hacken bei Spaltenüberschrift auf jeder Seite wiederholen angehackt ist!
      Da ist noch folgende Einstellung wichtig:
      Bei den Spaltengruppen rechts auf das kleine schwarze Dreieck klicken und die Checkbox Erweiterter Modus anhacken

      Dann erscheinen sämtliche Zeilen und Spalten als (static) gekennzeichnet und danach die oberste (static)-Zeile der Zeilengruppe auswählen - diese Zeile ist für den Spaltenkopf der Tabelle zuständig (die Zeile wird auch parallel in der Tabelle des Designers hervorgehoben). Im rechten Eigenschaftenfenster für das ausgewählte Tablixelement die Eigenschaft RepeateOnNewPage auf True setzen.

      Und jetzt funktioniert der Seitenwechsel auch mit den Spaltenköpfen der Tabelle... :)

      Den Report kann man dann noch mit Kopf- und Fußzeile ausstatten, wo oben im Berichtskopf ein Berichtsname angegeben wird und unten im Seitenfuß eine Seitenangabe von Anzahl Seiten und der Druckzeit steht (siehe im Ausdruckseditor die integrierten Felder). Sollte die Tabelle überbreit ausfallen, in den Berichtseigenschaften die Seite einrichten bzw. den Bericht vom Hochformat in ein Querformat umstellen usw.
      Tipp: auch hier wieder viel probieren (Formatieren, Formeln generieren, ect.) ...

      Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 4)

      Gruppieren von Tabellen mit dem Assistenten:
      Es gibt hierzu wieder unsere 2 Möglichkeiten mit den Assistenten:
      • ReportVieweraufgaben/neuen Bericht erstellen
      • Projekt/Hinzufügen/Neues Element.../Berichtsassistent


      Im oberen Anwendungsfall haben wir alle Elemente bei Felder anordnen in die Werte-Box verschoben und eine normale Tabelle mit einer Detailzeile generiert.
      Hier kann man aber auch eine Gruppierung vornehmen:
      Dabei zieht man ein oder mehrere Felder in die jeweiligen Gruppen-Boxen. Diese beiden Gruppen werden auch im Berichtsdesigner unten im Gruppierungsfenster angezeigt,
      wenn in der Reportmenü-Symbolleiste das Gruppierungsfenster aktiviert wurde.
      • nach Zeilen (...das ist die gängigste Gruppierung)
      • nach Spalten (...hier muss bei den Feldern in der Werte-Box immer eine Aggregatfunktion angewendet werden!
        Diese Art der Gruppierung ist eher selten anzuwenden und vorteilhaft mit Verwendung der interaktiven Gruppierung)
      • nach Zeilen und Spalten (Kreuztabelle! ...hier gilt Gleiches bei den Feldern in der Werte-Box, wie bei den Spalten!
        Dazu kommen wir aber erst weiter unten)
      Im nächsten Dialog des Assistenten wird das Gruppen-Layout des Berichtes eingestellt:
      Die Checkbox Teil-und Gesammtergebnisse anzeigen bestimmt, ob die Gruppe sichtbar ist oder nicht.
      Man kann die Gruppe in einer Blockdarstellung zeigen, wo der Blockname (das ausgewählte Feld) eine Zeile oberhalb oder unterhalb der Teilergebnisse steht.
      Oder man stuft die Tabelle gruppenweise ab. Hierzu wird rechts ein Beispiel im Vorschaufenster gezeigt.
      Die Checkbox Gruppen erweitern/reduzieren ermöglicht bei einer erstellten Gruppe, ob man interaktiv auf dem Bericht die Gruppe auf- bzw. zuklappen kann.
      Nach Bestätigen der Einstellungen wird noch eine Formatvorlage aus einer Liste zum auswählen gefragt und danach der Bericht automatisch erstellt.
      Im erstellten Bericht kann man dann noch den Report nacharbeiten.

      Manueles Gruppieren von Tabellen:
      1. Mit Projekt/Hinzufügen/Neues Element.../Bericht einen neuen leeren Bericht mit sinnigen Namen hinzufügen.
      2. Dann eine Tabelle von der Toolbox auf den leeren Textkörper des Berichtes ziehen und die Reportdatenquelle definieren.
      3. Die gewünschten Spalten vom Berichtsdatenfenster (Stg+Alt+D) in die Rohtabelle ziehen.

      4. Falls das Gruppierungsfenster im unteren Bereich noch ausgeblendet ist, über die Menüsymbolleiste Bericht bei Gruppierung die Checkbox aktivieren.
      5. Bei der Zeilengruppe (Details) das kleine schwarze Dreieck anklicken und im Kontextmenü Gruppe hinzufügen auswählen.
        Dann mit Übergeordnete Gruppe... den Dialog Tablix-Gruppe aufrufen.

      6. Das gewünschtes Feld bei der Combobox Gruppieren nach auswählen.

      7. Die Checkboxen Gruppenkopf und -fuß anwählen und den Dialog bestätigen.
        Gruppierung: man achte auf die geschwungene Klammer im Zeilenheader und die leicht grauen eckigen Klammern links in den Zellen (siehe Grundlegendes hier...)

      8. Man sieht jetzt im Beispiel die Gruppierung und das sich in der Spalte Bestimmungsland das Land sich in jeder Zeile wiederholen wird. Daher kann man diese Spalte löschen.
        Am Tablixspalten-Header mit Rechtsklick Spalten löschen wählen.

      9. Danach kann man, je nach dem der Layout-Wunsch ist, im Gruppenkopf oder -fuß die Spalte auswählen, wo eine Aggregation erwünscht ist (im Bild sind das die Frachtkosten).
      10. Die Aggregatfunktion kann dann über Rechtsklick der Maustaste bei fx Ausdruck... im Ausdruckseditor (siehe Kategorie Datasets) erstellt werden.

      Tipp:
      Hier erweist es sich oft, das man einige nebeneinander liegende Zellen zusammenfügen möchte und in diesem zusammengeführten Bereich die nebenstehende Aggregierung bezeichnen will.
      Einfach die Zellen auswählen und mit Rechtsklick im Kontextmenü Zellen zusammenführen anklicken.


      Das Bearbeiten funktioniert beim spaltenweise Gruppieren ähnlich, wie oben gezeigt...
      Hier ist auch wieder viel Üben angesagt, damit man mit den einzelnen Kontextbefehlen und den Dialogen vertraut wird.
      Das angehängte kleine Beispielprojekt zeigt die Unterschiede, der einzelenen Gruppierungsmethoden im fertigen Bericht an.
      Diese Berichte kann man wieder in der Combobox nacheinander auswählen und ansehen...
      Dateien

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VB1963“ ()

      Zunächst die Unterschiede der folgenden 3 Berichtssteuerelemente: (gekürzte Auszüge aus TechNet)
      • In einer Tabelle werden die Daten nach Zeilen gruppiert. Die Tabelle wird nach unten erweitert. Die Zeilengruppen können geschachtelt oder nebeneinander angeordnet werden. Eine Zeilengruppe zeigt für jeden Wert in der Gruppe eine dynamische Zeile an, die nach unten erweitert wird. Es können auch statische Zeilen für Bezeichnungen oder Gesamtwerte hinzugefügt werden.
      • In einer Matrix werden Daten angezeigt, die nach Zeilen und Spalten gruppiert sind. Die Matrix stellt ähnliche Funktionen wie Kreuztabellen und dynamische PivotTable-Ansichten bereit. Sie verfügt mindestens über eine Zeilengruppe und eine Spaltengruppe. Die Matrix wird für Spaltengruppen zur Seite und für Zeilengruppen nach unten erweitert. Die Matrixzellen enthalten zusammengefasste und aggregierte Werte für die Schnittmengen der Zeilen- und Spaltengruppen. Es können zusätzliche geschachtelte Gruppen und benachbarte Gruppen erstellt werden. Es können auch statische Zeilen für Bezeichnungen oder Gesamtwerte hinzufügt werden.
      • In einer Liste werden Daten im freien Format angezeigt. Man kann die Liste zum Entwerfen eines Formulars oder zum Anzeigen einer Tabelle und eines Diagramms verwenden. Die Textfelder können an einer beliebigen Position in der Liste angeordnet werden. Die Listenzeile wird für jeden Wert im Dataset einmal wiederholt.
      Der Tabellen-, der Matrix- und der Listendatenbereich werden in der Toolbox durch Vorlagen für den zugrunden liegenden Tablix-Datenbereich dargestellt. Wenn eine dieser Vorlagen hinzugefügt wird, generiert der Berichtsdesigner automatisch einen Tablix-Datenbereich, der für die Vorlage sein spezifisches Datenlayout zeigt. Standardmäßig werden von einer Tabellenvorlage Detaildaten in einem Rasterlayout angezeigt, während eine Matrix Gruppendaten in einem Rasterlayout und eine Liste Detaildaten in einem Freiformlayout anzeigt.

      Das Bild links oben zeigt die 3 Layouts (Tabelle, Matrix und Liste) und das Bild rechts oben die Berichtssteuerelemente, die tatsächlich vom Berichtsdesigner generiert wurden...
      Jede Tablix-Zelle in einer Tabelle oder Matrix enthält standardmäßig ein Textfeld. Die Zelle in einer Liste enthält ein Rechteck. Sie können ein Standardberichtselement durch ein anderes Berichtselement ersetzen, z. B. durch ein Bild. Beim Definieren von Gruppen für eine Tabelle, Matrix oder Liste fügt der Berichts-Designer dem Tablix-Datenbereich Zeilen und Spalten hinzu, in denen die gruppierten Daten angezeigt werden.

      Grundlage für das Verständnis des Tablix-Datenbereichs sind folgende Konzepte:
      • Der Unterschied zwischen Detaildaten und gruppierten Daten
      • Gruppen, die als Zeilengruppen auf der horizontalen Achse und als Spaltengruppen auf der vertikalen Achse als Elemente von Gruppenhierarchien organisiert sind.
      • Der Zweck von Tablix-Zellen in den vier Bereichen eines Tablix-Datenbereichs: Text, Kopfzeilen von Zeilengruppen, Kopfzeilen von Spaltengruppen und Ecke
      • Statische und dynamische Zeilen und Spalten sowie deren Beziehung zu Gruppen
      Mit Berichts-Assistent eine Kreuztabelle erstellen (zeilen- und spaltenweises Gruppieren):

      Bei Kreuztabellen werden immer Aggregierungen von Datenansammlungen im Schnittpunkt der Zeilengruppe und der Spaltengruppe verlangt und durchgeführt.
      Man kann somit eine Zeilensumme in Abhängigkeit einer Spaltengruppe oder umgekehrt durchführen und somit den Bericht konzentrieren.
      1. Projekt/Neues Element hinzufügen.../Berichts-Assistent und einen sinnigen Berichtsnamen vergeben ... der Dialog Berichts-Assistent wird aufgerufen.
      2. Bei der Option Felder anordnen werden die gewünschten Felder in die Boxen Zeilen- und Spaltengruppen gezogen und die aggregierenden Felder in der Werte-Box gezogen (siehe dazu das nächste Bild links unten)
      3. Danach das gewünscht Layout bestimmen (im Beispiel: Als Block, Teilergebnis unterhalb und keine Interaktion der Gruppen) und danach eine Formatvorlage auswählen und die Einstellungen bestätigen
      4. Im Textkörper des Berichtes wird dann eine Kreuztabelle generiert, die man dann noch händisch etwas nach belieben anpassen kann. Textfeld auswählen und mit Textfeldeigenschaften... (Textausrichtung, Zahlenformate, etc...) die Textfeldformatierung durchführen.


      Diesen Kreuztabellen-Bericht jetzt manuell erstellen:
      1. Mit Projekt/Neues Element hinzufügen.../Bericht einen leeren Bericht wählen und einen sinnigen Berichtsnamen vergeben.
      2. Ein Matrix-Steuerelement (ein Layout für einen Tablix-Datenbereich) auf den Textkörper des leeren Berichtes ziehen.
      3. Hier werden im Anschluss die Dataseteigenschaften (Datenanbindung an den Bericht) abgefragt.
        Dazu werden im Beispiel die Daten eines benutzerdefinierte Datenobjektes verwendet.
      4. Vom Berichtsdatenfenster (Strg+Alt+D) werden nun
        • das Feld Partie in die Spaltenzelle,
        • das Feld AnzahlMA in die Zeilenzellegezogen und
        • das Feld Produktion in die Wertezelle gezogen.
        • Das Feld Ausschuss wird zusätzlich neben die Produktion in der Wertezelle plaziert.
          Hier wird beim Ziehen rechts oder links eine blaue Markierung neben der Wertezelle sichtbar.
          Das Feld Ausschuss wird rechts neben der Produktion als neue Wertezelle angelegt.
        Die nächsten beschriebenen Befehle erreicht man mit der rechten Maustaste am betroffenen Objekt (Zeilen- und Spaltenheader oder Zelle) über das angezeigte Kontextmenü.
      5. Jetzt wird eine zusätzliche Zeilen-Gruppierung neben dem Feld AnzahlMA eingefügt.
        • Letzten Zeileheader anwählen und mit dem Befehl Gruppe hinzufügen/Untergeordnete Gruppe hinzufügen ausführen und das Feld Sortenwechsel auswählen.
        • In der letzten Zeile bei der Zelle AnzahlMA den Befehl Zeile einfügen/Innerhalb Von Gruppe-Unterhalb auswählen.



      6. Folgende fehlende Zeilen einfügen:
        • Am ersten Zeilenheader den Befehl Zeile einfügen/Innerhalb von Gruppe - Unterhalb ausführen
        • Am letzten Zeilenheader den Befehl Zeile einfügen/Ausserhalb von Gruppe - Unterhalb ausführen

      7. In der ersten Zeile den Text von 'AnzahlMA' und 'Group1' löschen und eine Zeile unterhalb 'AnzahlMA' und 'Sortenwechsel' schreiben.
      8. Unterhalb von 'Partie' in der neuen Zeile die beiden verbundenen Zellen mit dem Befehl Zellen teilen wieder teilen und 'Produktion' und 'Ausschuss' eintragen



      9. In den letzten beiden zeilen die Eintragungen laut Bild ebenfalls ergänzen...
      10. So, jetzt sind nur mehr die beiden Zeilensummen für das Feld Produktion und Ausschuss zu erstellen:
        • Den letzten Spaltenheader rechts außen anwählen und mit dem Befehl Spalte einfügen/Ausserhalb von Gruppe - Rechts einen neue Spalte rechts einfügen
        • Und dann nochmals in der neuen Spalte den Befehl Spale einfügen/Rechts ausführen.
        • In der ersten Zeile die letzten beiden Zellen auswählen und mit dem Befehl Zellen zusammenführen die beiden Zellen verbinden und die fehlenden Beschriftungen und Formeln einfügen
      Somit gleicht sich jetzt die Tabelle im Rohzustand der Tabelle des Assistenten. Es sind nur mehr die Formatierungen zu ergänzen...
      Wie man sieht - mit dem Assistenten ist es ein bequemerer und schneller Weg als mit ehrlicher Handarbeit, eine Gruppierung zu erstellen. Im Normalfall genügt der Assistent. Aber es gibt auch Fälle, wo eine Gruppierung dann noch manuell weiter entwickelt werden muss...
      Also, auch hier empfehle ich viel üben und mit den Kontextmenübefehlen spielen...

      Dieser Beitrag wurde bereits 11 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 5)

      mehrere Tabellen in einem Bericht:
      Bis jetzt wurde immer nur eine Tabelle im Textkörper des Berichtes erstellt, was ja oft genügt.
      Man kann aber auch mehrere Tabellen im Textkörper plazieren. In solchen Fällen muss man für jede Tabelle eine eigene Reportdatenquelle definieren. (BerichtsDaten/Neu/Dataset...)
      In den Berichtsdaten einfach mehrere Reportdatasets anlegen und die Benamung zur besseren Übersicht von der Projektdatentabelle übernehmen.
      Man zieht dann mehrere Tabellensteuerelemente in den Textkörper und ordnet jeder Tabelle eine Datenquelle zu.
      Da gibt es folgende verschiedene Möglichkeiten:
      • Entweder man zieht aus einer Datenquelle 1x ein Feld in den Tablixkörper,
      • man wählt aus einem leeren Feld 1x eine Entität aus,
      • oder man geht in den Dialog Tablixeigenschaften und stellt bei Allgemein eine Report-Datenquelle ein.

      Danach formatiert man die Tabellen nach seinen Wünschen.
      Per Code wird bei der Zuweisung der Datasources in den Bericht folgend vorgegangen:

      VB.NET-Quellcode

      1. With ReportViewer1
      2. .LocalReport.DataSources.Clear()
      3. .LocalReport.DataSources.Add(New ReportDataSource("Kunden", KundenBindingSource))
      4. .LocalReport.DataSources.Add(New ReportDataSource("Lieferanten", LieferantenBindingSource))
      5. .LocalReport.ReportEmbeddedResource = "ReportViewer_Unterberichte.Report 2 unabhängige Tabellen in einen Bericht.rdlc"
      6. .RefreshReport()
      7. End With

      Unterberichtsteuerelement:
      Man kann auch einen Unterbericht im selben Textkörper des Berichtes neben einer Tabelle einstellen.
      Dazu zieht man aus der Toolbox das Unterberichtsteuerelement in den Bericht und ordnet dem Steuerelement einen eigens erstellten Bericht zu.

      Bei einem Unterbericht ist es im Code wichtig, dass der Eventhandler zuerst für das SubReportProcessing-Ereignis angemeldet wird.
      In diesem Event wird die Reportdatenquelle dann dynamisch dem Unterbericht zugewiesen.

      VB.NET-Quellcode

      1. AddHandler ReportViewer1.LocalReport.SubreportProcessing, AddressOf updateSubReport
      2. '...
      3. Private Sub updateSubReport(sender As Object, e As SubreportProcessingEventArgs)
      4. e.DataSources.Clear()
      5. e.DataSources.Add(New ReportDataSource("Artikel", ArtikelBindingSource))
      6. End Sub

      Master- und Detailbericht:
      In diesem Fall zieht man von der Toolbox ein List-Steuerelement auf den Textkörper des Berichtes. Danach zieht man im Berichtsdatenfenster von der Mastertabelle die gewünschten Felder und von der Toolbox ein Unterberichtsteuerelement in die einzige Rechteck-Zelle. Dort positioniert man die Steuerelemente nach Bedarf. Nach Anwahl des einziegen Zeilenheaders wird im Kontextmenü die Gruppeneigenschaft für die Gruppierung eingestellt.

      Im Unterbericht, der dann im Unterberichtssteuerelement angezeigt werden soll, muss noch ein Parameter für die richtige Filterung des Unterberichtes definiert werden.
      Dieser Parameter ist dann für die Filterung des Unterberichtes zuständig.

      Im Unterberichtssteuerelement wird dann der fertige Unterbericht festgelegt und die Parameterzuweisung für den Filter des fertigen Unterberichts angegeben.
      Codemäßig wie oben im Unterbericht beschrieben vorgehen.

      Zusammengeführter Master- und Detailbericht:
      Wie man beim obigen Beispiel (Master-Bericht und Unterbericht als Detail) sehen kann,
      wird im Report nur der ausgewählte Masterdatensatz mit seinen zugehörenden Detaildaten angezeigt...
      Wenn man aber eine ganze Auflistung aller Masterdaten mit den zugehörenden Detaildaten haben möchte,
      muss man bei der Datenanbindung an den Report eine zusammengefasste Liste zur Verfügung stellen (siehe Kapitel 3 DataObjectBinding).
      Diese Daten werden dann im Report nach den Masterdaten gruppiert (siehe Kapitel 4)
      Der Weg über einen Unterbericht oder mit zwei unabhängigen Tabellen bietet sich hier immer wieder gerne an - aber das führt dann bei der Umsetzung des Reports in die weite Irre...

      VB.NET-Quellcode

      1. Private Sub UpdateReport()
      2. With Me.ReportViewer1
      3. .LocalReport.DataSources.Clear()
      4. .LocalReport.DataSources.Add(New ReportDataSource("DataSet1", From articles In DtsBusiness.Merchandise
      5. Join vendors In DtsBusiness.Seller On articles.ID Equals vendors.MerchandiseID
      6. Select New ItemArticleAndVendor(articles.Article, vendors.Vendor)))
      7. .LocalReport.ReportEmbeddedResource = "JoinedReport.ArticleAndVendor.rdlc"
      8. .RefreshReport()
      9. End With
      10. End Sub
      11. Public Class ItemArticleAndVendor
      12. Public Sub New(article As String, vendor As String)
      13. Me.Article = article
      14. Me.Vendor = vendor
      15. End Sub
      16. Public Property Article As String
      17. Public Property Vendor As String
      18. End Class

      Zeile #4 zeigt, wie die zusammengeführte Liste dem Report übergeben wird.
      Das rudimentäre Anschauungsprojekt ist unten beigefügt...

      Drillthrough Berichte: (Interaktiv)
      In einem Drillthroug-Vorgang wird einer Zelle im Hauptbericht eine Aktion für den Sprung zu einem Unterbericht zugewiesen.
      Wenn man mit dem Cursor über diese Zelle fährt, ändert sich dabei der Cursor für den Drillthroug-Vorgang - wenn man in die Zelle klickt,
      wird der Vorgang ausgelöst und direkt zum angegebenen Unterbericht gesprungen.
      Retour geht es mit dem blauen Pfeil nach links in der Reportviewer-Symbolleiste ('Zurück zum übergeordneten Bericht').
      Der Drillthrough-Vorgang ist nur bei einem Textfeld- und einem Bildsteuerelement möglich.
      Das folgende Bild zeigt, wie man diesen Vorgang einstellt:

      Im Code muss man dann nur noch das Drillthrough-Event behandeln. Hier wird die Datenquelle für den Unterbericht zugewiesen:

      VB.NET-Quellcode

      1. Private Sub ReportViewer1_Drillthrough(sender As System.Object, e As Microsoft.Reporting.WinForms.DrillthroughEventArgs) Handles ReportViewer1.Drillthrough
      2. CType(e.Report, LocalReport).DataSources.Add(New ReportDataSource("Artikel", ArtikelBindingSource))
      3. End Sub

      Anbei wieder eine Samplesolution, die obige Berichtsdarstellungen zeigt...
      Dateien

      Dieser Beitrag wurde bereits 12 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 6)

      Verwenden von Bilder im Report:

      Der Zugriff auf ein Bild kann über verschiedene Wege erfolgen:
      • es ist direkt im Report eingebunden (zulässige MIME-Typen: .jpeg, .bmp, .gif, .png)
      • stammt aus einer Datenbank (datengebundene Bilder als Binärdaten - BLOB)
      • oder einer externen Datenquelle (externe Bilder, die als URL auf eine Image-Datei verweisen)
      Bilder, die zum Projekt hinzugefügt wurden, können nicht für einen Bericht verwendet werden. Eingebettete Bilder werden direkt in die Berichtsdefinition (.rdlc-Datei) abgelegt und stehen nur für diesen einen Bericht zur Verfügung. Dabei werden die Bilddaten MIME-kodiert als Textdaten in die Berichtsdefinition abgelegt. Wenn viele Bilder in einem Report eingebettet werden, vergrößert sich die .rdlc-Datei enorm. Da ist es besser man lagert solche Bilder aus der Berichtsdefinitionsdatei aus.

      Ein Bild in den Bericht einbetten und anwenden:

      Mit Berichtsdaten(Strg+Alt+D)/Neu/Bilder öffnet man einen Dialog zum Auswählen der gewünschten Bilder aus dem Dateisystem und fügt das ausgewählte Bild eingebettet dem Bericht hinzu. Danach zieht man von der Toolbox des Berichtsdesigners ein Bildsteuerelement in den Textkörper des Berichtes. Im aufgehenden Dialog Bildeigenschaften ergänzt man die Eigenschaften zum Bildsteuerelement (siehe unten die Bilder). Bei der Combobox Bildquelle auswählen die Einstellung Eingebettet selektieren und unterhalb das gewünschte Bild aus der Combobox der eingebetteten Bilder anwählen. Man hat über den Button Importieren die Möglichkeit noch fehlende Bilder in die Berichtsdefinition einzubetten...


      Bilder aus einer Datenbank beziehen:

      In den Bildeigenschaften die Einstellung Datenbank auswählen und unterhalb das Feld der Tabelle auswählen, die die Bilddaten beinhaltet. Die MIME-Typen (JPEG, BMP, GIF, PNG) gelten nur bei Datenbank-Auswahl. Das Bild kann als Binärobjekt (BLOB) in einem ByteArray oder im MIME-Format als String in der Datenbank vorliegen. Dazu müssen die Bilddaten eigens konvertiert werden. Oder man speichert nur die Bildpfade ab und holt sich die Bildinformationen über folgenden Ausdruck: ="file://" & Fields!PathAndFileOfImage.Value aus einem externen Datenpfad.


      Verwenden von externen Bildern:

      Diese Bilder werden aus Sicherheitsgründen immer blockiert - man muss folgende Eigenschaft im Code ReportViewer.LocalReport.EnableExternalImages = True setzen, um auf externe Bilder überhaupt zugreifen zu können. Wenn das nichts hilft, kann man dann noch Änderungen an der bestehenden Netzwerkkonfiguration vornehmen...


      Bilder als Hintergrund anwenden:

      Die Bilder können in den folgenden Steuerelementen zur Anwendung kommen:
      • Textkörper des Berichtes, Berichtkopf und -fuß
      • Textfeld, Rechteck, Liste, Matrix oder Tabelle
      Die Hintergrundbildeigenschaften können dann noch via Eigenschaften-Dialog verfeinert werden, wie sich das Bild im Hintergrund darstellen soll.


      In der angefügten Samplesolution werden oben beschriebene Fälle anschaulich dargestellt.
      Hierbei werden 4 Beispielbilder in einem Unterordner Pictures extern zur Verfügung gestellt.
      Ein Dataset mit der Pictures-Tabelle wird beim Öffnen mit den Daten der Bilder gefüllt.
      Die Bilddaten werden als ByteArray() (BLOB) und als String (MIME) abgelegt. Beide Abrufvariationen werden im zweiten Report gezeigt.
      Der Name des Bildes wird in einer extra Spalte gespeichert, diese Spalte wird als Referenz zum Abrufen der externen Bilder verwendet (zweite Report)
      Wenn Bilder aus einer externen Quelle geladen werden, muss vorher im Code ReportViewer.LocalReport.EnableExternalImages = True gesetzt werden.
      Im ersten Report werden externe Bilder in einem Picturesteuerelement dargestellt und es wird ein eingebettetes Bild als Hintergrund in der Kopf- und Fußzeileverwendet.
      Im zweiten Report werden die Bild-Darstellungen als Datenbankbilder (intern/extern) gezeigt.

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Private Sub cbxBerichte_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cbxBerichte.SelectedIndexChanged
      2. Dim Bericht As String = getItem(CType(sender, ComboBox))
      3. With ReportViewer1
      4. .Reset() 'manchmal kommt es vor, dass die Berichtsparameter nicht mehr aufgelistet werden... (Achtung: SubReportProcessing-Ereignishandler wieder herstellen!)
      5. .LocalReport.EnableExternalImages = True
      6. .LocalReport.DataSources.Clear()
      7. If Bericht = "Bilder-Datenbank" Then bindReport(Bericht, "Pictures", PicturesBindingSource)
      8. .LocalReport.ReportEmbeddedResource = String.Concat("ReportViewerBilder.Report ", Bericht, ".rdlc")
      9. .LocalReport.SetParameters(New ReportParameter("rpPicturePath", Application.StartupPath))
      10. .RefreshReport()
      11. End With
      12. End Sub
      13. Sub FillDataSet()
      14. PicturesDataSet.Pictures.Clear()
      15. Dim di As New DirectoryInfo(String.Concat(Application.StartupPath, "\../../Pictures/"))
      16. Dim picList = di.EnumerateFiles("*.jp*")
      17. For Each pic In picList
      18. Dim fi = pic.Name.Split("."c)
      19. Dim rw = PicturesDataSet.Pictures.NewPicturesRow
      20. rw.Name = fi(0)
      21. rw.Extension = fi(1)
      22. rw.BLOB = IMAGEtoBLOB(Bitmap.FromFile(pic.FullName))
      23. rw.MIME = BLOBtoMIME(rw.BLOB)
      24. PicturesDataSet.Pictures.AddPicturesRow(rw)
      25. Next
      26. End Sub
      27. Private Shared Function IMAGEtoBLOB(Image As Image) As Byte()
      28. Using ms As New MemoryStream()
      29. Image.Save(ms, ImageFormat.Jpeg)
      30. Return ms.ToArray()
      31. End Using
      32. End Function
      33. Private Function BLOBtoMIME(ByRef Bytes() As Byte) As String
      34. Return Convert.ToBase64String(Bytes)
      35. End Function
      Dateien

      Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 7)

      Einen Hyperlink im Report anwenden:

      Das Textfeld- und Bildsteuerelement kann neben dem DrillThrough-Vorgang auch einen Hyperlink-Vorgang auslösen.
      Dazu ist aber per Code die Eigenschaft ReportViewer.LocalReport.EnableHyperlinks-Eigenschaft = True zu setzen, damit dieser Vorgang überhaupt anschlägt.
      Dazu ruft man über das Kontextmenü des betreffenden Steuerelementes die Eigenschaften auf und danach bei der Seite Aktion die Option Hyperlinkaktion Gehe zu URL aktivieren.
      Eine Zeile darunter wird eine gültige URL verlangt bzw. ein Ausdruck, der einer URL entspricht.



      Bei diesem Vorgang muss aber nicht immer zu einer Webseite umgeleitet werden, sondern man kann es dazu auch verwenden, das irgend eine andere Aktion im Bericht durchgeführt wird.

      zum BEISPIEL: (angehängte Samplesolution)



      In einem Bericht sollen durch Anklicken:
      1. am Tabellenspaltenheader jeweils verschiedene Webseiten aufgerufen werden
      2. einer Zelle (Textfeld) in einer Tabelle ein Bild-Dialog geöffnet werden, der das dazugehörende Bild zur Datenzeile anzeigt.
      3. und beim Klicken einer Zelle die Bookmark-Aktion anzeigen (siehe weiter unten)
      Dazu muss als erstes die Hyperlinkaktion Gehe zu URL: ="Picture:" & Fields!Name.Value & "." & Fields!Extension.Value festgelegt werden.



      Im Code wird das Ereignis Hyperlink vom Reportviewer behandelt und über die HyperlinkEventArgs die Url ausgewertet, die wie im obigen Bild gezeigt, angegeben wurde. Der Pfad des externen Bildes wird dann einem Bildanzeigedialog übergeben:
      Anmerkung: hier ist es nicht notwendig ReportViewer.LocalReport.EnableExternalImages = True zu setzen, weil das Bild nicht im Bericht sondern in einem Dialog (Form) zur Anzeige gebracht wird!

      VB.NET-Quellcode

      1. ReportViewer1.LocalReport.EnableHyperlinks = True' Diese Eigenschaft muss vorher festgelegt werden, damit das Hyperlinkevent überhaupt ausgelöst werden kann!
      2. '
      3. Private Sub ReportViewer1_Hyperlink(sender As System.Object, e As HyperlinkEventArgs) Handles ReportViewer1.Hyperlink
      4. Dim uri As New Uri(e.Hyperlink)
      5. If uri.Scheme = "picture" Then
      6. e.Cancel = True
      7. Dim pic = Path.Combine(Application.StartupPath & "\../../Pictures/", uri.Segments(0))
      8. Using dlg As New DialogPicture(pic)
      9. dlg.ShowDialog()
      10. End Using
      11. End If
      12. End Sub

      Im obigen Verfahren kann man nur einen gültigen Hyperlink als String dem Anzeigedialog übergeben. Wenn man versucht, die Bilddaten als MIME-kodierten String zu übergeben, wird die Hyperlink-Aktion ohne Fehler nicht einfach angestoßen. Also kann man nur einen Bildverweis übergeben und ladet das Bild dann von externer Stelle. Es gibt aber noch eine zweite Methode, mit der ist es möglich, den MIME-kodierten Bild-String zum Anzeigedialog weiter zu reichen und damit kann man dann interne Datenbankbilder direkt im Anzeigedialog anzeigen lassen. Hier ist die Rede vom Bookmark-Ereignis des Reportviewers. Bei dieser Variante braucht man vorher auch keine zusätzlichen Eigenschaften setzen. Diese Aktion wird nur vom Bild- und Textfeldsteuerelement zur Verfügung gestellt. Man braucht über das Kontextmenü des betreffenden Steuerelementes die Eigenschaften aufrufen und dann bei der Seite Aktion die Option Gehe zu Lesezeichen anwählen. Es wird unmittelbar danach ein Feld für das Lesezeichen angefordert. In unserem Beispiel wählt man die Spalte für die MIME-Bilddaten, die als langer String vorliegen.



      Im Code wertet man dann die BookmarkNavigationEventArgs entsprechend aus und übergibt die Bilddaten dem Anzeigedialog.

      VB.NET-Quellcode

      1. Private Sub ReportViewer1_BookmarkNavigation(sender As System.Object, e As BookmarkNavigationEventArgs) Handles ReportViewer1.BookmarkNavigation
      2. e.Cancel = True
      3. Using dlg As New DialogPicture(MIMEtoIMAGE(e.BookmarkId))
      4. dlg.ShowDialog()
      5. End Using
      6. End Sub


      kleines weiteres Future: Es gibt im Bericht auch die Eigenschaft QuickInfo und funktioniert, wenn man mit der Maus über die Steuerelemente rüberfährt, wie gewohnt und gibt kurz den Infotext aus. Das Textfeld, das Bildelement und die Tablixvarianten(Tabelle, Matrix und Liste) bieten diese Eigenschaft an.

      Dateien

      Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 8)

      Einbinden eines benutzerdef. Assembly zur Befehlserweiterung in den Formelausdrücken:

      Im Kapitel 2 wurde beschrieben, wie man umfangreiche Formelausdrücke mit benutzerdefiertem Code (eingebettet in der Berichtsdefinition) vereinfachen kann.
      Aber dort ist man auf folgende Stammnamespaces eingeschränkt (im Normalfall ist mit diesen leicht ein Auskommen):
      • Microsoft.VisualBasic
      • System.Convert
      • System.Math
      Es kann aber auch vorkommen, dass man eine umfangreiche Library für mehrere Berichte mit Ausdrücken von anderen Namespaces braucht und anwenden will. Oder es liegt eine Assembly in einer anderen .Net-Sprache vor, die man im Bericht zur Berechnung verschieder Werte anwenden will, dann muss man auf diese externe benutzerdefinierte Assembly extra verweisen (siehe erstes Bild unten). Zusätzlich ist es notwendig, die Assembly speziell für die Designzeit in das Standardverzeichnis des Berichtsdesigners zu hinterlegen. Ein gewohnter Verweis zur Assembly für das Projekt ist ebenfalls zu erstellen (siehe zweites Bild unten).

      Für Win 7 und VS2010 sind folgende Pfade zur Hinterlegung der benutzerdefinierten Assembly zu verwenden:
      • (32 Bit) -> C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies
      • (64 Bit) -> C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies
      Für Win 10 und VS2017 und höher gilt folgendes:
      Wichtig:
      Die ReportLib.dll vor Ausführen des Projektes in eines der installierten Verzeichnisse speichern:

      VS2017:
      C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
      • C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Current\Bin

      VS2019:
      C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\15.0\Bin
      • C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin


      Danach das Projekt nochmals neu erstellen!

      Wenn statische Methoden vorliegen, die zur Anwendung gedacht sind, genügt in den Berichtseigenschaften bei Verweise nur die Angabe der Assembly im ersten Abschnitt der Berichtsverweise. Des Weiteren kann es hier auch noch notwendig sein, dass Verweise hier im ersten Abschnitt zusätzlich angeführt werden müssen, die auch in der Assembly zusätzlich importiert worden sind. Das entscheidet in dem Fall die IDE in Form einer Fehlermeldung und korrigiert einfach nach. Für instanzbasierte Methoden muss man zusätzlich im zweiten unteren Abschnitt die Klasse mit vorangestellten Assemblynamen und einen dafür im Formelausdruck zu verwendeten Instanznamen angeben.



      Es gibt dann zwei Varianten zur Anwendung der Methoden in einem Formelausdruck:
      1. mit einer statischen Methode:
        =ReportLib.Picture.ImageHeight(Fields!BLOB.Value)
        Hier wird der vollqualifizierte Name der Methode angewendet. (Assembly.Klasse.Methode)
      2. mit einer instanzbezogenen Methode:
        =Code.iPicture.imgWidth(Fields!BLOB.Value)
        Hier wird der Instanzname im Code-Objekt angewendet. (Code.Instanz.Methode)

      In der Samplesolution werden beide Varianten angewendet. Hier werden die Bilddimensionen (Höhe und Breite) der einzelnen Bilder in der DB in Pixel berechnet und ausgegeben.
      Wichtig: Dieses Solution ist erst dann lauffähig, wenn vorher die ReportLib.dll in einen der oben angegebenen Pfade kopiert worden ist und anschließend das Projekt nochmals neu erstellt wurde.
      Diese .dll ist dann für sämtliche Berichte zugängig wenn die Verweise angegeben werden.



      Kleiner Auszug aus der ReportLib:
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.IO
      2. Imports System.Drawing
      3. Imports System.Drawing.Imaging
      4. Public Class Picture
      5. Public Shared Function ImageHeight(Blob As Byte()) As Integer
      6. Using ms As New MemoryStream(Blob)
      7. Return Image.FromStream(ms).Height
      8. End Using
      9. End Function
      10. '
      11. '
      12. '
      13. Public Function imgWidth(Mime As String) As Integer
      14. Using ms As New MemoryStream(Convert.FromBase64String(Mime))
      15. Return Image.FromStream(ms).Width
      16. End Using
      17. End Function
      18. '
      19. '
      20. '
      21. End Class

      Wenn die neue Sample nicht ordentlich kompiliert, kann die Ursache nur der Bericht mit seinen nicht aufgelösten Verweisen sein - Sollte das der Fall sein, bitte mir melden!
      Dateien

      Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „VB1963“ ()

      ReportViewer-Tutorial für Anfänger (Teil 9)

      Direktes Drucken ohne ReportViewer

      Es ist auch ohne Weiteres möglich, die erstellten Berichte (.rdlc) ohne den Reportviewer an den Drucker zu senden oder den Ausdruck einfach direkt in eine Datei umzulenken und später zu verwenden.
      In der angehängten Samplesolution wird veranschaulicht, wie das direkte Drucken bzw. Umlenken in eine Datei funktioniert.



      Die Methode DirectPrint bietet folgende Möglichkeiten:
      • es wird direkt gedruckt
      • der Bericht wird in eine Datei umgelenkt
      Im zweiten Fall wird ein SaveFile-Dialog aufgerufen, wo man den Pfad und den Namen und einen der fünf möglichen Dateitypen festlegen kann:
      [*]PDF
      [*]Word
      [*]Excel
      [*]Image (.jpg oder .bmp)


      Bei den Image-Files werden die Berichtsseiten als einzelene Bilddateien mit der Namenserweiterung (1-n) durchnummeriert abgespeichert.
      Bevor man die DirectPrint-Methode anwendet, muss zuvor der Bericht festgelegt werden und dieser wird dann der Methode übergeben.
      Optional kann man auch die Umlenkung in eine Datei festlegen.

      Public Function DirectPrint(Report As LocalReport, Optional Save As Boolean = False) As String

      Der Rückgabewert dieser Funktion ist ein String, der einen eventuellen Fehlertext beim Rendern des Berichtes bzw. beim Speichern zurrückgibt. (Standardeinstellung: 'Ready...')
      Diesen Text kann man zum Beispiel in einem Statuslable als Rückmeldetext ausgeben...
      Hinweis: Die LocalReport.DisplayName - Eigenschaft wird beim Speichern des Berichtes nur als Vorlage für den Filename verwendet. Diese Eigenschaft könnte man also auch weglassen - dann verzichtet man aber auf den Komfort der Namensvorlage.
      Bei Zeile #19 wird die Singleton-Klasse DirectPrinting instanziiert.
      Bei Zeile #20 wird die Methode DirectPrint angewendet.

      VB.NET-Quellcode

      1. Private Sub btnPrint_Click(sender As System.Object, e As System.EventArgs) Handles btnPrint.Click
      2. Dim rep As New LocalReport
      3. With rep
      4. .ReportEmbeddedResource = String.Concat("ReportViewerDirectPrinting.Report ", Bericht, ".rdlc")
      5. .DisplayName = Bericht
      6. Select Case Bericht
      7. Case Is = "Mein erster Bericht"
      8. .SetParameters(New ReportParameter("rpAlter", 47.ToString))
      9. .SetParameters(New ReportParameter("rpVorName", "Max"))
      10. .SetParameters(New ReportParameter("rpNachName", "Mustermann"))
      11. Case Is = "Pictures"
      12. .DataSources.Add(New ReportDataSource(Bericht, PicturesBindingSource))
      13. Case Is = "Produktion"
      14. Dim objData = New Produktion
      15. .DataSources.Add(New ReportDataSource(Bericht, objData.loadProduktion()))
      16. End Select
      17. End With
      18. StatusText.Text = String.Empty
      19. '
      20. 'alte Variante
      21. Dim prt = DirectPrinting.getInstance
      22. StatusText.Text = prt.DirectPrint(rep, CheckBoxSave.Checked)
      23. '
      24. 'neue Variante
      25. Using prt As New DirectPrinting 'Optional mit ... With {.SuppressPrintingPopUp = False}
      26. 'Überladungen
      27. StatusText.Text = prt.DirectPrint(rep, CheckBoxSave.Checked)
      28. StatusText.Text = prt.DirectPrint(rep, SeiteX, CheckBoxSave.Checked)
      29. StatusText.Text = prt.DirectPrint(rep, SeiteVon, SeiteBis, CheckBoxSave.Checked)
      30. End Using
      31. '
      32. End Sub

      Tip:
      Beim Drucken erscheint bei jeder Seite ein PopUp-Fenster, wo die gerade die zu druckende Seite angezeigt wird.
      Wenn das stört, kann man beim PrintDokument durch Zuweisen eines neuen StandardPrintControler dieses Fenster unterdrücken...
      Siehe auch oben in der neuen Variante mit der Angabe der Option SuppressPrintingPopUp (Defaultvalue = True)

      VB.NET-Quellcode

      1. 'alte Klasse VS2010...
      2. Public NotInheritable Class DirectPrinting
      3. Implements IDisposable
      4. '
      5. Private Sub printReport()
      6. Dim pDoc As New PrintDocument()
      7. '
      8. pDoc.PrintController = New StandardPrintController ' PopUp-Fenster beim Drucken unterdrücken
      9. pDoc.Print()
      10. '
      11. End Sub
      12. End Class


      Ich habe DirectPrinting um das SubreportProcessingEvent erweitert (siehe Zeile #9 im Spoiler). Hiermit ist es jetzt auch möglich, einen Unterbericht direkt auszudrucken...
      Dazu braucht man nur zusätzlich bei der Datasourcesauflistung die Datenquelle des Unterberichtes mitübergeben.

      VB.NET-Quellcode

      1. LocalReport.DataSources.Add(New ReportDataSource("MasterTabelle", MasterTabelleBindingSource))
      2. LocalReport.DataSources.Add(New ReportDataSource("UnterTabelle", UnterTabelleBindingSource))

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Private Sub updateSubReport(sender As Object, e As SubreportProcessingEventArgs)
      2. e.DataSources.Clear()
      3. For ds = 0 To myReport.DataSources.Count - 1
      4. If ds > 0 Then e.DataSources.Add(myReport.DataSources(ds))
      5. Next
      6. End Sub
      7. Public Function DirectPrint(Report As LocalReport, Optional Save As Boolean = False) As String
      8. AddHandler Report.SubreportProcessing, AddressOf updateSubReport
      9. If Save Then
      10. myReport = Report
      11. Dim fi = SaveTo()
      12. If fi Is Nothing Then Return String.Empty
      13. myFileExtension = fi.Extension
      14. If Not myExtensions.ContainsKey(myFileExtension) Then
      15. SystemSounds.Hand.Play()
      16. Return String.Concat("File-Error! : Die Dateiextension '", myFileExtension, "' wird nicht unterstützt...")
      17. End If
      18. myFile = New FileInfo(fi.FullName)
      19. myReport.Refresh()
      20. Using Printer As New DirectPrinting()
      21. If myExtensions.Item(myFileExtension) = "Image" Then Export() Else saveReport() 'PDF, Word, Excel
      22. Return myResponse
      23. End Using
      24. End If
      25. Using Printer As New DirectPrinting()
      26. myReport = Report
      27. myFile = Nothing
      28. myReport.Refresh()
      29. If Export() Then printReport()
      30. Return myResponse
      31. End Using
      32. End Function
      Ein Danke an @Antor :) , der mich bei seiner Frage auf diese Idee brachte...
      Die neue Version wurde für höher VS2010 neu aufgesetzt und hat einen Bug (gemeldet von @Gembolum ) behoben...
      Dateien

      Dieser Beitrag wurde bereits 18 mal editiert, zuletzt von „VB1963“ ()