iText操作PDF问题总结

简介:
这个星期我的任务就是处理一些报表的打印问题,因为我算项目组里对jasperreport比较熟悉的了,这个东东也是我引进到这个项目。ireport画报表,使用struts的action输出PDF到浏览器,这是我们目前的解决方案。今天遇到一个ireport解决不了的要求——合并单元格。类似下面这样的表结构:
----------------------------------------------
          |          |__c_____________
   dept   | value    |__b_____________
          |          |  a
--------------------------------------------------------
也就是需要跨行,跨列!-_-。在html表格中解决这个很简单,只要设置单元格的colspan和rowspan即可。我在ireport没有找到解决方案,如果您知道,请不吝赐教。查找资料弄了两个小时没进展,决定自己用iText写吧,通过google、baidu资料顺利达到了我的要求,仅在此记录下遇到的问题和解决方法。

一。一个HelloWorld实例:
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();
}
}
可以看到一个PDF文件的输出,总共只需要5个步骤
a.创建一个Document实例
Document document = new Document();
b.将Document实例和文件输出流用PdfWriter类绑定在一起
PdfWriter.getInstance(document,new FileOutputStream("HelloWorld.pdf"));
c.打开文档
document.open();
d.在文档中添加文字
document.add(new Paragraph("Hello World"));
e.关闭文档
document.close();
这样5个步骤,就可以生成一个PDF文档了。

二。如何使用jsp、servlet输出iText生成的pdf?
  如果每次都在服务端生成一个PDF文件给用户,不仅麻烦,而且浪费服务器资源,最好的方法就是以二进制流的形式输送到客户端。
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);
for int  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也是需要这个包的。然后定义中文字体:
     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;
    }

我将产生中文字体封装在方法内,自定义一个段落PDFParagraph继承自Paragraph,默认使用中文字体:
class  PDFParagraph  extends  Paragraph {
        
public  PDFParagraph(String content) {
            
super (content, getChineseFont());
        }
    }

使用的时候就可以简化了:

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

四。如何设置PDF横向显示和打印?

Rectangle rectPageSize  =   new  Rectangle(PageSize.A4); //  定义A4页面大小
rectPageSize  =  rectPageSize.rotate(); //  加上这句可以实现A4页面的横置
Document doc  =   new  Document(rectPageSize, 50 , 50 , 50 , 50 ); // 4个参数,设置了页面的4个边距

五。如何设置跨行和跨列?

使用PdfPTable和PdfPCell 是没办法实现跨行的,只能跨列,要跨行使用com.lowagie.text.Table和com.lowagie.text.Cell类,Cell类有两个方法:setRowspan()和setColspan()。

六。如何设置单元格边界宽度?

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

七。如何设置表头?
希望每一页都有表头,可以通过设置表头来实现。对于PdfPTable类来说,可以这样设置:
PdfPTable table  =   new  PdfPTable( 3 );
table.setHeaderRows(
2 );  //  设置了头两行为表格头

而对于om.lowagie.text.Table类,需要在添加完所有表头的单元格后加上一句代码:
table.endHeaders();

八。如何设置列宽?

Table table  =   new  Table( 8 );
float [] widths  =  {  0.10f 0.15f 0.21f 0.22f 0.08f 0.08f 0.10f ,
                    
0.06f  };
table.setWidths(widths);

上面的代码设置了一个有8列的表格,通过一个float数组设置列宽,这里是百分比。

九。单元格内段落文字居中和换行?
居中通过Cell类来设置,一开始我以为设置段落对齐就可以了,没想到是需要设置单元格:

cell.setHorizontalAlignment(Element.ALIGN_CENTER);


转义符\n实现。在我的这个应用中,因为数据库取出的数据是为了显示在html上的,所以有很多<br>标签,可以使用正则表达式替换成"\n"
" <br>1.测试<br>2.测试2 " .replaceAll( " <br>|</br> " , " \n " );

十。如何显示页码?
复杂的页码显示和水印添加,需要使用到 PdfPageEventHelper、 PdfTemplate等辅助类,具体的例子参见iText的文档,如果只是为了简单的显示页数,可以使用下面的代码:
            HeaderFooter footer  =   new  HeaderFooter( new  Phrase( " 页码: " ,getChineseFont()),  true );
            footer.setBorder(Rectangle.NO_BORDER);
            document.setFooter(footer);
            document.open();
你可能注意到了,添加footer需要在document.open之前。
目录
相关文章
|
6月前
|
Java API Apache
使用 Apache PDFBox 操作PDF文件
Apache PDFBox库是一个开源的Java工具,专门用于处理PDF文档。它允许用户创建全新的PDF文件,编辑现有的PDF文档,以及从PDF文件中提取内容。此外,Apache PDFBox还提供了一些命令行实用工具。
449 6
|
6月前
|
Java
java Itext创建pdf
java Itext创建pdf
65 0
|
3月前
|
XML 编解码 前端开发
wkhtmltopdf 代替 itext 将 url 转成 pdf
wkhtmltopdf 代替 itext 将 url 转成 pdf
45 0
|
5月前
|
编解码 文字识别
印刷文字识别操作报错合集之在尝试将PDF文件转换为图片时出现了问题,具体的错误代码是415,该怎么处理
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
5月前
|
XML Java 数据处理
视觉智能开放平台操作报错合集之pdf识别报503,是什么导致的
在使用视觉智能开放平台时,可能会遇到各种错误和问题。虽然具体的错误代码和消息会因平台而异,但以下是一些常见错误类型及其可能的原因和解决策略的概述,包括但不限于:1. 认证错误、2. 请求参数错误、3. 资源超限、4. 图像质量问题、5. 服务不可用、6. 模型不支持的场景、7. 网络连接问题,这有助于快速定位和解决问题。
|
6月前
|
数据采集 数据安全/隐私保护 Python
2024年最新【Python】如何用Python来操作PDF文件,收藏(2),2024年最新阿里p7Python面试题
2024年最新【Python】如何用Python来操作PDF文件,收藏(2),2024年最新阿里p7Python面试题
2024年最新【Python】如何用Python来操作PDF文件,收藏(2),2024年最新阿里p7Python面试题
|
6月前
|
Java
itext制作pdf表格
java中使用itext制作pdf表格
|
6月前
使用Itext导出PDF
使用Itext导出PDF
60 0
|
人工智能 API 数据安全/隐私保护
Python3,5行代码,Chatxxx能对PDF文件进行旋转、提取、合并等一系列操作,看了这篇,80岁老奶奶走路都不扶墙了。
Python3,5行代码,Chatxxx能对PDF文件进行旋转、提取、合并等一系列操作,看了这篇,80岁老奶奶走路都不扶墙了。
101 0
|
Java BI
iText导出PDF多表格
iText导出PDF多表格
220 0

热门文章

最新文章