忙,每天都在忙,几乎没有时间写代码,每天在各种文档中打开来打开去
,快疯了,真想找个时间能静静坐在哪儿,什么都不想,休息会。。。。。
闲言少叙,下个项目要用到写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即可