Click here to Skip to main content
15,892,697 members
Articles / Productivity Apps and Services / Microsoft Office

Export Tabular Data in PDF Format through the Web

Rate me:
Please Sign up or sign in to vote.
4.57/5 (12 votes)
13 Oct 2011CPOL5 min read 47.2K   1.3K   21  
This article presents an example to export tabular data in PDF format through the web.
using System;
using System.Linq;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Data;
using System.Collections.Generic;

namespace iTextTabularReport.Utilities
{
    // The main class used to generate Pdf tabular report.
    public class PdfTabularReport
    {
        // Configurations
        public ReportConfiguration ReportConfiguration { get; set; }

        // Internal properties, not set outside of the class
        public Image LogoImage { get; private set; }
        public PdfPTable Title { get; private set; }
        public PdfPTable PageNumberLabel { get; private set; }
        public float HeaderSectionHeight { get; private set; }
        public int PageCount { get; private set; }

        // Private instance variables
        Document PdfDocument = null;
        PdfWriter PdfWriter = null;
        MemoryStream PdfStream = null;

        // Constructor
        public PdfTabularReport(ReportConfiguration configuration = null)
        {
            // If configuration is not provided, the default will be used
            ReportConfiguration = configuration ?? new ReportConfiguration();
        }

        private void InitiateDocument()
        {
            PdfStream = new MemoryStream();
            PdfDocument = new Document(ReportConfiguration.PageOrientation);
            PdfDocument.SetMargins(ReportConfiguration.MarginLeft,
                ReportConfiguration.MarginRight,
                ReportConfiguration.MarginTop, ReportConfiguration.MarginBottom);
            PdfWriter = PdfWriter.GetInstance(PdfDocument, PdfStream);

            // create logo, header and page number objects
            PdfPCell cell;
            HeaderSectionHeight = 0;
            LogoImage = null;
            if (ReportConfiguration.LogoPath != null)
            {
                LogoImage = Image.GetInstance(ReportConfiguration.LogoPath);
                LogoImage.ScalePercent(ReportConfiguration.LogImageScalePercent);
                LogoImage.SetAbsolutePosition(PdfDocument.LeftMargin,
                    PdfDocument.PageSize.Height - PdfDocument.TopMargin
                        - LogoImage.ScaledHeight);

                HeaderSectionHeight = LogoImage.ScaledHeight;
            }

            Title = null;
            float titleHeight = 0;
            if ((ReportConfiguration.ReportTitle != null) ||
                (ReportConfiguration.ReportSubTitle != null))
            {
                Title = new PdfPTable(1);
                Title.TotalWidth = PdfDocument.PageSize.Width
                    - (PdfDocument.LeftMargin + PdfDocument.RightMargin);

                if (ReportConfiguration.ReportTitle != null)
                {
                    cell = new PdfPCell(new Phrase(ReportConfiguration.ReportTitle,
                                               new Font(ReportFonts.HelveticaBold, 12)));
                    cell.HorizontalAlignment = Element.ALIGN_CENTER;
                    cell.Border = 0;
                    Title.AddCell(cell);
                }

                if (ReportConfiguration.ReportSubTitle != null)
                {
                    cell = new PdfPCell(new Phrase(ReportConfiguration.ReportSubTitle,
                                               new Font(ReportFonts.Helvetica, 10)));
                    cell.HorizontalAlignment = Element.ALIGN_CENTER;
                    cell.PaddingTop = 5;
                    cell.Border = 0;
                    Title.AddCell(cell);
                }

                // Get the height of the title section
                for (int i = 0; i < Title.Rows.Count; i++)
                {
                    titleHeight = titleHeight + Title.GetRowHeight(i);
                }
            }
            HeaderSectionHeight = (HeaderSectionHeight > titleHeight)
                ? HeaderSectionHeight : titleHeight;


            PageNumberLabel = new PdfPTable(1);
            PageNumberLabel.TotalWidth = PdfDocument.PageSize.Width
                               - (PdfDocument.LeftMargin + PdfDocument.RightMargin);
            cell = new PdfPCell(new Phrase("Page Label", new Font(ReportFonts.Helvetica, 8)));
            cell.Border = 0;
            float pagenumberHeight = PageNumberLabel.GetRowHeight(0);
            HeaderSectionHeight = (HeaderSectionHeight > pagenumberHeight)
                ? HeaderSectionHeight : pagenumberHeight;
        }

