利用ItextSharp產PDF完整操作


 記得上回有寫到用C#操作Excel(.net 4.0)

很多朋友說推薦用NPOI,的確,用微軟自帶的操作execl會有很大的問題。客戶的主機不願意安裝excel,
這時我才意識到用自帶組件完全是不行的,我本來准備改用NPOI組件,但是這時客戶提出為了安全(數據安全),改用后台產PDF。
這就有了本文中ITextSharp的用法
本文介紹了基本全套的用法,包括頁眉,頁首,表格的用法,但是還是有很多問題沒有處理好,只是把我已經ok的地方拿出來給一些需要的朋友學習。
 
一:下載地址
下面這篇博文說明了ITextsharp的下載地址,本人就是按照這篇文章進行的下載
注意版本不同,一些函數的用法也不相同了
 
二:產出PDF
 
 /// <summary>
        /// 產生PDf /// </summary>
        /// <param name="strFileName">文件名稱</param>
        /// <param name="dt">數據源</param>
        public void PDF(string strFileName, DataTable dt, string PrintName) { if (!Directory.Exists(AppConfigString.FilePath)) { Directory.CreateDirectory(AppConfigString.FilePath); } string strPathTemp = AppConfigString.FilePath + DateTime.Now.ToString("yyyyMMddhhmmss") + ".pdf"; //零時的pdf地址,用於水印讀取文件
            string strPath = AppConfigString.FilePath + strFileName;//真正文件的位置
            Document document = new Document(PageSize.A4, 25, 25, 25, 25); FileStream stream = new FileStream(strPathTemp, FileMode.Create); PdfWriter writer = PdfWriter.GetInstance(document, stream); document.Footer = Foot();//頁尾的函數,在open前定義
 document.Open(); HeaderFooter head = new HeaderFooter(HeadTable(3, PrintName), true); //true為在頁眉的右邊生成一個頁數,會影響到頁眉的高度,在open后定義 //headTable為頁眉的函數
            head.Border = Rectangle.NO_BORDER; document.Header = head; //頁眉第一頁不會出現,第2頁才會出現,所以此地直接在第一列加了一個表頭 //頁尾在第一頁就會出現
            document.Add(HeadTable(3, PrintName));//第一頁表頭不自動添加 //主要數據的添加
            int IRowCount = dt.Rows.Count; int IColumnCount = dt.Columns.Count; PdfPTable pdfTb = new PdfPTable(IColumnCount); pdfTb.HeaderRows = 1;//自動加表頭
            for (int i = 0; i < IRowCount; i++) { for (int j = 0; j < IColumnCount; j++) { string value = dt.Rows[i][j].ToString(); Phrase phs = new Phrase(value, PdfFont.Font(3)); //此時把數據轉為Phrase只是為了使用字體,不然中文不能顯示
 pdfTb.AddCell(phs); } } document.Add(pdfTb); document.Close(); writer.Close(); PDFWatermark(strPathTemp, strPath, 10, 10, PrintName);//為生成好的文件添加水印
 }
 上面為一段完整的使用過程,注釋是我剛加的,比較詳細了,說下面幾個問題  1:頁眉和頁首    》頁眉與頁首都使用相同的類HeaderFooter,只是頁眉是給 document.Header,頁尾是給document.Footer    》頁尾是在document.open前,頁眉是在document.open后    》頁眉第一頁不會出現,第2頁才會出現,所以此地直接在第一列加了一個表頭。頁尾在第一頁就會出現。  2:頁眉的制作方法   由於頁眉不好制作,所以我選擇直接先拼成PdfPTable,再把PdfPTable放到Phrase,再把Phrase放到HeaderFooter給頁眉,這樣就好操作些   這個是在百度知道上找到的思路,我就這樣做了,呵呵...  下面為我制作頁眉的方法,一些信息安全問題已換為XXXXX 
