1. 程式人生 > >iTextSharp5.0頁首頁尾及Asp.net預覽的實現(PDF匯出)

iTextSharp5.0頁首頁尾及Asp.net預覽的實現(PDF匯出)

iTextSharp5.0後沒有了HeaderFooter的類,導致頁首頁尾難以實現。經查資料後,發現可以通過PdfPageEventHelper裡面的OnEndPage來實現。先看看實現的效果圖。


頁首和頁尾部分使用PdfPTable來達成,下面是實現程式碼

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace ITextSharpTest
{
    public class PDFBase : PdfPageEventHelper
    {
        #region 屬性
        private String _fontFilePathForHeaderFooter = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "SIMHEI.TTF");
        /// <summary>
        /// 頁首/頁尾所用的字型
        /// </summary>
        public String FontFilePathForHeaderFooter
        {
            get
            {
                return _fontFilePathForHeaderFooter;
            }

            set
            {
                _fontFilePathForHeaderFooter = value;
            }
        }

        private String _fontFilePathForBody = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "SIMSUN.TTC,1");
        /// <summary>
        /// 正文內容所用的字型
        /// </summary>
        public String FontFilePathForBody
        {
            get { return _fontFilePathForBody; }
            set { _fontFilePathForBody = value; }
        }


        private PdfPTable _header;
        /// <summary>
        /// 頁首
        /// </summary>
        public PdfPTable Header
        {
            get { return _header; }
            private set { _header = value; }
        }

        private PdfPTable _footer;
        /// <summary>
        /// 頁尾
        /// </summary>
        public PdfPTable Footer
        {
            get { return _footer; }
            private set { _footer = value; }
        }


        private BaseFont _baseFontForHeaderFooter;
        /// <summary>
        /// 頁首頁尾所用的字型
        /// </summary>
        public BaseFont BaseFontForHeaderFooter
        {
            get { return _baseFontForHeaderFooter; }
            set { _baseFontForHeaderFooter = value; }
        }

        private BaseFont _baseFontForBody;
        /// <summary>
        /// 正文所用的字型
        /// </summary>
        public BaseFont BaseFontForBody
        {
            get { return _baseFontForBody; }
            set { _baseFontForBody = value; }
        }

        private Document _document;
        /// <summary>
        /// PDF的Document
        /// </summary>
        public Document Document
        {
            get { return _document; }
            private set { _document = value; }
        }

        #endregion


        public override void OnOpenDocument(PdfWriter writer, Document document)
        {
            try
            {
                BaseFontForHeaderFooter = BaseFont.CreateFont(FontFilePathForHeaderFooter, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                BaseFontForBody = BaseFont.CreateFont(FontFilePathForBody, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                Document = document;
            }
            catch (DocumentException de)
            {

            }
            catch (System.IO.IOException ioe)
            {

            }
        }

        #region GenerateHeader
        /// <summary>
        /// 生成頁首
        /// </summary>
        /// <param name="writer"></param>
        /// <returns></returns>
        public virtual PdfPTable GenerateHeader(iTextSharp.text.pdf.PdfWriter writer)
        {
            return null;
        }
        #endregion

        #region GenerateFooter
        /// <summary>
        /// 生成頁尾
        /// </summary>
        /// <param name="writer"></param>
        /// <returns></returns>
        public virtual PdfPTable GenerateFooter(iTextSharp.text.pdf.PdfWriter writer)
        {
            return null;
        }
        #endregion

        public override void OnEndPage(iTextSharp.text.pdf.PdfWriter writer, iTextSharp.text.Document document)
        {
            base.OnEndPage(writer, document);

            //輸出頁首
            Header = GenerateHeader(writer);
            Header.TotalWidth = document.PageSize.Width - 20f;
            ///呼叫PdfTable的WriteSelectedRows方法。該方法以第一個引數作為開始行寫入。
            ///第二個引數-1表示沒有結束行,並且包含所寫的所有行。
            ///第三個引數和第四個引數是開始寫入的座標x和y.
            Header.WriteSelectedRows(0, -1, 10, document.PageSize.Height - 20, writer.DirectContent);

            //輸出頁尾
            Footer = GenerateFooter(writer);
            Footer.TotalWidth = document.PageSize.Width - 20f;
            Footer.WriteSelectedRows(0, -1, 10, document.PageSize.GetBottom(50), writer.DirectContent);
        }
    }
}

