由于业务中需要导出pdf合同,而且合同中有些数据是列表的,长度不固定,迫不得已只能使用itext手写pdf
table:宽度与页面的比列:table.setWidth(95);//占页面宽度比例
位置:table.setAlignment(Element.ALIGN_LEFT);//左
网上教程:
网上有教程是通过模板pdf,准备表单域(key),然后读取模板odf和读取的动态数据一结合得到需要的pdf
但是控制动态数据填充后禁用编辑似乎不能用(如果你有方法,能否留言告知我,感激不尽!)
除此之外,如果是生成表格,比如商品列表,再通过key来一 一对号入座,那就使得上述方法不适用
我也尝试过,通过上诉方法生成多个目标pdf(p1,p2),然后再招网上的另一个方法merge合并pdf(p3),但是得到的pdf(p3)是合并了,但是动态区域是空白,查看合并前的单个pdf(p1,p2)是有值的(只是不能禁用编辑)
我的做法:
在无表单(比如商品列表那种情景)时,借鉴于模板pdf准备表单,填充key的方式生成想要的pdf,
第一步:
将目的pdf需要显示的模板字符串中动态的位置使用“占位符”来代替
第二步:
使用工具了类(将查询的数据实体转为map类型的数据(属性名-属性值)))
第三步:
替换占位符
第四步:
将替换后的模板字符串输出到pdf上
代码示例:
POI.java
public class POI {
public static void main(String[] args) throws Exception {
//准备数据map
Map<String ,Object> dataMap=new HashMap<>();
dataMap.put("customer","张三");
dataMap.put("producer","李四");
dataMap.put("signTime",new SimpleDateFormat("yyyy/MM/dd").format(new Date()));
dataMap.put("year",3);
//准备模板字符串
String infoStr="PDF示例 \n 甲方:{customer},乙方:{producer} 于 {signTime} 签订此合同,自签订日生效,有效期{year}年";
//替换key
infoStr=replaceKeyWords(dataMap,infoStr);
//输出到文档
// 创建Document对象(页面的大小为A4,左、右、上、下的页边距为10)
Document document = new Document(PageSize.A4, 10, 10, 10, 10);
OutputStream outputStream=new FileOutputStream(new File("C:\\Users\\Administrator\\Desktop\\hello.pdf"));
// 建立书写器
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
// 打开文档
document.open();
Paragraph content=new Paragraph(infoStr,setFont(20));
document.add(content);
document.close();
writer.close();
}
/**
* 设置字体编码格式
*
* @return
*/
public static Font setFont(float size) {
BaseFont baseFont = null;
try {
baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Font font = new Font(baseFont, size, Font.NORMAL, Color.black);
return font;
}
/**
* @param dataMap
* @param originStr
* @return 将originStr中的关键字替换掉
*/
public static String replaceKeyWords(Map<String, Object> dataMap, String originStr) throws Exception {
if (StringUtils.isEmpty(originStr)) {
throw new Exception("originStr can't be null");
}
Set<String> set = dataMap.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
Object data = dataMap.get(key);
if (null == data || "".equals(data)) {
data = "无";
}
originStr = originStr.replace("{" + key + "}", data.toString());
}
return originStr;
}
}
测试结果:
至于生成表格的代码,只能特定的表格写上代码生成
其他问题,欢迎在下方留言
pom依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.birt.runtime.3_7_1</groupId>
<artifactId>com.lowagie.text</artifactId>
<version>2.1.7</version>
</dependency>
总结:
本方法:
优点;
1,可以达到模板带来的按照key填充数据
2,pdf动态数据固定,不可修改
3,使用比较灵活(建立在代码书写pdf的基础上)
缺点:
1样式太难调整,不能达到模板所带来的样式可以在word中调整带来的快感
2,代码复用率不高,由于样式,格式全在后端生成
理想的思路
(暂时还未实现,只是使用了上述有缺陷的思路完成了业务需求):
1,使用模板生成样式,通过key填充数据,得到pdf1
2,表格使用后端代码生成,得到pdf2
3,pdf拼接合并(pdf1+pdf2=pdf3)