PDF DataSet

W poprzednim wpisie o report Viewer utworzyliśmy prosty plik PDF.

Sprawa jest trochę bardziej złożona, jeżeli chcemy wyświetlić kolekcję elementów w pliku PDF przy użyciu ReportViewer.

Na czym polega problem?

ReportViewer jest starą kontrolką. Gdy zaczynamy z nią działać, to ta kontrolka, aż się prosi o używanie głupich przestarzałych rozwiązań jak np. "ObjectDataSource".

Osobiście mam wstręt do tych rozwiązań. Nic dziwnego, że nie chciałem pisać tego wpisu przez długi czas.

ObjectDataSource

ReportViewer operuje także na rozwiązaniu DataSet. Rozwiązanie to było prawidłowe, gdy mieliśmy .NET 2.0  i nie było jeszcze LINQ oraz innych rozwiązań, jak NHiberante i ADO.NET Entity Framework.

Teraz to wydaje się śmieszne i żałosne.

Ciężko więc stworzyć plik PDF przy użyciu ReportViewer bez tworzenia pliku DataSet . Jest to jednak możliwe.

Zapomnij też o używaniu kreatorów do kontrolek ReportViewer, gdyż te właśnie tworzą pliki DataSet.

Zrób to więc najbardziej prawidłowo. Mam oto prosty projekt, który jest tak prosty, że aż nazywa się “ClassLibrary1”.

DataSource

Zawiera on klasę Person.

namespace ClassLibrary1
{
    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Istnieje też klasa "MyDataSource", która zwraca kolekcję klasy Person.

using System.Collections.Generic;

namespace ClassLibrary1
{
    public class MyDataSource
    {
        private static List<Person> _lstPeople = null;
        public static List<Person> GetAllPeople()
        {
            if (_lstPeople == null)
            {
                _lstPeople = new List<Person>();
                _lstPeople.Add(new Person()
                {
                    ID = 1,
                    Name = "Cezary",
                    Age = 30
                });

                _lstPeople.Add(new Person()
                {
                    ID = 2,
                    Name = "Darek",
                    Age = 30
                });

                _lstPeople.Add(new Person()
                {
                    ID = 3,
                    Name = "Krzysztof",
                    Age = 30
                });

                _lstPeople.Add(new Person()
                {
                    ID = 4,
                    Name = "Kamil",
                    Age = 31
                });

            }
            return _lstPeople;
        }
    }
}

W drugim projekcie utworzymy prosty plik PDF z tabelką.

ReportViewer

W pliku ReportViewer dodajemy tabelkę.

image

W projekcie nie istnieje żaden plik dataset. Dlatego po utworzeniu tabelki pojawi się kreator. Na szczęście jest to jedyny kreator, który będzie nam potrzebny.

W kreatorze wybieramy "Data Source". Dobrze, że źródłem danych może być biblioteka osobnego projektu.

W "Available dataset" wybieramy klasę i metodę zwracającą kolekcje.

DataSet Porperties

Po tym kreatorze zostanie za linkowane źródło danych oraz DataSet, mimo iż nie istnieje. Dodamy je później w kodzie.

Report Data

Mając tabelkę w łatwy sposób powiązujemy pola do odpowiednich kolumn.

Table

Kolorowanie kolumn i zmiana czcionki może być uciążliwe.

Table 2

Dlatego też, zamiast zaznaczać pojedynczo kolumny i edytować je po kolei, lepiej skorzystać z okna "Properties", gdzie wszystkie graficzne właściwości kolumny są dostępne.

Okno Properties

Pozostało jeszcze tylko utworzyć ten plik PDF.

Kod tworzący plik PDF nie zmienił się za bardzo od ostatniego wpisu.

protected void Button1_Click(object sender, EventArgs e)
{
    ReportViewer ReportViewer1 = new ReportViewer();
    ReportViewer1.LocalReport.ReportPath = 
    HttpContext.Current.Server.MapPath(@"\Report1.rdlc");

    var people = MyDataSource.GetAllPeople();
    ReportViewer1.LocalReport.DataSources.Add(new 
    Microsoft.Reporting.WebForms.ReportDataSource()
    {
        Name = "DataSet1",
        Value = people
    });

    byte[] byteViewer = ReportViewer1.LocalReport.Render("PDF");
    FileStream newFile;
    string filename = Guid.NewGuid().ToString() + ".pdf";
    string path = HttpContext.Current.Server.MapPath(@"\") + filename;
    newFile = new FileStream(path, FileMode.Create);
    newFile.Write(byteViewer, 0, byteViewer.Length);
    newFile.Flush();
    newFile.Close();
}

Najważniejsza część kodu znajduję się tutaj. Przed utworzeniem pliku PDF musimy dodać źródło danych do ReportViewer i nazwać go tak samo, jak fikcyjny "DataSet".

Kiedyś tutaj właśnie umieszczało się obiekt DataSet. Na szczęście można też umieścić kolekcję "IEnumerable", którą pobierzemy na swój własny sposób.

var people = MyDataSource.GetAllPeople();

ReportViewer1.LocalReport.DataSources.Add(
new Microsoft.Reporting.WebForms.ReportDataSource()
{
    Name = "DataSet1",
    Value = people
});

Oto wygenerowana tabelka w pliku PDF.

image

Przykład jest prosty. Jednak korzystając z ReportViewer, właśnie największym wyzwaniem jest rozgryzienie, jak korzystać z kolekcji "IEnumerable", nie kusząc się o stare rozwiązania i technologie.

Edit z roku 2022: Kod jest tutaj PanNiebieski/ReportViewerCollectionInWebForms (github.com)