`
javajack
  • 浏览: 21861 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Itext应用封装(一)__写pdf模板

阅读更多

 忙,每天都在忙,几乎没有时间写代码,每天在各种文档中打开来打开去

,快疯了,真想找个时间能静静坐在哪儿,什么都不想,休息会。。。。。

 

      闲言少叙,下个项目要用到写pdf文件,在项目还没开始之前,终于有一周的时间再开始学习点技术了。查阅了网上的资料,感觉itext还不错,又上itext官网(http://itextpdf.com/),现在版本好像是5.0,试用了下,与之前版本好像没有太多的区别,但包名换了,版本稳定与否也不清楚,最后决定用了个以前的版本IText2.1.7(奇怪,好像从这个版本直接上升到了5)

      写pdf模板其实很简单,每个pdf模板文件中都要先定义许多文字域,有个名称(name),用itext直接写就行了,网上查了下,都是直接写pdf文件,且名字都写死到代码中了,感觉有麻烦,下面是自己写的方法,简单封装了下,不知道是否好用(还没试用),先写下来,供大家参考,来拍拍砖!

 

     首先要定义一个DataBean接口,代码如下:

/**
 * 数据bean,向单元格传递的数据将按继承此类
 * @author lilj
 *
 */
public interface DataBean {

}

 

不会吧?没有内容?

是的,没有内容,这是基础:),以后你的数据bean要继承这个bean。比如说你有一个pdf模板文件,假设要一个字段xm,代码如下:

public class DataBeanImpl implements DataBean
{
	private String  xm;

	public String getXm() {
		return xm;
	}
	public void setXm(String xm) {
		this.xm = xm;
	}
}

 

这样不可以了,也就是说这个bean要与pdf模板中的要写的数据一致。

下面就要进行pdf处理了,第一个方法是根据一个模板文件及databean生成一个pdf文件,代码如下:

 

	/**
	 * 根据一个databean,处理一个pdf文件,
	 * @param templatefile //模板文件路径
	 * @param destfile  //目标文件路径
	 * @param databean //数据接口的实现
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public void getPdfFile(String templatefile,String destfile,DataBean databean) throws IOException, DocumentException
	{

		String TemplatePDF=templatefile;

		PdfReader reader = new PdfReader(TemplatePDF);
		
		PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destfile));

		AcroFields form = stamper.getAcroFields();
		DataBean db = databean;
		List<String> fieldnames = this.getFieldName(db);
		
		for(int i=0;i<fieldnames.size();i++)
		{
			String tmpname = fieldnames.get(i);
			String value = this.getFieldValue(tmpname, db);
			form.setField(tmpname, value);
		}
		
		stamper.setFormFlattening(true);
		stamper.close();		
	}	

 这个方法中用到两个方法,一个是getfieldname,另一个是getfieldvale分别是取databean实现的名字与值,代码如下:

	/**
	 * 根据数据bean得到pdf中要写入的textfield的名字
	 * @param db
	 * @return
	 */
	private List<String> getFieldName(DataBean db)
	{
		List<String> fieldnames = new ArrayList<String>();
		
		Field[] fields = db.getClass().getDeclaredFields();
		
		for(int i=0;i<fields.length;i++)
		{
			String tmpname  = fields[i].getName();
			fieldnames.add(tmpname);
		}
		return fieldnames;
	}

 

    getfieldvalue方法如下:

 

	private String getFieldValue(String fieldname,DataBean db)
	{
		String value="";
		Method[] methods = db.getClass().getDeclaredMethods();
		
		for(int i=0;i<methods.length;i++)
		{
			String methodname = methods[i].getName();
			if (methodname.substring(0,3).toUpperCase().equals("GET") && methodname.substring(3).toUpperCase().equals(fieldname.toUpperCase()))
			{
				Method method = methods[i];
				try {
					value = (String)method.invoke(db,new Object[] {});
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return value;
	}

 好了,主要的方法就是这些了,其实很简单,就和用到了反射,这样,根据每个pdf模板,我只要去实现databean就行了,然后向bean赋值,也可以从数据库中直接取,调用getpdffile方法就可以生成pdf文件了。

 

按说程序写到这应该就行,但要是有多页呢,应该如何处理呢?于是就又写了个方法

	/**
	 * 根据一组databean,生成一个pdf
	 * 生成方法,是将多个pdf合并
	 * @param templatefile
	 * @param destfile
	 * @param databean
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public void getPdfFile(String templatefile,String destpath,String destfilename,List<DataBean> databean) throws IOException, DocumentException
	{
		String filename=destpath+"/"+destfilename;
		Document document = new Document();
		PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename)); 
		document.open();
		for (int i=0;i<databean.size();i++)
		{
			String tmppdffile = destpath+"/tmp_"+destfilename;
			this.getPdfFile(templatefile,tmppdffile,databean.get(i));
			PdfReader reader = new PdfReader(tmppdffile);   
            int n = reader.getNumberOfPages();   
            for(int j=1; j<=n; j++)   
            {   
                document.newPage();    
                PdfImportedPage page = copy.getImportedPage(reader, j);   
                copy.addPage(page);   
            }  			
		}
		
		//删除临时文件
		File file =new File(destpath+"/tmp_"+destfilename);
		if (file.exists())
			file.delete();

		document.close();
	}

调用的时候调用这个就行了,如果只有一页,就在list中只放一个databean就行了。

 

如何调用就简单了,大家应该都会,就不写了。需要的话可以留言!

 

本程序在itext2.1.7上测试通过,中文问题引用itextasian.jar即可

分享到:
评论
5 楼 flyfeifei66 2011-08-30  
牛人啊,学习了
4 楼 javajack 2011-01-13  
java_base 写道
您好,想问一下,如果我想做一个模板,模板里有两个区域,区域里可以放图片,表格,文本。想每次生成pdf文档直接调用这个模板。
这样的区域如何定义呢?
又如何获得区域的名称呢?
我用的是在一个page里创建规定区域的三个template,但调用模板时得不到每个template的名称,没办法向里面添加东西。
先谢谢了!

目前没做更深入研究,目前的实现是通过动态生成pdf实现的。
3 楼 java_base 2010-11-15  
您好,想问一下,如果我想做一个模板,模板里有两个区域,区域里可以放图片,表格,文本。想每次生成pdf文档直接调用这个模板。
这样的区域如何定义呢?
又如何获得区域的名称呢?
我用的是在一个page里创建规定区域的三个template,但调用模板时得不到每个template的名称,没办法向里面添加东西。
先谢谢了!
2 楼 javajack 2010-10-29  
wgcniler 写道
你好,我根据你的方法根据模板来新创pdf文件,但是为什么那些域写不进内容呢?我的代码如下:
String TemplatePDF="d:/test/test_CA_d3.pdf"; 
PdfReader reader = new PdfReader(TemplatePDF); 
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("d:/test/test_222.pdf")); 
AcroFields form = stamper.getAcroFields();
form.setField("pName", "CHUSHAN");
form.setField("cDClass", "M");
form.setField("cBflight", "CA1860");
form.setField("rTfrom", "LIUZHOU");
stamper.setFormFlattening(true);
stamper.close();


一般情况下,写不进去数据,有两个原因
1、数据bean没有数据
2、pdf模板中的字段名应该与数据bean中的名一致,记住是区分大小写的
1 楼 wgcniler 2010-09-25  
你好,我根据你的方法根据模板来新创pdf文件,但是为什么那些域写不进内容呢?我的代码如下:
String TemplatePDF="d:/test/test_CA_d3.pdf"; 
PdfReader reader = new PdfReader(TemplatePDF); 
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("d:/test/test_222.pdf")); 
AcroFields form = stamper.getAcroFields();
form.setField("pName", "CHUSHAN");
form.setField("cDClass", "M");
form.setField("cBflight", "CA1860");
form.setField("rTfrom", "LIUZHOU");
stamper.setFormFlattening(true);
stamper.close();

相关推荐

Global site tag (gtag.js) - Google Analytics