        private MemoryStream RenderDocument(ReportTable reportTable)
        {
            PdfWriter.PageEvent = new PageEventHelper { Report = this };
            PdfDocument.Open();
            reportTable.RenderTable(PdfDocument, PdfWriter);
            PdfDocument.Close();
            PdfWriter.Flush();
            return PdfStream;
        }

        // Method to get the pdf stream
        public MemoryStream GetPdf<T>(List<T> data, List<ReportColumn> displayColumns)
        {
            InitiateDocument();

            // Add the report data
            var top = (HeaderSectionHeight == 0)
                          ? PdfDocument.PageSize.Height - PdfDocument.TopMargin
                          : PdfDocument.PageSize.Height - PdfDocument.TopMargin
                          - HeaderSectionHeight - 10;
            var reportTable = ReportTable.CreateReportTable<T>(data,
                displayColumns, top, PdfDocument);
            PageCount = reportTable.PageCount;

            return RenderDocument(reportTable);
        }

        // Overloaded method to get the pdf stream. It takes that data as DataTable
        public MemoryStream GetPdf(DataTable data, List<ReportColumn> displayColumns)
        {
            List<DataRow> list = data.AsEnumerable().ToList();
            return GetPdf<DataRow>(list, displayColumns);
        }
    }

    // Fonts used by the tabular report
    public class ReportFonts
    {
        public static BaseFont Helvetica {
            get { return BaseFont.CreateFont(BaseFont.HELVETICA,
                BaseFont.CP1252, false); } }
        public static BaseFont HelveticaBold {
            get { return BaseFont.CreateFont(BaseFont.HELVETICA_BOLD,
                BaseFont.CP1252, false); } }
    }

    // Utility class to render the Pdf table to the report document
    internal class ReportTable
    {
        private PdfPTable headerTable;
        private PdfPTable dataTable;
        private List<Tuple<int, int>> pageSplitter;
        private float width;
        private float top;
        private float height;

        public int PageCount
        {
            get { return (pageSplitter.Count == 0) ? 1 : pageSplitter.Count; }
        }

        // Private constructor. The instances need to use "CreateReportTable"
        // method to create.
        private ReportTable(List<ReportColumn> displayColumns,
            Document document, float top)
        {
            pageSplitter = new List<Tuple<int, int>>();
            this.top = top;
            width = document.PageSize.Width
                              - document.LeftMargin - document.RightMargin;
            height = top - document.BottomMargin;

            float[] columnWidths =
                (from c in displayColumns select (float)c.Width).ToArray();
            headerTable = new PdfPTable(columnWidths);
            headerTable.TotalWidth = width;
            dataTable = new PdfPTable(columnWidths);
            dataTable.TotalWidth = width;

            foreach (var column in displayColumns)
            {
                AddCell(headerTable, column.HeaderText,
                    new Font(ReportFonts.HelveticaBold, 10), BaseColor.WHITE, 5f);
            }
        }

        private static void AddCell(PdfPTable table, string Text, Font font,
            BaseColor backgroundColor = null, float padding = 3f)
        {
            PdfPCell cell = new PdfPCell(new Paragraph(Text, font));
            cell.Padding = padding;
            cell.Border = 0;
            cell.VerticalAlignment = Element.ALIGN_MIDDLE;
            cell.BackgroundColor = backgroundColor ?? BaseColor.WHITE;
            table.AddCell(cell);
        }

        private static void AddRow(Object dataitem, System.Type type,
            List<ReportColumn> displayColumns, BaseColor color, PdfPTable table)
        {
            foreach (var column in displayColumns)
            {
                var text = string.Empty;

                if (type.FullName == "System.Data.DataRow")
                {
                    text = ((DataRow) dataitem)[column.ColumnName].ToString();
                }
                else
                {
                    var propertyInfo = type.GetProperty(column.ColumnName);
                    text = (propertyInfo.GetValue(dataitem, null) == null)
                               ? ""
                               : propertyInfo.GetValue(dataitem, null).ToString();
                }

                AddCell(table, text, new Font(ReportFonts.Helvetica, 8), color);
            }
        }

