故事背景
各位码农们好!我是在社会接受练习时长2年半的java练习生,大家也可以叫我小卡拉米 吴!最近在项目中遇到一个需求,就是有关于pdf文件生成的,具体需求如下。
到了小卡拉米 吴讲故事的时间了:
事情是这样的。
小吴是一名普通的码农,和野原广志一样,但不是小组长,生活除了工作就是回家。
突然,在某一天的加班的晚上,小王加班很晚,结束了一天的工作,身体甚是乏困呀!在边走的路上,嘴里还在对自己的领导:什么傻*领导,加nm破班!买nm的命!若是老子富德流油,绝对踩你桌子,睡觉掀你被子!后来用jio踢飞一个小石子,结果踢中了一个阿拉丁神灯,结果冒出来一个河神。
河神突然问道:骂骂赖赖的年轻人啊~,你踢的是这个金石头还是这个银石头呢,。
小吴回道:你跟我玩呢,这三个都是普通石头,金石头和银石头,刷漆还没干,赶紧的赔我100W,损塞。
河神,指了指路灯下草丛旁的方向,在那边有100W。小吴顺势的走向那个方向,打开草丛,果真有100w,于是把钱塞在装电脑的背包,把吃饭的家伙 (某想thinkPad 老win10)丢掉,飞奔往家里跑。
为了不让人怀疑,小吴在这接下来的几个月以10w的额度存入银行,对于银行来说,是一笔大额存单,于是以VIP待遇服务小吴,服务办理流畅,小吴给了五星好评。在这一年里,小吴吃着利润在家养着,后来去银行PC端打了电子凭证,结果批量打凭证的时候,打了10张,小吴嫌繁琐,就问客服能不能把这些凭证尽量放在一个A4里去呢。结果银行说,只能打一张呀。
需求分析
小吴去银行查询凭证,想要将这一年的凭证批量打印下来,想把这些凭证数据尽量放在一页纸上。
功能实现分析
需要实现这样的需求,有以下这几种思考:
准备:基础生成单页的pdf代码已经实现
实际思考:将尽量数据塞在一页的a4纸域,那么用document.newPage()方法生成新的pdf页面,然后循环继续塞入,对于一页塞多少个,需要在循环进行处理。
功能实现方式:
1.通过画模版,用代码填充
你可以通过制作pdf模版的方式进行处理,然后根据pdf文本域通过代码进行填充,缺点就是需要画模版,生产模版后的数据过长可能会导致数据展示一半的情况。
2.通过代码生成
total:总数据条数
pageSizeNum:A4页面设定的条数(一个A4塞多少条)
代码生成需要考虑怎样塞入一个A4域,并且如何处理,最后一页小于设定pageSizeNum。
最后一页数据条数,我们可以用取余的方式total%pageSizeNum进行判断。
1)希尔排序
你可以使用排序算法处理一页塞入多少个数据,用到希尔排序,根据页面条数进行希尔排序放入,这样就不需要考虑最后一页。
2)计数器
在循环插入数据是,用一个计数器的方式进行实现,也不用考虑最后一页,计数器计数count==pageSizeNum时,生产新的document.newPage()页面,并将恢复默认为0.
3)先分页,再处理最后一页 (这样有点复杂,需要最后一页的数据条数,可以写递归方法进行实现)
代码实现
这里用代码生成pdf,采用计数器方式比较便捷,其他方式各位可以自己实现,这边提供思路。
依赖:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-pdfa</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>layout</artifactId>
<version>7.2.3</version>
</dependency>
代码实现:
package com.wujz.test.util;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class OtherModel {
public static void main(String[] args) {
Map<String, Object> taxPayList = new HashMap<>();
taxPayList.put("ELEC_BACK_DOC_NUM", "123456789123456789");
//数据总数
int total=10;
//页面条数 一页1-3条
int pageNumSize=1;
//生成pdf页数 10/3=4页
try {
//创建文档对象
Document document = new Document(PageSize.A4);
//导出的地址
PdfWriter.getInstance(document, new FileOutputStream("D:\\pdfOut\\otherModel_test_1.pdf"));
//打开文档
document.open();
//中文字体,解决中文不能显示问题
//BaseFont bfChinese = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font blueFont = new Font(bfChinese, 14, Font.BOLD);
//设置字体黑色
blueFont.setColor(BaseColor.BLACK);
Font blueFont1 = new Font(bfChinese, 12, Font.BOLD);
//字体颜色
blueFont1.setColor(BaseColor.BLACK);
//设置字体黑色
Font fontValueBody = new Font(bfChinese);
fontValueBody.setColor(BaseColor.BLACK);
fontValueBody.setSize(8);
Font fontValueLabelBody = new Font(bfChinese, 8, Font.BOLD);
//
Font fontValue = new Font(bfChinese);
fontValue.setColor(BaseColor.BLACK);
fontValue.setSize(9f);
int pageNumSizeCount=0;
//核心处理逻辑
for(int i=0;i<total;i++) {
//计数器 计数添加在页面的数为a4的最大页面数
pageNumSizeCount+=1;
pdfContent(document, taxPayList, blueFont, blueFont1, fontValueBody);
if(pageNumSizeCount==pageNumSize){
document.newPage();
pageNumSizeCount=0;
}
}
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void pdfContent(Document document, Map<String, Object> pdfFillContent, Font blueFont, Font blueFont1, Font fontValueBody) throws DocumentException {
//pdfContent start
Paragraph paragraph1 = new Paragraph("XX银行单位定期存单电子凭证", blueFont);
Paragraph paragraph = new Paragraph();
//设置段落前后间距
paragraph1.setSpacingAfter(20);
//设置段段落居中
paragraph1.setAlignment(Element.ALIGN_CENTER);
document.add(paragraph1);
//定义段落
Paragraph paragraphL = new Paragraph("", blueFont1);
Paragraph paragraphR = new Paragraph();
Phrase elecDocNumLabel = new Phrase("电子凭证编号:", blueFont1);
//Phrase elecDocNum=new Phrase(taxPayList.get("ELEC_BACK_DOC_NUM").toString(),fontValueLabelBody);
Phrase elecDocNum = new Phrase(pdfFillContent.get("ELEC_BACK_DOC_NUM").toString(), blueFont1);
paragraphR.add(elecDocNumLabel);
paragraphR.add(elecDocNum);
//设置段落前后间距
paragraphL.setLeading(0);
paragraphL.setAlignment(0);
paragraphR.setLeading(0);
paragraphR.setAlignment(2);
//设置段段落居中
paragraph.add(paragraphL);
paragraph.add(paragraphR);
paragraph.setSpacingAfter(18);
document.add(paragraph);
//LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
//定义列数
int tableBodyFlag = 15;
// 创建表对象
PdfPTable tableBody = new PdfPTable(tableBodyFlag);
//居中对齐
tableBody.setHorizontalAlignment(Element.ALIGN_CENTER);
tableBody.setWidthPercentage(100); // 宽度100%填充
float[] columnWidths1 = {0.15f,0.1f,0.15f,0.09f,0.1f,0.05f,0.09f,0.1f,0.15f,0.09f,0.1f,0.05f,0.09f,0.09f,0.1f};
tableBody.setWidths(columnWidths1);
//设置行对象
ArrayList<PdfPRow> listRowBody = tableBody.getRows();
//第一行
PdfPCell body1[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph10 = new Paragraph("你单位已在我行开立单位定期存单。", fontValueBody);
body1[0] = new PdfPCell(paragraph10);//单元格内容
body1[0].setColspan(15);
body1[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body1[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body1[0].setMinimumHeight(15);
PdfPRow rowBody1 = new PdfPRow(body1);
PdfPCell body2[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph20 = new Paragraph("户名", fontValueBody);
Paragraph paragraph21 = new Paragraph("户名", fontValueBody);
Paragraph paragraph22 = new Paragraph("开户日期", fontValueBody);
Paragraph paragraph23 = new Paragraph("开户日期", fontValueBody);
body2[0] = new PdfPCell(paragraph20);//单元格内容
body2[1] = new PdfPCell(paragraph21);//单元格内容
body2[12] = new PdfPCell(paragraph22);//单元格内容
body2[13] = new PdfPCell(paragraph23);//单元格内容
body2[1].setColspan(11);
body2[13].setColspan(2);
body2[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body2[1].setHorizontalAlignment(Element.ALIGN_LEFT);
body2[12].setHorizontalAlignment(Element.ALIGN_CENTER);
body2[13].setHorizontalAlignment(Element.ALIGN_LEFT);
body2[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body2[1].setVerticalAlignment(Element.ALIGN_MIDDLE);
body2[12].setVerticalAlignment(Element.ALIGN_MIDDLE);
body2[13].setVerticalAlignment(Element.ALIGN_MIDDLE);
body2[0].setMinimumHeight(15);
body2[1].setMinimumHeight(15);
body2[12].setMinimumHeight(15);
body2[13].setMinimumHeight(15);
PdfPRow rowBody2 = new PdfPRow(body2);
PdfPCell body3[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph30 = new Paragraph("账号", fontValueBody);
Paragraph paragraph31 = new Paragraph("账号", fontValueBody);
Paragraph paragraph32 = new Paragraph("起息日期", fontValueBody);
Paragraph paragraph33 = new Paragraph("起息日期", fontValueBody);
body3[0] = new PdfPCell(paragraph30);//单元格内容
body3[1] = new PdfPCell(paragraph31);//单元格内容
body3[12] = new PdfPCell(paragraph32);//单元格内容
body3[13] = new PdfPCell(paragraph33);//单元格内容
body3[1].setColspan(11);
body3[13].setColspan(2);
body3[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body3[1].setHorizontalAlignment(Element.ALIGN_LEFT);
body3[12].setHorizontalAlignment(Element.ALIGN_CENTER);
body3[13].setHorizontalAlignment(Element.ALIGN_LEFT);
body3[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body3[1].setVerticalAlignment(Element.ALIGN_MIDDLE);
body3[12].setVerticalAlignment(Element.ALIGN_MIDDLE);
body3[13].setVerticalAlignment(Element.ALIGN_MIDDLE);
body3[0].setMinimumHeight(15);
body3[1].setMinimumHeight(15);
body3[12].setMinimumHeight(15);
body3[13].setMinimumHeight(15);
PdfPRow rowBody3 = new PdfPRow(body3);
PdfPCell body4[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph40 = new Paragraph("种类", fontValueBody);
Paragraph paragraph41 = new Paragraph("种类".toString(), fontValueBody);
Paragraph paragraph42 = new Paragraph("利率", fontValueBody);
Paragraph paragraph43 = new Paragraph("".toString(), fontValueBody);
Paragraph paragraph44 = new Paragraph("约转方式", fontValueBody);
Paragraph paragraph45 = new Paragraph("约转方式".toString(), fontValueBody);
Paragraph paragraph46 = new Paragraph("约转存期", fontValueBody);
Paragraph paragraph47 = new Paragraph("约转存期".toString(), fontValueBody);
Paragraph paragraph48 = new Paragraph("存期", fontValueBody);
Paragraph paragraph49 = new Paragraph("存期".toString(), fontValueBody);
body4[0] = new PdfPCell(paragraph40);//单元格内容
body4[1] = new PdfPCell(paragraph41);//单元格内容
body4[3] = new PdfPCell(paragraph42);//单元格内容
body4[4] = new PdfPCell(paragraph43);//单元格内容
body4[6] = new PdfPCell(paragraph44);//单元格内容
body4[7] = new PdfPCell(paragraph45);//单元格内容
body4[9] = new PdfPCell(paragraph46);//单元格内容
body4[10] = new PdfPCell(paragraph47);//单元格内容
body4[12] = new PdfPCell(paragraph48);//单元格内容
body4[13] = new PdfPCell(paragraph49);//单元格内容
body4[1].setColspan(2);
body4[4].setColspan(2);
body4[7].setColspan(2);
body4[10].setColspan(2);
body4[13].setColspan(2);
body4[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body4[1].setHorizontalAlignment(Element.ALIGN_LEFT);
body4[3].setHorizontalAlignment(Element.ALIGN_CENTER);
body4[4].setHorizontalAlignment(Element.ALIGN_LEFT);
body4[6].setHorizontalAlignment(Element.ALIGN_CENTER);
body4[7].setHorizontalAlignment(Element.ALIGN_LEFT);
body4[9].setHorizontalAlignment(Element.ALIGN_CENTER);
body4[10].setHorizontalAlignment(Element.ALIGN_LEFT);
body4[12].setHorizontalAlignment(Element.ALIGN_CENTER);
body4[13].setHorizontalAlignment(Element.ALIGN_LEFT);
body4[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[1].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[3].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[4].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[6].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[7].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[9].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[10].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[12].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[13].setVerticalAlignment(Element.ALIGN_MIDDLE);
body4[0].setMinimumHeight(15);
body4[1].setMinimumHeight(15);
body4[3].setMinimumHeight(15);
body4[4].setMinimumHeight(15);
body4[6].setMinimumHeight(15);
body4[7].setMinimumHeight(15);
body4[9].setMinimumHeight(15);
body4[10].setMinimumHeight(15);
body4[12].setMinimumHeight(15);
body4[13].setMinimumHeight(15);
PdfPRow rowBody4 = new PdfPRow(body4);
PdfPCell body5[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph50 = new Paragraph("开户银行", fontValueBody);
Paragraph paragraph51 = new Paragraph("开户银行", fontValueBody);
Paragraph paragraph52 = new Paragraph("到期日期", fontValueBody);
Paragraph paragraph53 = new Paragraph("到期日期", fontValueBody);
body5[0] = new PdfPCell(paragraph50);//单元格内容
body5[1] = new PdfPCell(paragraph51);//单元格内容
body5[12] = new PdfPCell(paragraph52);//单元格内容
body5[13] = new PdfPCell(paragraph53);//单元格内容
body5[1].setColspan(11);
body5[13].setColspan(2);
body5[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body5[1].setHorizontalAlignment(Element.ALIGN_LEFT);
body5[12].setHorizontalAlignment(Element.ALIGN_CENTER);
body5[13].setHorizontalAlignment(Element.ALIGN_LEFT);
body5[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body5[1].setVerticalAlignment(Element.ALIGN_MIDDLE);
body5[12].setVerticalAlignment(Element.ALIGN_MIDDLE);
body5[13].setVerticalAlignment(Element.ALIGN_MIDDLE);
body5[0].setMinimumHeight(15);
body5[1].setMinimumHeight(15);
body5[12].setMinimumHeight(15);
body5[13].setMinimumHeight(15);
PdfPRow rowBody5 = new PdfPRow(body5);
PdfPCell body6[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph60 = new Paragraph("金额(大写)", fontValueBody);
Paragraph paragraph61 = new Paragraph("金额(大写)".toString(), fontValueBody);
body6[0] = new PdfPCell(paragraph60);//单元格内容
body6[1] = new PdfPCell(paragraph61);//单元格内容
body6[1].setColspan(14);
body6[0].setHorizontalAlignment(Element.ALIGN_CENTER);
body6[1].setHorizontalAlignment(Element.ALIGN_LEFT);
body6[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body6[1].setVerticalAlignment(Element.ALIGN_MIDDLE);
body6[0].setMinimumHeight(15);
body6[1].setMinimumHeight(15);
PdfPRow rowBody6 = new PdfPRow(body6);
PdfPCell body7[] = new PdfPCell[tableBodyFlag];
Paragraph paragraph70 = new Paragraph("本电子凭证所示存单信息,仅对借款人作为质押贷款之用,存款人不得提前支取。", fontValueBody);
body7[0] = new PdfPCell(paragraph70);//单元格内容
body7[0].setColspan(15);
body7[0].setVerticalAlignment(Element.ALIGN_MIDDLE);
body7[0].setMinimumHeight(20);
PdfPRow rowBody7 = new PdfPRow(body7);
listRowBody.add(rowBody1);
listRowBody.add(rowBody2);
listRowBody.add(rowBody3);
listRowBody.add(rowBody4);
listRowBody.add(rowBody5);
listRowBody.add(rowBody6);
listRowBody.add(rowBody7);
document.add(tableBody);
}
}
结果
一页1条:
一页2条:
一页4条:
总结
关于pdf一页多条的需求,是我近期在实际开发中遇到的,当时没有接触过POI这块,后来也是分析和学习,查阅了很多资料搜寻到的,希望对各位正在遇到的该问题的有帮助,谢谢各位!
注意
需求中,有可能一页A4装不下3条或者4条,甚至2条就不行,这时候需要去和产品沟通,是否需要调整需求。比如A4需要查询几个班的成绩单,一个班的数据可能一张A4展示不下,这是有可能舍弃一页多条的需求。
标签:java,ALIGN,Element,Paragraph,PdfPCell,new,100w,pdf,body4 From: https://blog.csdn.net/Wjingze/article/details/139703501