项目需求:获取列表数据之后直接将数据生成一个pdf。因此需要使用到 itext 对pdf进行直接操作。
环境配置
需要为pdf添加文字域,因此需要安装Adobe Acrobat
准备一个空的PDF文件,如果有现成的模板更好
依赖配置,我们使用itext的7版本
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.3</version>
<type>pom</type>
</dependency>
快速使用
使用Adobe Acrobat Pro DC打开空PDF,使用 文字域 工具为PDF添加文字域,要注意为每个文字域命名。
如果你有现成的模板PDF,直接使用识别域可以识别空白区域然后自动生成文字域,但是一般都不太准确
如果你的单个数据很多的话,可以在属性中设置多行
设置完文字域之后记得保存。
代码实现
@SpringBootTest
class StickerApplicationTests {
private static final String TEMP_PATH = "C:\\Users\\An1ong\\Desktop\\Stickers.pdf";
//生成PDF的位置
private static final String DEST_PATH = "C:\\Users\\An1ong\\Desktop\\StickersOut.pdf";
//本地上字体的路径
private static final String FONT_PATH = "";
@Autowired
private StickerService stickerService;
@Test
void contextLoads() throws IOException {
//创建一个新的PDF文件,并写入数据
PdfReader reader = new PdfReader(TEMP_PATH);
// 创建一个 PdfWriter 对象以写入新的PDF
PdfWriter writer = new PdfWriter(DEST_PATH);
// 创建一个 PdfDocument 对象
PdfDocument pdfDoc = new PdfDocument(reader, writer);
// 获取 PDF 表单
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);
//获得数据,准备填充
List<Sticker> stickerList = stickerService.list(10);
//文本填充
for(int i = 0; i < stickerList.size();i++){
Sticker sticker = stickerList.get(i);
// 生成自定义序号,格式为 "001"、"002"、"003"
String customId = String.format("%03d", i + 1);
String idFieldName = "id" + (i + 1);
String nameFieldName = "name" + (i + 1);
PdfFormField idField = form.getField(idFieldName);
if (idField != null) {
idField.setValue(customId);
}
PdfFormField nameField = form.getField(nameFieldName);
if (nameField != null) {
nameField.setValue(sticker.getStickerName());
}
}
//消除掉表单域
form.flattenFields();
//关闭流
pdfDoc.close();
}
}
行数也不算少,但里面的逻辑其实也很简单。这是一个Springboot的单元测试,我调用service中方法获取了一个装着对象的列表。
用PdfReader读取你要套写的模板,用PdfWriter将数据写入模板。创建出一个PdfDocument对象并将这两个参数传入就可以开始对PDF操作了。
注意,这个过程不会直接在原PDF上操作,而是生成一个新的PDF进行操作,程序结束后原PDF模版还是空白的。
PdfAcroFrom获取PDF表单,然后PdfFormField获取其中的文字域,最后使用for循环动态的将数据套打在模板上就完成了。
最终会生成一个新的文件
最终效果:
之所以要在最后调用form.flattenFields消除掉表单域是因为如果不消除表单域的话就会变成这样。
封装
我们可以把这个在单元测试中的程序封装成工具类重复使用
public class PdfPrintUtil {
// private static final String TEMP_PATH = "C:\\Users\\An1ong\\Desktop\\Stickers.pdf";
//
// private static final String DEST_PATH = "C:\\Users\\An1ong\\Desktop\\StickersOut.pdf";
public static void printPDF(String TEMP_PATH,String DEST_PATH,List<Sticker> stickerList) throws IOException {
//创建一个新的PDF文件,并写入数据
PdfReader reader = new PdfReader(TEMP_PATH);
// 创建一个 PdfWriter 对象以写入新的PDF
PdfWriter writer = new PdfWriter(DEST_PATH);
// 创建一个 PdfDocument 对象
PdfDocument pdfDoc = new PdfDocument(reader, writer);
// 获取 PDF 表单
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);
//文本填充
for(int i = 0; i < stickerList.size();i++){
Sticker sticker = stickerList.get(i);
// 生成自定义序号,格式为 "001"、"002"、"003"
String customId = String.format("%03d", i + 1);
String idFieldName = "id" + (i + 1);
String nameFieldName = "name" + (i + 1);
PdfFormField idField = form.getField(idFieldName);
if (idField != null) {
idField.setValue(customId);
}
PdfFormField nameField = form.getField(nameFieldName);
if (nameField != null) {
nameField.setValue(sticker.getStickerName());
}
}
//消除掉表单域
form.flattenFields();
//关闭流
pdfDoc.close();
}
}