用pdf模板生成pdf文档很简单,首先需要手动做个pdf模板,上面有很多的类似html里的text域的东西,
给他们起好名字,在程序里填充就可以了。虽然由于不会做模板(实际上由于短时间无法去熟悉使用Adobe Acrobat )
而没有用到此篇文章(转载的别人的)(只好手动生成),但是感觉写的还是不错的。贴出来,以便将来用到了查看。
首先要定义一个DataBean接口,代码如下:
public interface DataBean {
}
它是空的,表示是一个存储数据的接口,你也可以不要它,但是面向接口编程是个好的习惯。
将来就用它里面的数据来填充pdf表单。
比如说你有一个pdf模板文件,假设要一个字段xm,代码如下:
public class DataBeanImpl implements DataBean
{
private String xm;
public String getXm() {
return xm;
}
public void setXm(String xm) {
this.xm = xm;
}
}
下面就要进行pdf处理了,第一个方法是根据一个模板文件和databean生成一个pdf文件,代码如下:
/**
* 根据一个databean,处理一个pdf文件,
* @param templatefile //模板文件路径
* @param destfile //目标文件路径
* @param databean //数据接口的实现
*/
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
*/
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;
}
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) {
e.printStackTrace();
}
}
}
return value;
}
可以看出这几段代码的功能还是比较清晰的,他根据数据模型的属性判断需要往pdf表单中填入哪些内容,这首先当然要求你在
做模板和设计DB类时属性域保持一致。然后遍历这些属性,在遍历时通过遍历get方法和get方法后面的字符串找到属性具体的值。
这样就可以以值对的形式将DB的内容输出到pdf表单中。
form.setField(tmpname, value);
上面的代码可以封装在一个类中,可以把他看成是一个“打印公共类”,而对于不同的表单你还可能需要写一个单独的操作类
来准备数据,你很有可能会查询数据库,然后调用DB的set方法。
按说程序写到这应该就行了,但要是有多页呢,应该如何处理呢?于是就又写了个方法:
/**
* 根据一组databean,生成一个pdf,生成方法,是将多个pdf合并
* @param templatefile
* @param destfile
* @param databean
*/
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();
}
个人觉得这个方法可能会有些问题,所有的DB都是用相同的模板个目标路径。而每个处理DB的循环,
都用从头复制?总之是极为混乱的一个方法,
我们的疑问是:一个pdf模板不可以有多页吗?只要一个DB里的内容能跟表单里的所有内容一致应该就可以了。
等用到了将来再说吧。