/// <summary>
        /// 產生表頭的數據 /// </summary>
        /// <param name="IType">1:ID 2:Name 3:detali</param>
        /// <returns></returns>
        public Phrase HeadTable(int IType, string PrintName) { string strhead = ""; switch (IType) { case 1: strhead = "XXXXXXXXXXXXXXXXXXXX"; break; case 2: strhead = "XXXXXXXXXXXXXXXXXXXX"; break; case 3: strhead = "XXXXXXXXXXXXXXXXXXXX"; break; } Phrase phshead = new Phrase(strhead, PdfFont.Font(1)); Phrase phsjimi = new Phrase("XXXXXXXXXXXXXXXXXXXX ", PdfFont.Font(3)); Phrase phsPeople = new Phrase("XXXXXXXXXXXXXXXXXXXX" + PrintName + "XXXXXXXXXXXXXXXXXXXX" + PrintName, PdfFont.Font(3)); Phrase phsPage = new Phrase(" ", PdfFont.Font(3)); Phrase phsPrintDate = new Phrase("列印時間:" + DateTime.Now.ToString("yyyy/MM/dd hh:mm") + "\r\n Print Date:" + DateTime.Now.ToString("yyyy/MM/dd hh:mm"), PdfFont.Font(3)); PdfPCell pchead = new PdfPCell(phshead); pchead.VerticalAlignment = 1; pchead.HorizontalAlignment = 1; PdfPCell pcjimi = new PdfPCell(phsjimi); PdfPCell pcPeople = new PdfPCell(phsPeople); PdfPCell pcPage = new PdfPCell(phsPage); PdfPCell pcPrintDate = new PdfPCell(phsPrintDate); PdfPCell pcnull = new PdfPCell(); pchead.Border = 0; pcjimi.Border = 0; pcPeople.Border = 0; pcPage.Border = 0; pcPrintDate.Border = 0; pcnull.Border = 0; pcPeople.PaddingBottom = 10; pcPrintDate.PaddingBottom = 10; Phrase phead = new Phrase(); PdfPTable thead = new PdfPTable(2); thead.AddCell(pchead); thead.AddCell(pcjimi); thead.AddCell(pcnull); thead.AddCell(pcPage); thead.AddCell(pcPeople); thead.AddCell(pcPrintDate); thead.SetWidths(new float[] { PageSize.A4.Width, 200 }); phead.Add(thead); return phead; }
 
 
 頁尾的方法
        /// <summary>
        /// 頁尾 /// </summary>
        /// <returns></returns>
        public HeaderFooter Foot() { string strFoot = @"XXXXXXXXXXXXXXXXXX"; Phrase pfoot = new Phrase(strFoot, PdfFont.Font(2)); HeaderFooter foot = new HeaderFooter(pfoot, false); foot.Border = Rectangle.NO_BORDER; return foot; }
 3:字體的問題  如果沒有定義字體,漢字是不會出現的,下面是我定義的字體,使用的ITextSharp控件字體,當然也可以使用字體文件詳情可查看http://winsystem.ctocio.com.cn/334/12194834.shtml 
        /// <summary>
        /// 文字類型定義 /// </summary>
        /// <param name="IType">返回文字類別</param>
        /// <returns></returns>
        public static Font Font(int IType) { BaseFont.AddToResourceSearch("iTextAsian.dll"); BaseFont.AddToResourceSearch("iTextAsianCmaps.dll"); BaseFont bf = BaseFont.CreateFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); //簡體?繁體不能使用 //             Font font = new Font(bf);//普通文章
            font.Size = 10; Font fontFoot = new Font(bf);//頁腳文字
            fontFoot.Size = 7; fontFoot.Color = Color.RED; Font fontNormal = new Font(bf);//正常文字
            fontNormal.Size = 7; switch (IType) { case 1: return font; case 2: return fontFoot; case 3: return fontNormal; default: return fontNormal; } }
 
4:主要內容的制作 根據數據源,利用PdfPTable和Phase等制作,塊等我還沒用會,主要是樣式和定位沒搞會下面的博客有在Asp.Net中操作PDF – iTextSharp -利用塊,短語,段落添加文本的方法http://www.cnblogs.com/CareySon/archive/2011/11/03/2234625.html5:水印的添加
        /// <summary>
        /// 為生成的pdf添加水印 /// </summary>
        /// <param name="inputfilepath"></param>
        /// <param name="outputfilepath"></param>
        /// <param name="top"></param>
        /// <param name="left"></param>
        /// <returns></returns>
        public bool PDFWatermark(string inputfilepath, string outputfilepath, float top, float left, string strName) { PdfReader pdfReader = null; PdfStamper pdfStamper = null; try { pdfReader = new PdfReader(inputfilepath); int numberOfPages = pdfReader.NumberOfPages; iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1); float width = psize.Width; float height = psize.Height; pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create)); PdfContentByte waterMarkContent; WatermarkCreater wmc = new WatermarkCreater(); Draw.Image image = wmc.GetImageByte(strName, AppConfigString.WaterMarkPath); var img = Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Png); if (left < 0) { left = width - image.Width + left; } img.SetAbsolutePosition(left, (height - image.Height) - top); //每一頁加水印,也可以設置某一頁加水印 
                for (int i = 1; i <= numberOfPages; i++) { waterMarkContent = pdfStamper.GetUnderContent(i); waterMarkContent.AddImage(img); } return true; } catch (Exception ex) { ex.Message.Trim(); return false; } finally { if (pdfStamper != null) pdfStamper.Close(); if (pdfReader != null) pdfReader.Close(); //把添加水印前的pdf文件刪除,保存最新的文件
                if (File.Exists(inputfilepath)) { File.Delete(inputfilepath); } } }
這就是我們為什么要用一個零時路徑了,先把產出的pdf放到零時路徑,用來產生水印的時候讀取,生成水印文件后,再把零時文件刪除即可其中的WatermarkCreater方法可以看我以前的博客,報表水印的產生http://www.cnblogs.com/xiaoshuai1992/p/waterMark.html,方法相同 至此可以達到客戶的要求,但是一些樣式的問題就需要大家仔細研究了,這就是我的實踐過程,希望可以和大家一起學習了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM