Java生成PDF文档 iText使用PDF模板一
最近在弄这个java生成pdf,哎,在网上查找了各种各样的学习资料,弄了几天,今天终于把这个效果简单的弄出来,所以,也把这个,我所走过的坑,作一个记录,提供接下来需要学习的人。
参考文献文档:https://blog.csdn.net/u012377333/article/details/51264122#
https://my.oschina.net/lujianing/blog/894365
iText
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。
iText 官网:http://itextpdf.com/
iText 开发文档: http://developers.itextpdf.com/developers-home
iText目前有两套版本iText5和iText7。iText5应该是网上用的比较多的一个版本。iText5因为是很多开发者参与贡献代码,因此在一些规范和设计上存在不合理的地方。iText7是后来官方针对iText5的重构,两个版本差别还是挺大的。不过在实际使用中,一般用到的都比较简单,所以不用特别拘泥于使用哪个版本。比如我们在http://mvnrepository.com/中搜索iText,出来的都是iText5的依赖。
整个项目结构如下:
第一步:下载AdobeAcrobat DC,必须使用这个来制作from域。
第二步:使用AdobeAcrobat DC将Word导成PDF文档。
第三步:添加“文本域”到我们想要添加内容的位置:
效果如下,博主这里的模板如下:
第四步:保存PDF文档;
接下来就是代码部分:
首先创建一个maven项目,这里博主就不多介绍了,如果这个不会,那就没有办法了。
一:引入iText所需要的依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
<!--pdf itext 的jar依赖 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
对应的jar包
二:开户账票所对应的实体类如下:
package com.demo;
//账票实体
public class Ticket {
private String ticketId;// 流水号
private String homesId;
private String ticketCreateTime;// 创建时间
private String ticketCompany;// 账票单位
private String sysName;// 系统名称
private String moneyLittle;// 小写金额
private String moneyBig;// 大写金额
private String accountCompany;// 公司名称
private String bedNumber;// 编号
private String username;// 用户名
private String password;// 密码
// 无参构造
public Ticket() {
super();
}
// 有参构造
public Ticket(String ticketId, String homesId, String ticketCreateTime, String ticketCompany, String sysName,
String moneyLittle, String moneyBig, String accountCompany, String bedNumber, String username,
String password) {
this.ticketId = ticketId;
this.homesId = homesId;
this.ticketCreateTime = ticketCreateTime;
this.ticketCompany = ticketCompany;
this.sysName = sysName;
this.moneyLittle = moneyLittle;
this.moneyBig = moneyBig;
this.accountCompany = accountCompany;
this.bedNumber = bedNumber;
this.username = username;
this.password = password;
}
public String getTicketId() {
return ticketId;
}
public void setTicketId(String ticketId) {
this.ticketId = ticketId;
}
public String getHomesId() {
return homesId;
}
public void setHomesId(String homesId) {
this.homesId = homesId;
}
public String getTicketCreateTime() {
return ticketCreateTime;
}
public void setTicketCreateTime(String ticketCreateTime) {
this.ticketCreateTime = ticketCreateTime;
}
public String getTicketCompany() {
return ticketCompany;
}
public void setTicketCompany(String ticketCompany) {
this.ticketCompany = ticketCompany;
}
public String getSysName() {
return sysName;
}
public void setSysName(String sysName) {
this.sysName = sysName;
}
public String getMoneyLittle() {
return moneyLittle;
}
public void setMoneyLittle(String moneyLittle) {
this.moneyLittle = moneyLittle;
}
public String getMoneyBig() {
return moneyBig;
}
public void setMoneyBig(String moneyBig) {
this.moneyBig = moneyBig;
}
public String getAccountCompany() {
return accountCompany;
}
public void setAccountCompany(String accountCompany) {
this.accountCompany = accountCompany;
}
public String getBedNumber() {
return bedNumber;
}
public void setBedNumber(String bedNumber) {
this.bedNumber = bedNumber;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
三:账票模板:这与参考的文献不一样,但实现的目的都一样。博主这里采用的是这种方法
3.1:因:iText 不支持中文,所以需要引入中文字体,引入下载字体:https://www.fontke.com/这里介绍一个字体网。
package com.demo;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
//账票模板
public class PDFTempletTicket {
private String templatePdfPath;//模板路径
private String ttcPath;//生成的新路径
private String targetPdfpath;//源路径
private Ticket ticket;//账票实体
private static final String FONT = "中黑体.ttf";//引入的字体
//get与set
public String getTemplatePdfPath() {
return templatePdfPath;
}
public void setTemplatePdfPath(String templatePdfPath) {
this.templatePdfPath = templatePdfPath;
}
public String getTtcPath() {
return ttcPath;
}
public void setTtcPath(String ttcPath) {
this.ttcPath = ttcPath;
}
public String getTargetPdfpath() {
return targetPdfpath;
}
public void setTargetPdfpath(String targetPdfpath) {
this.targetPdfpath = targetPdfpath;
}
public Ticket getTicket() {
return ticket;
}
public void setTicket(Ticket ticket) {
this.ticket = ticket;
}
//无参构造
public PDFTempletTicket() {
super();
}
//有参构造
public PDFTempletTicket(String templatePdfPath, String ttcPath, String targetPdfpath, Ticket ticket) {
this.templatePdfPath = templatePdfPath;
this.ttcPath = ttcPath;
this.targetPdfpath = targetPdfpath;
this.ticket = ticket;
}
// 使用中文字体
Font f1 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//获取
public void templetTicket(File file) throws Exception {
//创建一个pdf读取对象
PdfReader reader = new PdfReader(templatePdfPath);
//创建一个输出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//创建pdf模板,参数reader bos
PdfStamper ps = new PdfStamper(reader, bos);
//封装数据
AcroFields s = ps.getAcroFields();
s.setField("ticketId", ticket.getTicketId());
s.setField("ticketCreateTime", ticket.getTicketCreateTime());
s.setField("ticketCompany", ticket.getTicketCompany());
s.setField("sysName", ticket.getSysName());
s.setField("moneyLittle", ticket.getMoneyLittle());
s.setField("moneyBig", ticket.getMoneyBig());
s.setField("accountCompany", ticket.getAccountCompany());
s.setField("bedNumber", ticket.getBedNumber());
s.setField("username", ticket.getUsername());
s.setField("password", ticket.getPassword());
ps.setFormFlattening(true);//这里true表示pdf可编辑
ps.close();//关闭PdfStamper
FileOutputStream fos = new FileOutputStream(file);//创建文件输出流
fos.write(bos.toByteArray());//写入数据
fos.close();//关闭输出流
}
}
四:测试类-TestTempletTicket
package com.demo;
import java.io.File;
public class TestTempletTicket {
public static void main(String[] args) throws Exception {
//账票对象
Ticket ticket = new Ticket();
ticket.setTicketId("201812212710000");
ticket.setTicketCreateTime("2018年12月21日");
ticket.setTicketCompany("中国人民银行");
ticket.setSysName("智能看护系统");
ticket.setMoneyLittle("50,000.00");
ticket.setMoneyBig("伍万元整");
ticket.setAccountCompany("中国政府");
ticket.setBedNumber("500床位");
ticket.setUsername("qiu");
ticket.setPassword("123456");
//模板对象
PDFTempletTicket Ticketpdf = new PDFTempletTicket();
//模板源路径
Ticketpdf.setTemplatePdfPath("D:\\pdfDemo\\开户账票.pdf");
//设置tarGet的路径,这个是项目中的源路径
//Ticketpdf.setTargetPdfpath("D:\\a.pdf");
//set封装账票信息
Ticketpdf.setTicket(ticket);
//指定生成的新路径
File file = new File("D:\\pdfDemo\\demo.pdf");
//创建文件
file.createNewFile();
//使生成的文件file生效,这个必须有
Ticketpdf.templetTicket(file);
}
}
运行结果如下:
效果有点丑:这里也不做调试了,这里主要是功能做出来,其他的效果可以自己慢慢调 了。相信介绍的这样清楚,不是这行的的人估计也能看懂了吧。加油!!!!!!以后遇到类似的,相信大家至少有个映像,如果还是不会做,没关系,参考这篇,相信你一定做好的,加油!谁也不是天生就是天才,都是不断的去学习!这个效果其实已经是相对简单的,真正在实际项目中,业务逻辑可能要复杂些。加油!!!
如果参照别人的,会出现以下问题:
备注:导出PDF文档,From域的内容不可见问题;iText找不到字体;
问题1:我开始导出的From域内容看不到,将ps.setFormFlattening(true);设置为flase后,可以看到From域,还是看不到内容,我点击进入From后可以看到内容,该方法是将From域隐藏;后来看到有人设置From域内容的字体:BaseFontbf = BaseFont.createFont(PDFTicket.class.getResource(“/“) + “org/csun/ns/util/simsun.ttc,1”,
BaseFont.IDENTITY\_H, BaseFont.EMBEDDED);
以及:
s.setSubstitutionFonts(fontList);
问题2:别人的代码:
BaseFont bf = BaseFont.createFont(“STSong-Light”, “UniGB-UCS2-H”, BaseFont.NOT_EMBEDDED);
会报找不到字体的错误,这里的解决方式就是通过使用自己的字体就好,simsun.ttc是Windows下面自带的字体(简体宋体:C:\Windows\Fonts下面有很多字体可以使用)
以上两个问题,可以参照博主的这种做法就可化解,如果你有更好的方法,不妨可以留言也介绍给博主
还没有评论,来说两句吧...