ReportViewer-Tutorial für Anfänger - Fragethread

  • VB.NET
  • .NET (FX) 4.0

Es gibt 42 Antworten in diesem Thema. Der letzte Beitrag () ist von Pe..CH.

    Dankeschön :)

    Volkmar schrieb:

    den voreingestellten Pfad und den Dateinamen beim Export z.B. als pdf zu verändern? Nach Möglichkeit dynamisch, so dass man das nicht immer manuell eingeben muss?

    Ja das ist schon öfters gefragt worden und auch möglich...
    1) Man benutzt dazu ganz einfach das ReportViewer.ReportExport-Event und stellt e.Cancel auf True ein.
    2) Mit e.Extension kann man seine ausgewählte File-Extension bestimmen.
    3) Dann wird mittels einer eigenen Exportmethode mit den Argumenten: Pfad, Filenamen und ausgewählter Extension der Report in das definierte File exportiert.

    Dazu habe ich eine einfache Export-Funktion verfasst (leichte Anlehnung an Kapitel 9)
    Diese Methode kann man auch ohne ReportViewer verwenden und ruft den Export einfach über ein Button-Click-Event auf...

    Funktion PrintIntoFile

    VB.NET-Quellcode

    1. Public Function PrintIntoFile(Report As LocalReport, Directory As DirectoryInfo, Filename As String, Extension As String) As String
    2. Dim myExtensions As New Dictionary(Of String, String) From {{"PDF", ".pdf"}, {"Excel", ".xls"}, {"Word", ".doc"}}
    3. Dim myFile As FileInfo
    4. Dim myResponse As String = "Ready..."
    5. '
    6. If Directory Is Nothing OrElse String.IsNullOrWhiteSpace(Filename) Then Return String.Concat("Argument-Error! : ", "invalid Directoy or Filename...")
    7. If Not myExtensions.ContainsKey(Extension) Then Return String.Concat("Argument-Error! : ", "invalid File-Extension...")
    8. myFile = New FileInfo(Path.Combine(Directory.Name, String.Concat(Filename, myExtensions.Item(Extension))))
    9. Report.Refresh()
    10. '
    11. Try
    12. Using fs = New FileStream(myFile.FullName, FileMode.Create)
    13. Dim Bytes() As Byte = {}
    14. Bytes = Report.Render(Extension)
    15. If Bytes.Length > 0 Then
    16. fs.Write(Bytes, 0, Bytes.Length)
    17. fs.Flush()
    18. End If
    19. End Using
    20. Catch ex As MissingReportSourceException
    21. myResponse = String.Concat("Report-Error! : ", ex.Message)
    22. IO.File.Delete(myFile.FullName)
    23. Catch ex As LocalProcessingException
    24. myResponse = String.Concat("Report-Error! : ", ex.InnerException.Message)
    25. IO.File.Delete(myFile.FullName)
    26. Catch ex As IOException
    27. myResponse = String.Concat("IO-Error! : ", ex.Message)
    28. Catch ex As Exception 'sonstiger Fehler
    29. myResponse = String.Concat("Unknown-Error! : ", ex.Message)
    30. End Try
    31. Return myResponse
    32. End Function

    Handhabe im ReportExport-Event

    VB.NET-Quellcode

    1. Private Sub ReportViewer1_ReportExport(sender As System.Object, e As ReportExportEventArgs) Handles ReportViewer1.ReportExport
    2. e.Cancel = True
    3. StatusText.Text = PrintIntoFile(ReportViewer1.LocalReport, New DirectoryInfo("MyDirectory"), "MyFile", e.Extension.LocalizedName)
    4. End Sub

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

    Hallo @VB1963
    ich habe zu dem ganzen Thema ReportViewer 2 Fragen:
    Zum einen musste ich etwas googlen um den ReportViewer wieder ins Visual Studio 2017 Enterprise für c# zu bekommen, aber hab es soweit hin bekommen.
    Nun habe ich meinen Bericht erstellt.
    muss ich tatsächlich das Dataset, welches ja in der Hauptform schon geladen wird, in der Report Form neu einlesen?

    C#-Quellcode

    1. private void frmReport_Load(object sender, EventArgs e)
    2. {
    3. dsCore.LoadDataSet(file);
    4. bsSellerArticle.Filter = "Sold = true";
    5. this.rvSellerArticle.RefreshReport();
    6. }

    Im Bericht wird mir auch leider immer nur der erste Eintrag der Übergeordneten Tabelle angeueigt und nicht alle weitern....
    Im Bericht habe ich 2 Felder, die ich gerne berechnen möchte, als Grundlage zur Berechnung wird ein Datenfeld aus der Tabelle benötigt.
    Hier sagt mir der Bericht stets, das ich kein Dataset zugrunde liegen habe... hab ich aber.
    der Ausdruck Fields!TurnOver.Value, "dsSeller" wird immer untergringelt, aber man sieht den Hinweis darunter nicht.
    Wie kann ich also die beiden Werte (Turnover*0,2) = Provision und (TurnOver-Provision) = Endsumme berechnen??

    Falls Du das Projekt dazu benötigst, könnte ich es Dir per PM zukommen lassen.

    Danke Dir
    Gruß
    Micha
    "Hier könnte Ihre Werbung stehen..."
    Hi,

    MichaHo schrieb:

    Zum einen musste ich etwas googlen um den ReportViewer wieder ins Visual Studio 2017 Enterprise für c# zu bekommen, aber hab es soweit hin bekommen.
    Ja, das muss ich in meinem Tutorial für VS2017 einpflegen - da hat sich grundsätzlich etwas geändert...

    MichaHo schrieb:

    muss ich tatsächlich das Dataset, welches ja in der Hauptform schon geladen wird, in der Report Form neu einlesen?
    Ja - wie im Tutorial Kapitel 5 gezeigt.
    Man gibt im Report die Tabellen (dort leider Dataset genannt) von der Datenquelle (Dataset) an und bindet sie dann nachher per Code und refresht den Report...
    Ich denke, das hast du auch gemacht, weil dann schreibst du:

    MichaHo schrieb:

    Im Bericht wird mir auch leider immer nur der erste Eintrag der Übergeordneten Tabelle angeueigt und nicht alle weitern....
    und das muss ich mir anschauen...
    Leider kann man hier per PN keine Projekte hochladen. Da wäre es gut, wenn du da eine abgespeckte Solution, die das Problem zeigt,
    entweder hier im Tutorial postest (wäre besser - da können alle davon etwas lernen)
    oder sonst als Anhang per Mail an mich sendest die Adresse gebe ich dir per PN bekannt...
    Lg
    VB1963

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

    Hallo @VB1963
    Nun hab ich ein abgespecktes Projekt erstellt und wollte dort den Reportviewer testen.
    Bin Deiner Anleitung in Kapitel 5 gefolgt.

    Wenn ich dann den Bericht aufrufe erhalte ich den Fehler: "Für dsSeller wurde keine Datenbankinstanz festgelegt" (oder so ähnlich).

    Ich hänge das Projekt hier mal an.
    Im Ordner DataFile ist das DataSet File drinn, dort hab ich paar Zeilen eingefügt...
    Was mich auch stört ist, das mit dem ReportViewer immer auch SQL Server Types in sämtlichen Sprachen mit installiert wird...
    gefolgt bin ich bei der Installation diesem Link.
    Dateien
    "Hier könnte Ihre Werbung stehen..."
    Hallo @MichaHo
    Mir sind folgende Punkte aufgefallen:
    Wichtig ist, dass bei den Verweisen folgende Elemente mit der richtigen Versionsnummer aufgelistet sind:
    Microsoft.ReportViewer.Common.dll (Standard)
    Microsoft.ReportViewer.Design.dll (Standard)
    Microsoft.ReportViewer.WinForms.dll (Standard)
    Microsoft.ReportViewer.DataVisualization.dll (wenn in den Berichten noch Diagramme angezeigt werden sollen, wird diese .dll zusätzlich noch gebraucht)
    Microsoft.ReportViewer.ProcessingObjectModel.dll (sollte die Zielumgebung keinen ReportViewer aufweisen, ist diese .dll noch zusätzlich mit der Anwendung mit zu liefern)
    Microsoft.SqlServer.Types.dll (Wichtig: mit Datenbankanbindung)

    Dieser Umfang deckt alle Bedürfnisse zum reporten ab und sollten im folgenden Pfad unter Win10 und VS2017 nach der NuGet-Installataion zu finden sein:
    C:\Users\DuAlsUser\.nuget\packages\microsoft.reportingservices.reportviewercontrol.winforms\140.1000.523\lib\net40
    und sollten bei jedem Projekt mit Reporting mitgeliefert werden!

    Keine Punkte oder Sonderzeichen im Projektnamen!

    Du musst die Datenbinding zum Report ohne die Bindingsources machen!
    Statt dessen dazu eine gejointe Liste verwenden und diese dem Report übergeben und dort im Reportdesigner nach Seller gruppieren...
    Alles nachher via Designer verhübschen und mit entsprechenden Aggregationen ausstatten...

    C#-Quellcode

    1. private void UpdateDatas()
    2. {
    3. object tempList = from sellers in dsSellerArticle.Seller
    4. join articles in dsSellerArticle.Article on sellers.ID equals articles.SellerID
    5. select new ItemSellerVendor( sellers.Name, articles.Matchcode, articles.Price);
    6. this.reportViewer1.LocalReport.DataSources.Clear();
    7. this.reportViewer1.LocalReport.DataSources.Add(new Microsoft.Reporting.WinForms.ReportDataSource("DataSet1", tempList));
    8. this.reportViewer1.LocalReport.ReportEmbeddedResource = "ReportForMichaHo.SellerArticle.rdlc";
    9. this.reportViewer1.RefreshReport();
    10. }

    Sollte das Projekt bei dir nicht laufen - ev. obige Verweise neu setzen...

    Was mich auch stört ist, das mit dem ReportViewer immer auch SQL Server Types in sämtlichen Sprachen mit installiert wird...
    Das machst du über NuGet nur einmal und kannst den Ordner wieder aus deinem Projekt entfernen...
    Wenn du die bereitgestellten .dll's (siehe oben) in deinen Verweisen angegeben hast, passt's...

    PS zum Dataset:
    PrimeKey-Column -> nur mit ID bezeichnen.
    ForeignKey-Column -> xxxID mit erweiterter Bezeichnung, wobei xxx den Namen der Parenttable enthält.
    Damit werden die Relationen zueinander besser überschaubarer...
    Keine Namen verwenden, die den Schlüsselwörtern der Net-Sprache überlassen sind... (z.B.: Name, Size usw.)

    lg VB1963
    Dateien

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

    Hi @VB1963,
    Danke Dir erstmal für Deine Mühe.
    ich hatte im ersten Projekt den Reportviewer über NuGet installiert und im nächsten Projekt alle von Dir angegebenen Dll aus genau dem von Dir genannten Ordner ins Projekt gezogen.
    ich schaue mir Deinen Anhang am Wochenende an. Werde den Reportviewer definitiv im jetzigen Projekt brauchen, die Anforderung ist glaub mit dem itextsharp ekelhaft umzusetzen.
    Die Anforderung aus dem Qualtitätsmanagement kam gestern rein... sehr interessant... da gehts um Arbeitsanweisungen im Comic Stil...

    Danke Dir
    "Hier könnte Ihre Werbung stehen..."
    Hallo @VB1963,

    ich möchte mich an dieser Stelle einmal recht herzlich bei Dir für dieses tolle Tutorial bedanken!
    Die einzelnen Schritte sind wirklich gut erklärt und ich konnte damit nun auch erfolgreich eine erste Berichtsanwendung erstellen (Produktionsbericht zu einer unserer Anlagen).
    Die letzten 5 Beiträge hier zum Thema Datenbindung an den Report haben mir zusätzlich nochmal die Augen geöffnet und für noch mehr Verständnis zum Thema gesorgt.

    Vielen Dank dafür!
    @VB1963

    VB1963 schrieb:

    Dazu außerhalb des Textkörpers mit der rechten Maustaste auf den Bericht klicken und den Dialog Berichtseigenschaften auswählen.



    Hallo VB1963,
    erst mal vielen Dank fuer deine muehe mit diesem Tutorial.
    Ich versuche das gerade so zu machen wie du dass empfiehlst und haenge gerade die ganze Zeit daran das ich die Berichtseigenschaften nirgens finde.
    Ich wollte Variablen eingeben aber ich habe keine ahnung wie ich das jetzt machen soll.
    Auf der MS Seite steht es auch beschrieben das man das ueber die Berichtseigenschaften macht aber wenn ich die rechte Maustaste benutze im Bericht bekomme ich nur die Eigenschaften des Textbereiches bzw. Fuss/Kopfbereich.
    Ich habe RDLC Version 15.0.1427.0 drauf.(Verweise sind natuerlich eingebunden)
    Hast du mir vielleicht einen Tip?
    Vielen Dank

    Andy

    p.s. sorry hat sich erledigt. Ich hatte den Textkoerper als Textbox verstanden. Ich habe jetzt durch weiters ausprobieren kapiert das man ausserhalb des visuellen Berichtes klicken muss.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „andydan“ ()

    Hallo zusammen,

    um meine Verzweiflung beim Verständnis des ReportViewers nicht noch größer werden zu lassen....
    Wo um alles in der Welt, werden im Beispiel "ReportViewerTutorial01" die Daten für "Mimi Musterfrau 35" hinterlegt???
    Ja ein uraltes Thema und bestimmt für die meisten ein Lächeln, aber ich komm nicht dahinter...

    Vielen Dank für die Lösung des Rätsels ...
    Hallo VB1963: vielen Dank!!!

    unter Berichtsparameter/ Standardwerte hatte ich natürlich nicht geschaut :=(
    aber nur so lernt man dazu....

    btw. was muss ich beachten, damit sich beim laufenden Prog. und erneutem aufrufen der RP Form
    die Daten nicht verdoppelt werden. D.h. je öfter ich die Form mit dem Bericht aufrufe, je mehr
    Einträge der gleichen Daten kommen im Bericht....

    Gruß Udo

    INFO für Reportviewer Tutorial

    Hallo Community

    Da meine Sample-Beispiele in meinem-Tutorial ReportViewerTutorial für Anfänger allesamt mit VS2010 erstellt wurden und diese mit höheren Versionen nicht mehr ordentlich compilierten,
    habe ich alle Samples mit VS2019 nochmals erstellt und eingestellt...

    VB1963 schrieb:

    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

    Danke für euer Interesse

    *Topics zusammengeführt*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Hallo VB1963,

    arbeite gerade ein wenig mit deinem Tutorial.
    Im gesamten habe ich hier schon viel gelernt im Umgang mit rdlc. Danke hierfür.

    Für was ist im untenstehenden Code der Counter?
    Der counter ist ja immer 0
    Da er mir bei ausgabe in Datei immer (0) im Filename anhängt, habe ich den IF-Teil auskommentiert, so das er immer "myPath = myFile.FullName" nutzt.
    Bisher gab es keine ProblemeIch arbeite mit den Report Viewer v15 DLLs.


    Beim Direktdrucken mit Ausgabe in PDF Datei im Debugger bin ich immer wieder auf den Fehler gestoßen. (In der Release Version gab es kein Fehler)
    Assistent für verwaltetes Debuggen "PInvokeStackImbalance"Nachricht = Assistent für verwaltetes Debuggen "PInvokeStackImbalance" : "Ein Aufruf an die PInvoke-Funktion "Microsoft.ReportViewer.Common!Microsoft.ReportingServices.Rendering.ImageRenderer.FontPackage::CreateFontPackage" hat das Gleichgewicht des Stapels gestört. Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein. Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen."


    Nach hinzu fügen des Rot markierten Codes in deine Klasse hat es auch mit PDF funktioniert.

    C#-Quellcode

    1. private void SaveReport(int Counter = 0, byte[] Picture = null)
    2. {
    3. var myPath = string.Empty;
    4. if (Counter == 0 && !myExtensions.Any(d => d.Value == "Image"))
    5. myPath = myFile.FullName;
    6. else
    7. myPath = string.Concat(myFile.DirectoryName, '\\', string.Concat(myFile.Name.Replace(myFile.Extension, string.Empty), " (", Counter, ')', myFile.Extension));
    8. using (var fs = new FileStream(myPath, FileMode.Create))
    9. {
    10. byte[] Bytes = null;
    11. if (Picture == null)
    12. {
    13. try
    14. {
    15. var deviceInfo = @"<DeviceInfo><EmbedFonts>None</EmbedFonts></DeviceInfo>";
    16. Bytes = myReport.Render(myExtensions.First((d) => d.Key == myFileExtension).Value, deviceInfo); // Format angeben
    17. }
    18. catch (MissingReportSourceException ex)
    19. {
    20. myResponse = string.Concat("Report-Error! : ", ex.Message);
    21. }
    22. ......

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Gembolum“ ()

    Gembolum schrieb:

    Für was ist im untenstehenden Code der Counter?

    Der Zähler wird für den Export als Bilddatei (.jpg oder .bmp) gebraucht, da der Inhalt auf mehrere Bilder aufgeteilt werden muss, wenn die Seiten überlang werden...
    Siehe unten folgenden Codeausschnitt Zeile 22:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'den Bericht als EMF (Enhanced Metafile-Datei) exportieren
    2. Private Function Export() As Boolean
    3. Dim deviceInfo As String = "<DeviceInfo><OutputFormat>EMF</OutputFormat></DeviceInfo>"
    4. Dim Warnings As Warning() = Nothing
    5. myStreams = New List(Of Stream)()
    6. Try
    7. myReport.Render("Image", deviceInfo, AddressOf getStream, Warnings)
    8. Catch ex As MissingReportSourceException
    9. myResponse = $"Report-Error! : {ex.Message}"
    10. Catch ex As LocalProcessingException
    11. myResponse = $"Report-Error! : {ex.InnerException}"
    12. Catch ex As Exception 'sonstiger Fehler
    13. myResponse = $"Report-Error! {ex.Message}"
    14. End Try
    15. If myStreams.Count = 0 Then ' Fehler beim Rendern des Berichtes
    16. SystemSounds.Hand.Play()
    17. Return False
    18. End If
    19. Dim Counter = 0
    20. For Each e In myStreams
    21. e.Position = 0
    22. If Not myFile Is Nothing Then saveReport(Counter, StreamToBytes(e)) : Counter += 1 ' Imageseiten werden gespeichert (.jpg, .bmp)
    23. Next
    24. Return True
    25. End Function
    26. Private Sub saveReport(Optional Counter As Integer = 0, Optional Picture As Byte() = Nothing)
    27. Dim myPath = String.Empty
    28. If Counter = 0 AndAlso myExtensions.Item(myFileExtension) <> "Image" Then
    29. myPath = myFile.FullName
    30. Else
    31. myPath = $"{myFile.DirectoryName}\{myFile.Name.Replace(myFile.Extension, String.Empty)} ({Counter}){myFile.Extension}"
    32. End If
    33. Using fs = New FileStream(myPath, FileMode.Create)
    34. Dim Bytes() As Byte = {}
    35. If Picture Is Nothing Then
    36. Try
    37. Dim deviceInfo As String = "<DeviceInfo><OutputFormat>EMF</OutputFormat></DeviceInfo>"
    38. Bytes = myReport.Render(myExtensions.Item(myFileExtension), deviceInfo) 'Format angeben
    39. Catch ex As MissingReportSourceException
    40. myResponse = $"Report-Error! : {ex.Message}"
    41. Catch ex As LocalProcessingException
    42. myResponse = $"Report-Error! : {ex.InnerException.Message}"
    43. Catch ex As Exception 'sonstiger Fehler
    44. myResponse = $"Report-Error! : {ex.Message}"
    45. End Try
    46. Else
    47. Bytes = Picture
    48. End If
    49. If Bytes.Length = 0 Then ' Fehler beim Rendern des Berichtes
    50. SystemSounds.Hand.Play()
    51. fs.Close()
    52. IO.File.Delete(myPath) ' Datei der Länge 0 wieder löschen
    53. Else
    54. fs.Write(Bytes, 0, Bytes.Length)
    55. Try
    56. fs.Flush()
    57. Catch ex As Exception
    58. myResponse = $"Report-Error! : {ex.Message}"
    59. End Try
    60. End If
    61. End Using
    62. End Sub
    Zeilen 29-33 behandeln den Zähler wie die Ausgabeseiten mit einen Zähler versehen werden...

    Bezüglich des beschriebenen Fehlers: den konnte ich bei mir nicht nachstellen - aber Danke für den Hinweis (werde ich berücksichtigen)

    VB1963 schrieb:


    Bezüglich des beschriebenen Fehlers: den konnte ich bei mir nicht nachstellen - aber Danke für den Hinweis (werde ich berücksichtigen)


    Ich teste sollche sachen immer in einem Alten testprojekt, hier ahtte ich den Fehler nicht.
    Ich habe diese Problem erst feststellen können, als ich mit VS2019 ein neues Projekt ersteltte und hier nocheinmal getestet habe.

    Edit:
    Ah jetzt hab ich den Fehler gefunden, warum es mir nicht logisch war.
    Beim VB übernehmen habe ich bei der IF-abfrage aus "Ungleich Image" -> "Is gleich Image".
    Nach korektur macht es jetzt auch mit deiner Antowrt sinn :)
    Dein VB-Code

    Quellcode

    1. If Counter = 0 AndAlso myExtensions.Item(myFileExtension) <> "Image" Then


    Mein C#-Code

    Quellcode

    1. if (Counter == 0 && !myExtensions.Any(d => d.Value == "Image"))


    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Gembolum“ ()

    VB1963 schrieb:

    Bezüglich des beschriebenen Fehlers: den konnte ich bei mir nicht nachstellen
    Der PInvokeStackImbalance-Error ist jetzt bei mir auch aufgetaucht. Dieser wird auch schon bei VS2017 ausgelöst, wenn man einen Bericht in eine PDF-Datei umleiten will, die mehrere Seiten beinhaltet!
    Den kann man bei mehrseitigen PDF mit "<DeviceInfo><EmbedFonts>None</EmbedFonts></DeviceInfo>" verhindern... (wie @Gembolum oben bereits schrieb)
    Ich habe die Klasse DirektPrinting neu aufgesetzt und erweitert --> Die TestSolution ist im Tutorial Kapitel 9 wo auch ein Beispiel mit Master/Detail(Unterbericht) gezeigt wird!

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