莊周夢(mèng)蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          iText操作PDF問題總結(jié)

          Posted on 2007-04-02 15:52 dennis 閱讀(12830) 評(píng)論(9)  編輯  收藏 所屬分類: java
              這個(gè)星期我的任務(wù)就是處理一些報(bào)表的打印問題,因?yàn)槲宜沩?xiàng)目組里對(duì)jasperreport比較熟悉的了,這個(gè)東東也是我引進(jìn)到這個(gè)項(xiàng)目。ireport畫報(bào)表,使用struts的action輸出PDF到瀏覽器,這是我們目前的解決方案。今天遇到一個(gè)ireport解決不了的要求——合并單元格。類似下面這樣的表結(jié)構(gòu):
          ----------------------------------------------
                    |          |__c_____________
             dept   | value    |__b_____________
                    |          |  a
          --------------------------------------------------------
          也就是需要跨行,跨列!-_-。在html表格中解決這個(gè)很簡(jiǎn)單,只要設(shè)置單元格的colspan和rowspan即可。我在ireport沒有找到解決方案,如果您知道,請(qǐng)不吝賜教。查找資料弄了兩個(gè)小時(shí)沒進(jìn)展,決定自己用iText寫吧,通過google、baidu資料順利達(dá)到了我的要求,僅在此記錄下遇到的問題和解決方法。

          一。一個(gè)HelloWorld實(shí)例:
          package com.lowagie.examples.general;

            
          import java.io.FileOutputStream;
            
          import java.io.IOException;

            
          import com.lowagie.text.*;
            
          import com.lowagie.text.pdf.PdfWriter;

            
          /**
             * Generates a simple 'Hello World' PDF file.
             *
             * 
          @author blowagie
             
          */

            
          public class HelloWorld {

              
          /**
               * Generates a PDF file with the text 'Hello World'
               *
               * 
          @param args no arguments needed here
               
          */
              
          public static void main(String[] args) {

                System.out.println(
          "Hello World");

                
          // step a: creation of a document-object
                Document document = new Document();
                
          try {
                  
          // step b:
                  
          // we create a writer that listens to the document
                  
          // and directs a PDF-stream to a file
                  PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));

                  
          // step c: we open the document
                  document.open();
                  
          // step d: we add a paragraph to the document
                  document.add(new Paragraph("Hello World"));
                } 
          catch (DocumentException de) {
                  System.err.println(de.getMessage());
                } 
          catch (IOException ioe) {
                  System.err.println(ioe.getMessage());
                }

                
          // step e: we close the document
                  document.close();
                }
              }
          可以看到一個(gè)PDF文件的輸出,總共只需要5個(gè)步驟
          a.創(chuàng)建一個(gè)Document實(shí)例
            Document document = new Document();
          b.將Document實(shí)例和文件輸出流用PdfWriter類綁定在一起
            PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));
          c.打開文檔
            document.open();
          d.在文檔中添加文字
            document.add(new Paragraph("Hello World"));
          e.關(guān)閉文檔
            document.close();
          這樣5個(gè)步驟,就可以生成一個(gè)PDF文檔了。

          二。如何使用jsp、servlet輸出iText生成的pdf?
            如果每次都在服務(wù)端生成一個(gè)PDF文件給用戶,不僅麻煩,而且浪費(fèi)服務(wù)器資源,最好的方法就是以二進(jìn)制流的形式輸送到客戶端。
          1)JSP輸出:
          <%@ page import="java.io.*,java.awt.Color,com.lowagie.text.*,com.lowagie.text.pdf.*"%>

          <%
          response.setContentType
          "application/pdf" );
          Document document 
          = new Document();
          ByteArrayOutputStream buffer
          = new ByteArrayOutputStream();
          PdfWriter writer
          =
          PdfWriter.getInstance( document, buffer );
          document.open();
          document.add(
          new Paragraph("Hello World"));
          document.close();
          DataOutput output 
          =
          new DataOutputStream
          ( response.getOutputStream() );
          byte[] bytes = buffer.toByteArray();
          response.setContentLength(bytes.length);
          forint i = 0;
          < bytes.length;
          i
          ++ )
          {
          output.writeByte( bytes[i] );
          }
          %>

          2)servlet輸出,稍微改造下就可以使用在struts中:
          import java.io.*;
          import javax.servlet.*;
          import javax.servlet.http.*;
          import com.lowagie.text.*;
          import com.lowagie.text.pdf.*;
          public void doGet
          (HttpServletRequest request,
          HttpServletResponse response)
          throws IOException,ServletException
          {
          Document document 
          =
          new Document(PageSize.A4, 36,36,36,36);
          ByteArrayOutputStream ba
          = new ByteArrayOutputStream();
          try
          {
          PdfWriter writer 
          =
          PdfWriter.getInstance(document, ba);
          document.open();
          document.add(
          new
          Paragraph(
          "Hello World"));
          }
          catch(DocumentException de)
          {
          de.printStackTrace();
          System.err.println
          (
          "A Document error:" +de.getMessage());
          }
          document.close();
          response.setContentType
          (
          "application/pdf");
          response.setContentLength(ba.size());
          ServletOutputStream out
          = response.getOutputStream();
          ba.writeTo(out);
          out.flush();
          }


          三。如何輸出中文?
              首先需要下載iTextAsian.jar包,可以到iText的主站上下,ireport也是需要這個(gè)包的。然后定義中文字體:
              private static final Font getChineseFont() {
                  Font FontChinese 
          = null;
                  
          try {
                      BaseFont bfChinese 
          = BaseFont.createFont("STSong-Light",
                              
          "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                      FontChinese 
          = new Font(bfChinese, 12, Font.NORMAL);
                  } 
          catch (DocumentException de) {
                      System.err.println(de.getMessage());
                  } 
          catch (IOException ioe) {
                      System.err.println(ioe.getMessage());
                  }
                  
          return FontChinese;
              }

          我將產(chǎn)生中文字體封裝在方法內(nèi),自定義一個(gè)段落PDFParagraph繼承自Paragraph,默認(rèn)使用中文字體:
          class PDFParagraph extends Paragraph {
                  
          public PDFParagraph(String content) {
                      
          super(content, getChineseFont());
                  }
              }

          使用的時(shí)候就可以簡(jiǎn)化了:

          Paragraph par = new PDFParagraph("你好");

          四。如何設(shè)置PDF橫向顯示和打印?

          Rectangle rectPageSize = new Rectangle(PageSize.A4);// 定義A4頁面大小
          rectPageSize = rectPageSize.rotate();// 加上這句可以實(shí)現(xiàn)A4頁面的橫置
          Document doc = new Document(rectPageSize,50,50,50,50);//4個(gè)參數(shù),設(shè)置了頁面的4個(gè)邊距

          五。如何設(shè)置跨行和跨列?

          使用PdfPTable和PdfPCell 是沒辦法實(shí)現(xiàn)跨行的,只能跨列,要跨行使用com.lowagie.text.Table和com.lowagie.text.Cell類,Cell類有兩個(gè)方法:setRowspan()和setColspan()。

          六。如何設(shè)置單元格邊界寬度?

          Cell類的系列setBorderWidthXXXX()方法,比如setBorderWidthTop(),setBorderWidthRight()等

          七。如何設(shè)置表頭?
          希望每一頁都有表頭,可以通過設(shè)置表頭來實(shí)現(xiàn)。對(duì)于PdfPTable類來說,可以這樣設(shè)置:
          PdfPTable table = new PdfPTable(3);
          table.setHeaderRows(
          2); // 設(shè)置了頭兩行為表格頭

          而對(duì)于om.lowagie.text.Table類,需要在添加完所有表頭的單元格后加上一句代碼:
          table.endHeaders();

          八。如何設(shè)置列寬?

          Table table = new Table(8);
          float[] widths = { 0.10f0.15f0.21f0.22f0.08f0.08f0.10f,
                              
          0.06f };
          table.setWidths(widths);

          上面的代碼設(shè)置了一個(gè)有8列的表格,通過一個(gè)float數(shù)組設(shè)置列寬,這里是百分比。

          九。單元格內(nèi)段落文字居中和換行?
          居中通過Cell類來設(shè)置,一開始我以為設(shè)置段落對(duì)齊就可以了,沒想到是需要設(shè)置單元格:

          cell.setHorizontalAlignment(Element.ALIGN_CENTER);


          轉(zhuǎn)義符\n實(shí)現(xiàn)。在我的這個(gè)應(yīng)用中,因?yàn)閿?shù)據(jù)庫取出的數(shù)據(jù)是為了顯示在html上的,所以有很多<br>標(biāo)簽,可以使用正則表達(dá)式替換成"\n"
          "<br>1.測(cè)試<br>2.測(cè)試2".replaceAll("<br>|</br>","\n");

          十。如何顯示頁碼?
          復(fù)雜的頁碼顯示和水印添加,需要使用到PdfPageEventHelper、PdfTemplate等輔助類,具體的例子參見iText的文檔,如果只是為了簡(jiǎn)單的顯示頁數(shù),可以使用下面的代碼:
                      HeaderFooter footer = new HeaderFooter(new Phrase("頁碼:",getChineseFont()), true);
                      footer.setBorder(Rectangle.NO_BORDER);
                      document.setFooter(footer);
                      document.open();
          你可能注意到了,添加footer需要在document.open之前。

          評(píng)論

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2007-04-04 08:51 by 祎恬凡
          對(duì)于你開始那個(gè)結(jié)構(gòu),你又沒想過用子報(bào)表將其分割!!!
          不知道子報(bào)表是否可行!!

          # re: iText操作PDF問題總結(jié)[未登錄]  回復(fù)  更多評(píng)論   

          2007-04-04 08:56 by dennis
          @祎恬凡

          這個(gè)我早就試過,沒辦法做到的,因?yàn)榭缧械膯涡懈叨扰c子報(bào)表關(guān)聯(lián),又沒辦法動(dòng)態(tài)設(shè)置行高

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2007-04-30 10:30 by 葉之韻律
          終于找到一個(gè)稍微有點(diǎn)建設(shè)性的文章了,可惜還是沒提到我需要解決的問題:動(dòng)態(tài)換行。簡(jiǎn)單地說就是,如果某一行有個(gè)字段的數(shù)據(jù)過長(zhǎng),我想把該字段自動(dòng)換行,同時(shí)把該行的所有字段的高度撐大。我在iReport把Stretch Type的Relavive to band height選上,并且把Stretch with overflow給勾上后,預(yù)覽JrViewer時(shí)保存為PDF文件,如果有一個(gè)字段太長(zhǎng)了,就可以自動(dòng)把該字段所在行的整行換行;但如果用代碼輸出為pdf時(shí),需要換行的字段卻不顯示出來,并且整行也不換行了。請(qǐng)教一下,這個(gè)問題應(yīng)該怎么解決呢?

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2007-05-08 15:15 by dennis
          @葉之韻律
          似乎沒辦法解決,我的處理方法就是將field的length和height相應(yīng)增大,字段總有一個(gè)最大長(zhǎng)度!-_-

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2007-06-28 10:07 by Melinda
          葉之韻律:
          屬性中的position type應(yīng)該選成float

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2008-06-06 11:12 by xmzzy
          請(qǐng)問下,用iReport導(dǎo)出到word后,原來<textarea>中的大段文字的換行符會(huì)在導(dǎo)出的word里顯示成<br>,這個(gè)問題如何解決?

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2012-07-09 17:08 by 閆曉盼
          如何設(shè)置表頭內(nèi)容???

          # re: iText操作PDF問題總結(jié)  回復(fù)  更多評(píng)論   

          2012-07-09 17:13 by 閆曉盼
          明白了……對(duì)自己無解了,嘿嘿,

          # 換行  回復(fù)  更多評(píng)論   

          2013-08-09 13:56 by 張志明
          換行成兩行 的高度是一行的高度兩倍怎么換
          主站蜘蛛池模板: 嘉兴市| 刚察县| 玛曲县| 翁牛特旗| 肃南| 宜宾县| 湘西| 安图县| 伊川县| 大竹县| 平凉市| 乌苏市| 海安县| 宜阳县| 富阳市| 杭锦后旗| 花莲县| 和静县| 永州市| 东阿县| 吕梁市| 鸡泽县| 靖边县| 德兴市| 镇雄县| 五原县| 阜新| 姜堰市| 湛江市| 沽源县| 建宁县| 景洪市| 富平县| 方正县| 东安县| 吉安市| 应城市| 宣恩县| 秭归县| 岑溪市| 祁东县|