本站不再更新,歡迎光臨 java開發(fā)技術(shù)網(wǎng)
          隨筆-230  評(píng)論-230  文章-8  trackbacks-0
          因?yàn)榍靶┤兆釉谝粋€(gè)項(xiàng)目中用到了iText,稍有收獲,便總結(jié)于此,以供他人所需。

          iText是一個(gè)比較底層的pdf庫(kù),很多項(xiàng)目的pdf操作都是以它為基礎(chǔ)的。像spring,以及另一個(gè)比較有名的報(bào)表工具jasperreports。簡(jiǎn)單的pdf報(bào)表輸出用它比較合適,比較復(fù)雜的話使用起來(lái)就比較困難了,你要手工編寫太多的代碼。

          比較好的是iText網(wǎng)站上提供相當(dāng)多的示例代碼,比較容易入門。我這里只說(shuō)一些在它的文檔里并沒(méi)有直接講到的東西。

          1 關(guān)于Document

          Document的幾種構(gòu)造函數(shù):
          public Document();
          public Document(Rectangle pageSize);
          public Document(Rectangle pageSize,
          int marginLeft,
          int marginRight,
          int marginTop,
          int marginBottom);
          下面兩種比較有用,如果是你想定義紙張大小和邊緣的時(shí)候。對(duì)于Margin,iText上提到“You can also change the margins while you are adding content. Note that the changes will only be noticed on the NEXT page. If you want the margins mirrored (odd and even pages), you can do this with this method: setMarginMirroring(true). ”不過(guò),對(duì)于table似乎并不好使。table并不會(huì)了理會(huì)你設(shè)定的margin,如果想改變它的magin還是需要去改變它的寬度(setWidth)。

          2 pdf表單

          使用PdfStamper是可以填充pdf表單的,這樣就給出了一種很好的報(bào)表生成思路。
          word制作報(bào)表樣式-->acrobat轉(zhuǎn)pdf-->itext填充數(shù)據(jù)-->輸出pdf
          這做非常簡(jiǎn)單,因?yàn)榭梢员容^容易的控制pdf的樣式。我對(duì)于Java的報(bào)表工具了解的并不多,不過(guò)在jasperreports,即使用GUI工具做一個(gè)樣式比較復(fù)雜的報(bào)表也不是怎么容易。比如有那種斜線的表頭,比較花哨的嵌套表格。這樣的情況還是比較多見的,客戶不會(huì)關(guān)系你實(shí)現(xiàn)起來(lái)是否困難。不過(guò)想要使用這種方式也有不足的地方。首先是acrobat把word轉(zhuǎn)化成pdf的時(shí)候,格式總是保持不好,特別的是字體。然后是文件的體積這樣生成的pdf會(huì)比直接用iText生成的pdf文件大很多,acrobat在pdf里加入了太多無(wú)用的信息。初次使用iText填充Adobe Designer生成的pdf表單時(shí)會(huì)有點(diǎn)小麻煩。在Designer中設(shè)計(jì)了一個(gè)name的text文本框的綁定名為name。照著iText中例子使用使用PdfStamper的setField方法去這樣寫form.setField("name", "XXXX");并不會(huì)成功。原因是Adobe Designer生成的表單名都是具有層次的,它可能是這個(gè)樣子form1[0].#subform[0].name[0]。不過(guò)我們可以用一個(gè)方法把它們列出來(lái),只要做一次就知道結(jié)構(gòu)了,可以使用類似下面的代碼:
          PdfReader reader = new PdfReader("form.pdf");
          PdfStamper stamp = new PdfStamper(reader, new FileOutputStream("registered_flat.pdf"));
          AcroFields form = stamp.getAcroFields();
          for (Iterator it = form.getFields().keySet().iterator(); it
          .hasNext();) {
          System.out.println(it.next());
          }
          如果直接用iText編程生成的表單就不會(huì)有這樣的問(wèn)題,設(shè)定的什么名字就是什么名字。

          3 表單元素

          pdf并不像html那樣具有良好清晰的結(jié)構(gòu),而是一個(gè)有層次的文檔類型。在它的maillist里,作者說(shuō)明了iText雖然可以操作現(xiàn)存的pdf文件但是沒(méi)辦法去還原它的結(jié)構(gòu)的。沒(méi)辦法像html一樣,能從一個(gè)pdf文件獲得一個(gè)清晰的“源文件”的。關(guān)于層次,可以從iText上得到詳細(xì)的講述,獲取去看看pdf規(guī)范。表單和普通文本是不在一個(gè)層上的。沒(méi)辦法適用對(duì)待文本表各一樣把它們簡(jiǎn)單的add進(jìn)Document對(duì)象。獲取一個(gè)cb直接去用絕對(duì)定位的方法可以加入表單元素,不過(guò)很多的時(shí)候因?yàn)榕虐娌⒉荒苣敲春?jiǎn)單的去做。就是在html中布局一樣可以使用表格定位。想把一個(gè)表單元素加入cell,要借助cell的setCellEvent方法。以一個(gè)checkbox為例。新建一個(gè)類CheckBoxForm,實(shí)現(xiàn)PdfPCellEvent接口。需要實(shí)現(xiàn)一個(gè)cellLayout的方法。
          ? public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
          position可以好好利用,它包含當(dāng)前cell的位置信息,你可以用它來(lái)確定自己checkbox的位置。
          position.top()-position.bottom()就能得到高position.right()-position.left()可以得到長(zhǎng),如果需要這兩個(gè)值得花可以如此計(jì)算。下面的代碼就是定義一個(gè)寬度為a的checkbox的rectangle 。它在cell中水平居中,垂直也居中。
          ? ? float bo = (position.top()-position.bottom()-a)/2;
          ? ? float ao = (position.right()-position.left()-a)/2; ? ?
          ? ? Rectangle rectangle = new Rectangle(position.left() + ao, position
          ? ? ? ? ? .bottom() + bo, position.left() +ao+ a, position.bottom()+ bo + a);
          然后把它加入Document
          ? ? RadioCheckField tf = new RadioCheckField(writer, rectangle, fieldname,
          ? ? ? ? ? "f");
          ? ? tf.setCheckType(RadioCheckField.TYPE_SQUARE);
          ? ? tf.setBorderWidth(1);
          ? ? tf.setBorderColor(Color.black);
          ? ? tf.setBackgroundColor(Color.white); ? ? ?
          ? ? try {
          ? ? ? ? PdfFormField field = tf.getCheckField(); ? ? ? ?
          ? ? ? ? writer.addAnnotation(field);
          ? ? } catch (IOException e) {
          ? ? ? ? e.printStackTrace();
          ? ? } catch (DocumentException e) {
          ? ? ? ? e.printStackTrace();
          ? ? }
          其它的元素與此類似。

          4 PdfPTable和Table

          說(shuō)不上哪種更好用,有時(shí)候不能不使用PdfPTable。可惜它只有setColspan方法,沒(méi)有setRowspan。嵌套的時(shí)候也有區(qū)別,PdfPTable是用addcell()加入嵌套表的,table則有一個(gè)更明了的方法insertTable()。PdfPTable想進(jìn)行設(shè)置border之類的操作要先獲得一個(gè)默認(rèn)cell,
          pdfPTableName.getDefaultCell().setBorder(Rectangle.NO_BORDER);//設(shè)置無(wú)框的表
          另外在PdfPTable中,一些修飾屬性會(huì)因?yàn)樵O(shè)置的時(shí)機(jī)不正確而沒(méi)有效果。如,適用cell的構(gòu)造函數(shù)加入了文本,在cell的setVerticalAlignment()fangfa去設(shè)定垂直對(duì)齊方式就不會(huì)有效。還有一個(gè)有意思的不同是table默認(rèn)外邊框是加粗的,而PdfPTable則一樣粗細(xì)。

          5 字體

          iText的例子有很多足夠用,給出一些pdf的字體名稱和編碼,如果想使用內(nèi)嵌字體的話。
          語(yǔ)言 PDF 字體名
          簡(jiǎn)體中文 STSong-Light
          繁體中文 MHei-Medium
          MSung-Light
          日語(yǔ) HeiseiKakuGo-W5
          HeiseiMin-W3
          韓語(yǔ) HYGoThic-Medium
          HYSMyeongJo-Medium

          字符集 編碼
          簡(jiǎn)體中文 UniGB-UCS2-H
          UniGB-UCS2-V
          繁體中文 UniCNS-UCS2-H
          UniCNS-UCS2-V
          日語(yǔ) UniJIS-UCS2-H
          UniJIS-UCS2-V
          UniJIS-UCS2-HW-H
          UniJIS-UCS2-HW-V
          韓語(yǔ) UniKS-UCS2-H
          UniKS-UCS2-H
          必須要有Asian的包才可以用,也可以使用TrueType字體。

          posted on 2007-02-28 16:02 有貓相伴的日子 閱讀(5686) 評(píng)論(0)  編輯  收藏 所屬分類: jdk
          本站不再更新,歡迎光臨 java開發(fā)技術(shù)網(wǎng)
          主站蜘蛛池模板: 贡嘎县| 赫章县| 多伦县| 杭锦后旗| 普兰县| 安化县| 鹿泉市| 凤山县| 鸡西市| 蒙城县| 盘山县| 扎赉特旗| 阜平县| 濉溪县| 新建县| 廊坊市| 库尔勒市| 历史| 德令哈市| 长乐市| 富蕴县| 呼和浩特市| 老河口市| 宝兴县| 乐平市| 定结县| 吉林市| 涪陵区| 平遥县| 六枝特区| 凤凰县| 闽侯县| 鄂州市| 图木舒克市| 德钦县| 南投市| 武清区| 闵行区| 长乐市| 大埔县| 含山县|