注:為了便於使用,做了一個PDFBase,後續只需要繼承即可。
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace ITextSharpTest
{
    /// <summary>
    /// PDF報表
    /// </summary>
    public class PDFReport : PDFBase
    {
        #region 屬性
        private int _pageRowCount = 12;
        /// <summary>
        /// 每頁的資料行數
        /// </summary>
        public int PageRowCount
        {
            get { return _pageRowCount; }
            set { _pageRowCount = value; }
        }
        #endregion

        /// <summary>
        /// 模擬資料。實際時可能需要從資料庫或網路中獲取.
        /// </summary>
        private DataTable _dtSimulateData = null;

        private DataTable GenerateSimulateData()
        {
            DataTable dtSimulateData = new DataTable();
            dtSimulateData.Columns.Add("Order", typeof(int));//序號
            dtSimulateData.Columns.Add("No");//料號
            dtSimulateData.Columns.Add("Name");//名稱
            dtSimulateData.Columns.Add("Type");//型別
            dtSimulateData.Columns.Add("GetTime");//領取時間
            dtSimulateData.Columns.Add("BackTime");//歸還時間
            dtSimulateData.Columns.Add("Remark");//備註
            DataRow row = null;
            String[] types = new string[] { "文具", "輔料", "生活用品", "測試用具", "實體機" };
            DateTime getDate = DateTime.Now;
            DateTime backDate = DateTime.Now;
            for (int i = 0; i < 100; i++)
            {
                row = dtSimulateData.NewRow();
                row["Order"] = i + 1;
                row["No"] = (10000 + i + 1).ToString();
                row["Name"] = Guid.NewGuid().ToString().Substring(0, 5);//造出隨機名稱
                row["Type"] = types[(i * 3) % 5];
                row["GetTime"] = getDate.AddDays(i).ToString("yyyy-MM-dd");
                row["BackTime"] = ((i + i) % 3 == 0) ? "" : (backDate.AddDays(i + (i * 3) % 8).ToString("yyyy-MM-dd"));//造出沒有歸還時間的資料
                row["Remark"] = "XXXXXXX";
                dtSimulateData.Rows.Add(row);
            }
            return dtSimulateData;
        }

        #region GenerateHeader
        /// <summary>
        /// 生成頁首
        /// </summary>
        /// <param name="fontFilePath"></param>
        /// <param name="pageNumber"></param>
        /// <returns></returns>
        public override PdfPTable GenerateHeader(iTextSharp.text.pdf.PdfWriter writer)
        {
            BaseFont baseFont = BaseFontForHeaderFooter;
            iTextSharp.text.Font font_logo = new iTextSharp.text.Font(baseFont, 30, iTextSharp.text.Font.BOLD);
            iTextSharp.text.Font font_header1 = new iTextSharp.text.Font(baseFont, 16, iTextSharp.text.Font.BOLD);
            iTextSharp.text.Font font_header2 = new iTextSharp.text.Font(baseFont, 12, iTextSharp.text.Font.BOLD);
            iTextSharp.text.Font font_headerContent = new iTextSharp.text.Font(baseFont, 12, iTextSharp.text.Font.NORMAL);

            float[] widths = new float[] { 55, 300, 50, 90, 15, 20, 15 };

            PdfPTable header = new PdfPTable(widths);
            PdfPCell cell = new PdfPCell();
            cell.BorderWidthBottom = 2;
            cell.BorderWidthLeft = 2;
            cell.BorderWidthTop = 2;
            cell.BorderWidthRight = 2;
            cell.FixedHeight = 35;
            cell.Phrase = new Phrase("LOGO", font_logo);
            cell.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
            cell.VerticalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
            cell.PaddingTop = -1;
            header.AddCell(cell);

            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_LEFT);
            cell.Phrase = new Paragraph("PDF報表示例", font_header1);
            header.AddCell(cell);


            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_RIGHT);
            cell.Phrase = new Paragraph("日期:", font_header2);
            header.AddCell(cell);

            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_LEFT);
            cell.Phrase = new Paragraph("2015-07-27", font_headerContent);
            header.AddCell(cell);

            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_RIGHT);
            cell.Phrase = new Paragraph("第", font_header2);
            header.AddCell(cell);

            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_CENTER);
            cell.Phrase = new Paragraph(writer.PageNumber.ToString(), font_headerContent);
            header.AddCell(cell);

            cell = GenerateOnlyBottomBorderCell(2, iTextSharp.text.Element.ALIGN_RIGHT);
            cell.Phrase = new Paragraph("頁", font_header2);
            header.AddCell(cell);
            return header;
        }

        #region GenerateOnlyBottomBorderCell
        /// <summary>
        /// 生成只有底邊的cell
        /// </summary>
        /// <param name="bottomBorder"></param>
        /// <param name="horizontalAlignment">水平對齊方式<see cref="iTextSharp.text.Element"/></param>
        /// <returns></returns>
        private PdfPCell GenerateOnlyBottomBorderCell(int bottomBorder,
                                                            int horizontalAlignment)
        {
            PdfPCell cell = GenerateOnlyBottomBorderCell(bottomBorder, horizontalAlignment, iTextSharp.text.Element.ALIGN_BOTTOM);
            cell.PaddingBottom = 5;
            return cell;
        }

        /// <summary>
        /// 生成只有底邊的cell
        /// </summary>
        /// <param name="bottomBorder"></param>
        /// <param name="horizontalAlignment">水平對齊方式<see cref="iTextSharp.text.Element"/></param>
        /// <param name="verticalAlignment">垂直對齊方式<see cref="iTextSharp.text.Element"/</param>
        /// <returns></returns>
        private PdfPCell GenerateOnlyBottomBorderCell(int bottomBorder,
                                                            int horizontalAlignment,
                                                            int verticalAlignment)
        {
            PdfPCell cell = GenerateOnlyBottomBorderCell(bottomBorder);
            cell.HorizontalAlignment = horizontalAlignment;
            cell.VerticalAlignment = verticalAlignment; ;
            return cell;
        }

        /// <summary>
        /// 生成只有底邊的cell
        /// </summary>
        /// <param name="bottomBorder"></param>
        /// <returns></returns>
        private PdfPCell GenerateOnlyBottomBorderCell(int bottomBorder)
        {
            PdfPCell cell = new PdfPCell();
            cell.BorderWidthBottom = 2;
            cell.BorderWidthLeft = 0;
            cell.BorderWidthTop = 0;
            cell.BorderWidthRight = 0;
            return cell;
        }
        #endregion

        #endregion

        #region GenerateFooter
        public override PdfPTable GenerateFooter(iTextSharp.text.pdf.PdfWriter writer)
        {
            BaseFont baseFont = BaseFontForHeaderFooter;
            iTextSharp.text.Font font = new iTextSharp.text.Font(baseFont, 10, iTextSharp.text.Font.NORMAL);

            PdfPTable footer = new PdfPTable(3);
            AddFooterCell(footer, "審閱:", font);
            AddFooterCell(footer, "審批:", font);
            AddFooterCell(footer, "製表:張三", font);
            return footer;
        }

        private void AddFooterCell(PdfPTable foot, String text, iTextSharp.text.Font font)
        {
            PdfPCell cell = new PdfPCell();
            cell.BorderWidthTop = 2;
            cell.BorderWidthRight = 0;
            cell.BorderWidthBottom = 0;
            cell.BorderWidthLeft = 0;
            cell.Phrase = new Phrase(text, font);
            cell.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
            foot.AddCell(cell);
        }
        #endregion

        #region ExportPDF
        /// <summary>
        /// 匯出PDF
        /// </summary>
        /// <param name="path">匯出路徑</param>
        public static void ExportPDF(String path)
        {
            PDFReport pdfReport = new PDFReport();
            Document document = new Document(PageSize.A4.Rotate(), -90, -90, 60, 10);//此處設定的偏移量是為了加大頁面的可用範圍,可以使用預設.
            PdfWriter pdfWriter = PdfWriter.GetInstance(document, new FileStream(path, FileMode.Create));
            pdfWriter.PageEvent = pdfReport;//此處一定要賦值,才能觸發頁首和頁尾的處理
            document.Open();
            pdfReport.AddBody(document);
            document.Close();
        }

        /// <summary>
        /// 匯出PDF
        /// </summary>
        /// <param name="path">匯出路徑</param>
        public static byte[] ExportPDF()
        {
            PDFReport pdfReport = new PDFReport();
            Document document = new Document(PageSize.A4.Rotate(), -90, -90, 60, 10);//此處設定的偏移量是為了加大頁面的可用範圍,可以使用預設.
            MemoryStream ms = new MemoryStream();
            PdfWriter pdfWriter = PdfWriter.GetInstance(document, ms);
            pdfWriter.PageEvent = pdfReport;//此處一定要賦值,才能觸發頁首和頁尾的處理
            document.Open();
            pdfReport.AddBody(document);
            document.Close();
            byte[] buff = ms.ToArray();
            return buff;
        }
        #endregion

        #region AddBody
        private void AddBody(Document document)
        {
            _dtSimulateData = GenerateSimulateData();
            int count = (_dtSimulateData.Rows.Count + (PageRowCount - 1)) / PageRowCount;
            for (int i = 0; i < count; i++)
            {
                AddBodySinglePage(i + 1);
                document.NewPage();
            }
        }

        private void AddBodySinglePage(int pageNumber)
        {
            BaseFont baseFont = BaseFontForBody;
            iTextSharp.text.Font font_columnHeader = new iTextSharp.text.Font(baseFont, 11f, iTextSharp.text.Font.BOLD);
            iTextSharp.text.Font font_contentNormal = new iTextSharp.text.Font(baseFont, 9.5f, iTextSharp.text.Font.NORMAL);
            iTextSharp.text.Font font_contentSmall = new iTextSharp.text.Font(baseFont, 8f, iTextSharp.text.Font.NORMAL);

            int columnCount = 6;//此處是為了當列數很多時,便於迴圈生成所要的列寬比例
            float[] widths = new float[columnCount];
            for (int i = 0; i < columnCount; i++)
            {
                widths[i] = 1;
            }
            //需要加寬的再進行額外處理
            widths[3] = 2;//時間
            widths[4] = 3;//備註

            PdfPTable bodyTable = new PdfPTable(widths);
            bodyTable.SpacingBefore = 10;//與頭部的距離

            AddBodyHeader(bodyTable, font_columnHeader);
            AddBodyContent(bodyTable, font_contentNormal, font_contentSmall, pageNumber);

            Document.Add(bodyTable);
        }

        #region AddBodyHeader
        /// <summary>
        /// 新增Body的列標題
        /// </summary>
        /// <param name="document"></param>
        /// <param name="font_columnHeader"></param>
        private void AddBodyHeader(PdfPTable bodyTable, iTextSharp.text.Font font_columnHeader)
        {
            //採用Rowspan和Colspan來控制單元格的合併與拆分,類似於HTML的Table.
            AddColumnHeaderCell(bodyTable, "料號", font_columnHeader, 1, 2);
            AddColumnHeaderCell(bodyTable, "名稱", font_columnHeader, 1, 2);
            AddColumnHeaderCell(bodyTable, "種類", font_columnHeader, 1, 2);
            AddColumnHeaderCell(bodyTable, "時間", font_columnHeader, 2, 1);//表頭下還有兩列表頭
            AddColumnHeaderCell(bodyTable, "備註", font_columnHeader, 1, 2, true, true);

            //時間
            AddColumnHeaderCell(bodyTable, "領取", font_columnHeader);
            AddColumnHeaderCell(bodyTable, "歸還", font_columnHeader, true, true);
        }
        #endregion

        #region AddBodyContent Function
        /// <summary>
        /// 新增報表正文
        /// </summary>
        /// <param name="bodyTable"></param>
        /// <param name="fontNormal">普通字型</param>
        /// <param name="fontSmall">小字型,當內容顯示不下,需要使用小字型來顯示時,可以使用.</param>
        /// <param name="pageNumber">頁碼。便於從資料庫中按頁拉取資料時使用.</param>
        public void AddBodyContent(PdfPTable bodyTable,
                                   iTextSharp.text.Font fontNormal,
                                   iTextSharp.text.Font fontSmall,
                                   int pageNumber)
        {
            String filterExpression = String.Format("Order>{0} AND Order<={1}",
                                                    (pageNumber - 1) * PageRowCount,
                                                     pageNumber * PageRowCount);
            DataRow[] rows = _dtSimulateData.Select(filterExpression);
            foreach (var row in rows)
            {
                AddBodyContentRow(bodyTable, fontNormal, fontSmall, row);
            }
        }

        private void AddBodyContentRow(PdfPTable bodyTable, iTextSharp.text.Font fontNormal, iTextSharp.text.Font fontSmall, DataRow row)
        {
            AddBodyContentCell(bodyTable, String.Format("{0}", row["No"]), fontNormal);//料號
            AddBodyContentCell(bodyTable, String.Format("{0}", row["Name"]), fontNormal);//名稱
            AddBodyContentCell(bodyTable, String.Format("{0}", row["Type"]), fontNormal);//種類
            AddBodyContentCell(bodyTable, String.Format("{0}", row["GetTime"]), fontSmall, 1);//時間-領取
            String backTime = String.Format("{0}", row["BackTime"]);
            AddBodyContentCell(bodyTable, backTime, fontSmall);//時間-歸還
            AddBodyContentCell(bodyTable, String.Format("{0}", row["Remark"]), fontSmall, 2, true);//備註  

            AddBodyContentCell(bodyTable, (String.IsNullOrWhiteSpace(backTime)) ? "消耗品不需歸還" : "", fontSmall, 1);//時間-領取(下方說明)
        }

        private static void AddBodyContentCell(PdfPTable bodyTable,
                                               String text,
                                               iTextSharp.text.Font font,
                                               int rowspan = 2,
                                               bool needRightBorder = false)
        {
            PdfPCell cell = new PdfPCell();
            float defaultBorder = 0.5f;
            cell.BorderWidthLeft = defaultBorder;
            cell.BorderWidthTop = 0;
            cell.BorderWidthRight = needRightBorder ? defaultBorder : 0;
            cell.BorderWidthBottom = defaultBorder;
            cell.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
            cell.VerticalAlignment = iTextSharp.text.Element.ALIGN_BASELINE;
            cell.Rowspan = rowspan;
            cell.PaddingBottom = 4;
            cell.Phrase = new Phrase(text, font);
            cell.FixedHeight = 18f;
            bodyTable.AddCell(cell);
        }
        #endregion

        #region AddColumnHeaderCell Function
        /// <summary>
        /// 新增列標題單元格
        /// </summary>
        /// <param name="table">表格行的單元格列表</param>
        /// <param name="header">標題</param>
        /// <param name="font">欄位</param>
        /// <param name="colspan">列空間</param>
        /// <param name="rowspan">行空間</param>
        /// <param name="needLeftBorder">是否需要左邊框</param>
        /// <param name="needRightBorder">是否需要右邊框</param>
        public void AddColumnHeaderCell(PdfPTable table,
                                                String header,
                                                iTextSharp.text.Font font,
                                                int colspan,
                                                int rowspan,
                                                bool needLeftBorder = true,
                                                bool needRightBorder = false)
        {
            PdfPCell cell = GenerateColumnHeaderCell(header, font, needLeftBorder, needRightBorder);
            if (colspan > 1)
            {
                cell.Colspan = colspan;
            }

            if (rowspan > 1)
            {
                cell.Rowspan = rowspan;
            }

            table.AddCell(cell);
        }

        /// <summary>
        /// 新增列標題單元格
        /// </summary>
        /// <param name="table">表格</param>
        /// <param name="header">標題</param>
        /// <param name="font">欄位</param>
        /// <param name="needLeftBorder">是否需要左邊框</param>
        /// <param name="needRightBorder">是否需要右邊框</param>
        public void AddColumnHeaderCell(PdfPTable table,
                                                String header,
                                                iTextSharp.text.Font font,
                                                bool needLeftBorder = true,
                                                bool needRightBorder = false)
        {
            PdfPCell cell = GenerateColumnHeaderCell(header, font, needLeftBorder, needRightBorder);
            table.AddCell(cell);
        }
        #endregion

        #region GenerateColumnHeaderCell
        /// <summary>
        /// 生成列標題單元格
        /// </summary>
        /// <param name="header">標題</param>
        /// <param name="font">欄位</param>
        /// <param name="needLeftBorder">是否需要左邊框</param>
        /// <param name="needRightBorder">是否需要右邊框</param>
        /// <returns></returns>
        private PdfPCell GenerateColumnHeaderCell(String header,
                                                        iTextSharp.text.Font font,
                                                        bool needLeftBorder = true,
                                                        bool needRightBorder = false)
        {
            PdfPCell cell = new PdfPCell();
            float border = 0.5f;
            cell.BorderWidthBottom = border;
            if (needLeftBorder)
            {
                cell.BorderWidthLeft = border;
            }
            else
            {
                cell.BorderWidthLeft = 0;
            }

            cell.BorderWidthTop = border;
            if (needRightBorder)
            {
                cell.BorderWidthRight = border;
            }
            else
            {
                cell.BorderWidthRight = 0;
            }

            cell.HorizontalAlignment = iTextSharp.text.Element.ALIGN_CENTER;
            cell.VerticalAlignment = iTextSharp.text.Element.ALIGN_BASELINE;
            cell.PaddingBottom = 4;
            cell.Phrase = new Phrase(header, font);
            return cell;
        }
        #endregion

        #endregion
    }
}
注:程式碼對關鍵呼叫作了註釋。
Asp.net中的呼叫
 public partial class _default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                byte[] buff = PDFReport.ExportPDF();
                Response.ContentType = "application/pdf";
                Response.BinaryWrite(buff);
            }
        }
    }

WinForm中的呼叫
  private void btnExportPdf_Click(object sender, EventArgs e)
        {
            try
            {

                String path = textBoxPath.Text;
                if (String.IsNullOrWhiteSpace(path))
                {
                    MessageBox.Show("請輸入路徑");
                    return;
                }

                if (!Directory.Exists(Path.GetDirectoryName(path)))
                {
                    MessageBox.Show("指定的目錄不存在");
                    return;
                }

                if (".PDF" != Path.GetExtension(path).ToUpper())
                {
                    path = path + ".pdf";
                }
                PDFReport.ExportPDF(path);
                MessageBox.Show("匯出成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

原始碼下載http://download.csdn.net/detail/xxdddail/8943371

轉載請註明出處http://blog.csdn.net/xxdddail/article/details/47128319