        // Static method to create & return an instance object
        public static ReportTable CreateReportTable<T>(List<T> data,
            List<ReportColumn> displayColumns, float top, Document document)
        {
            // Construct an instance object
            var reportTable = new ReportTable(displayColumns, document, top);
            var type = typeof(T);

            // Add each data item into the PdfPTable.
            int srartRow = 0;
            int pageRowIndex = 0;
            float headerHeight = reportTable.headerTable.GetRowHeight(0);
            float actualHeight = headerHeight;
            for (int i = 0; i < data.Count; i++)
            {
                var dataItem = data[i];
                BaseColor color = (pageRowIndex++ % 2 == 0)
                    ? BaseColor.LIGHT_GRAY : BaseColor.WHITE;

                AddRow(dataItem, type, displayColumns, color, reportTable.dataTable);

                actualHeight = actualHeight + reportTable.dataTable.GetRowHeight(i);
                var lastRowReached = i == data.Count - 1;
                if ((actualHeight > reportTable.height) || lastRowReached)
                {
                    reportTable.pageSplitter.Add(new Tuple<int, int>(srartRow,
                        lastRowReached ? -1 : i));

                    if (!lastRowReached)
                    {
                        reportTable.dataTable.DeleteLastRow();
                        AddRow(dataItem, type, displayColumns, BaseColor.LIGHT_GRAY,
                            reportTable.dataTable);
                        pageRowIndex = 1;
                    }

                    actualHeight = headerHeight + reportTable.dataTable.GetRowHeight(i);
                    srartRow = i;
                }
            }

            return reportTable;
        }

        // Render the table to the Pdf document.
        public void RenderTable(Document document, PdfWriter writer)
        {
            float left = (document.PageSize.Width - headerTable.TotalWidth)/2;
            
            var pageCount = pageSplitter.Count;
            float headerHeight = headerTable.GetRowHeight(0);
            for (int i = 0; i < pageCount; i++)
            {
                var rownumbers = pageSplitter[i];
                headerTable.WriteSelectedRows(0, 1, left, top, writer.DirectContent);
                dataTable.WriteSelectedRows(rownumbers.Item1, rownumbers.Item2,
                        left, top - headerHeight, writer.DirectContent);

                if (i != pageCount - 1)
                {
                    document.NewPage();
                }
            }
        }
    }

    // PdfPageEventHelper: logo, title, sub-title, and page numbers.
    public class PageEventHelper: PdfPageEventHelper
    {
        public PdfTabularReport Report { get; set; }

        private void AddHeader(Document document, PdfWriter writer)
        {
            // Add logo
            if (Report.LogoImage != null)
            {
                document.Add(Report.LogoImage);
            }

            // Add titles
            if (Report.Title != null)
            {
                Report.Title.WriteSelectedRows(0, -1, document.LeftMargin,
                    document.PageSize.Height - document.TopMargin, writer.DirectContent);
            }

            // Add page number
            Report.PageNumberLabel.DeleteLastRow();
            var cell = new PdfPCell(new Phrase("Page " + document.PageNumber.ToString()
                + " of "
                + Report.PageCount.ToString(), new Font(ReportFonts.Helvetica, 8)));
            cell.Border = 0;
            cell.HorizontalAlignment = Element.ALIGN_RIGHT;
            Report.PageNumberLabel.AddCell(cell);
            var cellHeight = Report.PageNumberLabel.GetRowHeight(0);
            Report.PageNumberLabel.WriteSelectedRows(0, -1, document.LeftMargin,
                document.PageSize.Height - document.TopMargin - Report.HeaderSectionHeight
                + cellHeight, writer.DirectContent);
        }

        public override void OnStartPage(PdfWriter writer, Document document)
        {
            base.OnStartPage(writer, document);
            AddHeader(document, writer);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
I have been working in the IT industry for some time. It is still exciting and I am still learning. I am a happy and honest person, and I want to be your friend.

Comments and Discussions