Java 生成各种 PDF 实战方案(图片、模板、表格)

傷城~ 2023-10-12 21:03 166阅读 0赞

pom依赖

首先先引入咱们需要的pom依赖,我这里只粘贴pdf的吧,lombok和hutool经常用我就不粘贴了。、

  1. <dependency>
  2. <groupId>com.itextpdf</groupId>
  3. <artifactId>itextpdf</artifactId>
  4. <version>5.5.9</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.itextpdf</groupId>
  8. <artifactId>itext-asian</artifactId>
  9. <version>5.2.0</version>
  10. </dependency>

生成pdf,模板和图片及动态生成表格

这个没有搞页眉,只搞了页脚,设置页眉/页脚和水印的类会在最后粘贴出来,因为这几个案例用的都是一个配置类。

实体类

  1. @Data
  2. @Accessors(chain = true)
  3. public class DuizhangDomain {
  4. private String jg;
  5. private Integer ydz;
  6. private Integer wdz;
  7. private BigDecimal dzl;
  8. }
  9. @Data
  10. @Accessors(chain = true)
  11. public class YqTable implements Serializable {
  12. private String jg;
  13. private Integer yqs;
  14. }

生成pdf代码

  1. /**
  2. * 根据模板填充数据及图片,动态生成数据列表
  3. */
  4. public class CreatePdfEchrtsAndTableMain2 {
  5. private final static String TITLE = "这个是标题,可有可无";
  6. public void createPdfFile(HttpServletResponse response) throws IOException,
  7. DocumentException, TemplateException {
  8. //设置请求返回类型
  9. response.setHeader("Content-Disposition", "attachment;
  10. filename=测试.pdf"
  11. );
  12. OutputStream outputStream = response.getOutputStream();
  13. //模板路径,放到项目里用这个ClassPathResource
  14. ClassPathResource classPathResource = new ClassPathResource
  15. ("templates/
  16. test1.pdf");
  17. InputStream inputStream = classPathResource.getInputStream();
  18. PdfReader reader = new PdfReader(inputStream);
  19. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  20. PdfStamper ps = new PdfStamper(reader, bos);
  21. //设置字体
  22. final BaseFont font = BaseFont.createFont("STSong-Light",
  23. "UniGB-UCS2-H"
  24. , BaseFont.NOT_EMBEDDED);
  25. ArrayList<BaseFont> fontList = new ArrayList<>();
  26. fontList.add(font);
  27. //提取表单,这个是模板画好的文本框
  28. AcroFields s = ps.getAcroFields();
  29. s.setSubstitutionFonts(fontList);
  30. s.setFieldProperty("jrfk","textfont",font,null);
  31. s.setFieldProperty("bjzs","textfont",font,null);
  32. s.setFieldProperty("type","textfont",font,null);
  33. s.setFieldProperty("createTime","textfont",font,null);
  34. s.setFieldProperty("title","textfont",font,null);
  35. s.setField("jrfk","10");
  36. s.setField("bjzs","20");
  37. s.setField("type","日报");
  38. s.setField("createTime", DateUtil.now());
  39. s.setField("title", TITLE);
  40. //添加图片
  41. PdfContentByte cb = ps.getOverContent(1);
  42. //添加logo
  43. Rectangle logo = s.getFieldPositions("logo").get(0).
  44. position;
  45. Image logoImage = Image.getInstance("https://img1.baidu.
  46. com/
  47. it/u=36462618
  48. 57,3326755268&fm=253&app=138&size=w931&n=0&f=JPG&fmt=auto?
  49. sec=1668186000&
  50. t=20050fc88fc3feb1f9d28392f4595ec6");
  51. //根据域的大小缩放图片,我这里宽度在原有的域基础上加了100,你们可以自己调节
  52. logoImage.scaleToFit(logo.getWidth() + 100,logo.getHeight());
  53. logoImage.setAlignment(Image.MIDDLE);
  54. logoImage.setAbsolutePosition(logo.getLeft(),logo.getBottom());
  55. cb.addImage(logoImage);
  56. //获取统计图
  57. //获取域
  58. Rectangle rlt = s.getFieldPositions("rlt").get(0).position;
  59. //热力图
  60. Image rltImage = Image.getInstance("https://img0.baidu.com/it/u=404317734
  61. 5,1055141017&fm=253&app=138&size=w931&n=0&f=PNG&fmt=auto?sec=1668186000&t
  62. =8cfdc5c95cc0070eb91946d780ee8dc3");
  63. //根据域大小设置缩放图片
  64. rltImage.scaleToFit(rlt.getWidth() + 100,rlt.getHeight());
  65. // 设置居中
  66. rltImage.setAlignment(Image.MIDDLE);
  67. //绝对定位
  68. rltImage.setAbsolutePosition(rlt.getLeft(),rlt.getBottom());
  69. //图片旋转,这个可以将图片进行一个旋转,看自己需求
  70. // rltImage.setRotationDegrees(90);
  71. cb.addImage(rltImage);
  72. //按机构统计图
  73. //这个是生成echarts的类,如果需要生成echarts可以去看我的另一个文章,
  74. //上面前言已经提到了
  75. App app1 = new App();
  76. byte[] echarts1 = app1.createEcharts("ajg.ftl");
  77. Image ajgImage = Image.getInstance(echarts1);
  78. Rectangle ajg = s.getFieldPositions("ajg").get(0).position;
  79. // 根据域大小设置缩放图片
  80. ajgImage.scaleToFit(ajg.getWidth(),400);
  81. // 设置居中
  82. ajgImage.setAlignment(Image.MIDDLE);
  83. // 绝对定位
  84. ajgImage.setAbsolutePosition(ajg.getLeft(),ajg.getBottom());
  85. cb.addImage(ajgImage);
  86. //按机构排名,这个是在图片的基础上还要添加数据,这个模板可以画好
  87. for (int i = 1; i <= 3; i++) {
  88. s.setFieldProperty("ajg" + i,"textfont",font,null);
  89. s.setField("ajg" + i,"机构" + i);
  90. }
  91. App app = new App();
  92. byte[] echarts = app.createEcharts("option.ftl");
  93. //按业务
  94. Rectangle ayw = s.getFieldPositions("ayw").get(0).position;
  95. Image aywImage = Image.getInstance(echarts);
  96. // 设根据域大小设置缩放图片
  97. aywImage.scaleToFit(ayw.getWidth(), 400);
  98. // 设置居中
  99. aywImage.setAlignment(Image.MIDDLE);
  100. // 绝对定位
  101. aywImage.setAbsolutePosition(ayw.getLeft(),ayw.getBottom());
  102. cb.addImage(aywImage);
  103. //按业务排名
  104. for (int i = 1; i <= 3; i++) {
  105. s.setFieldProperty("ayw" + i,"textfont",font,null);
  106. s.setField("ayw" + i,"机构" + i);
  107. }
  108. //按场合
  109. Rectangle acj = s.getFieldPositions("acj").get(0).position;
  110. Image acjImage = Image.getInstance(echarts);
  111. // 设根据域大小设置缩放图片
  112. acjImage.scaleToFit(acj.getWidth(), 400);
  113. // 设置居中
  114. acjImage.setAlignment(Image.MIDDLE);
  115. // 绝对定位
  116. acjImage.setAbsolutePosition(acj.getLeft(),acj.getBottom());
  117. cb.addImage(acjImage);
  118. //按场景排名
  119. for (int i = 1; i <= 3; i++) {
  120. s.setFieldProperty("acj" + i,"textfont",font,null);
  121. s.setField("acj" + i,"机构" + i);
  122. }
  123. //按等级
  124. Rectangle adj = s.getFieldPositions("adj").get(0).position;
  125. Image adjImage = Image.getInstance(echarts);
  126. // 设根据域大小设置缩放图片
  127. adjImage.scaleToFit(adj.getWidth(),400);
  128. // 设置居中
  129. adjImage.setAlignment(Image.MIDDLE);
  130. // 绝对定位
  131. adjImage.setAbsolutePosition(adj.getLeft(),adj.getBottom());
  132. cb.addImage(adjImage);
  133. //按场景排名
  134. for (int i = 1; i <= 3; i++) {
  135. s.setFieldProperty("adj" + i,"textfont",font,null);
  136. s.setField("adj" + i,"机构" + i);
  137. }
  138. ps.setFormFlattening(true);
  139. ps.close();
  140. //*******************填充编辑好后的pdf**************
  141. reader = new PdfReader(bos.toByteArray());
  142. Rectangle pageSize = reader.getPageSize(1);
  143. Document document = new Document(pageSize);
  144. PdfWriter writer = PdfWriter.getInstance(document, outputStream);
  145. writer.setPageEvent(new PageEvent());
  146. // 打开文档
  147. document.open();
  148. PdfContentByte cbUnder = writer.getDirectContentUnder();
  149. PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
  150. cbUnder.addTemplate(pageTemplate, 0, 0);
  151. //重新开一页面
  152. document.newPage();
  153. createTable(writer,document);
  154. // document.newPage();
  155. createTableYq(writer,document);
  156. document.close();
  157. outputStream.close();
  158. }
  159. //为一个表格添加内容
  160. public PdfPCell createSetCell(String value,Font font){
  161. PdfPCell cell = new PdfPCell();
  162. cell.setPhrase(new Phrase(value,font));
  163. cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  164. cell.setHorizontalAlignment(Element.ALIGN_CENTER);
  165. return cell;
  166. }
  167. //添加表格
  168. public void createTable(PdfWriter writer,Document document) throws DocumentException, IOException {
  169. PdfPTable table = new PdfPTable(new float[] {
  170. 30, 80, 50, 50, 50});
  171. table.setTotalWidth(520);
  172. table.setPaddingTop(500);
  173. table.setLockedWidth(true);
  174. table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
  175. table.writeSelectedRows(0, -1,500,800,writer.getDirectContentUnder());
  176. //每页都显示表头,输入几就是第几行的表头固定
  177. table.setHeaderRows(2);
  178. table.setHeaderRows(3);
  179. //定义数据的字体
  180. BaseFont baseFont = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",
  181. BaseFont.NOT_EMBEDDED);
  182. Font textFont = new Font(baseFont, 10, Font.NORMAL);
  183. PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));
  184. cell.setHorizontalAlignment( Element.ALIGN_LEFT);
  185. cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
  186. cell.setBorder(Rectangle.NO_BORDER);
  187. cell.setColspan(5);
  188. table.addCell(cell);
  189. //表头信息
  190. PdfPCell heandCell = new PdfPCell();
  191. heandCell.setRowspan(1);
  192. heandCell.setColspan(5);
  193. heandCell.setFixedHeight(60);
  194. heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  195. heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  196. heandCell.setPhrase(new Phrase(TITLE + "对账情况表",textFont));
  197. table.addCell(heandCell);
  198. //表字段
  199. String title[] = {
  200. "序号","机构","已对账","未对账","对账率%"};
  201. for (int i = 0; i < title.length; i++) {
  202. PdfPCell heardCell = new PdfPCell();
  203. heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  204. heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  205. heardCell.setPhrase(new Phrase(title[i], textFont));
  206. heardCell.setMinimumHeight(20);
  207. table.addCell(heardCell);
  208. }
  209. //列表数据
  210. List<DuizhangDomain> duizhangDomains = new ArrayList<>();
  211. for (int i = 1; i <= 1000; i++) {
  212. DuizhangDomain duizhangDomain = new DuizhangDomain();
  213. duizhangDomain.setJg("机构" + i).setYdz(i).setWdz(i).setDzl(new
  214. BigDecimal(i));
  215. duizhangDomains.add(duizhangDomain);
  216. }
  217. for (int i = 0; i < duizhangDomains.size(); i++) {
  218. PdfPCell setCell1 = createSetCell((i + 1) + "", textFont);
  219. PdfPCell setCell2 = createSetCell(duizhangDomains.get(i).getJg(),
  220. textFont);
  221. PdfPCell setCell3 = createSetCell(duizhangDomains.get(i).getYdz().
  222. toString(), textFont);
  223. PdfPCell setCell4 = createSetCell(duizhangDomains.get(i).getWdz().
  224. toString(), textFont);
  225. PdfPCell setCell5 = createSetCell(duizhangDomains.get(i).getDzl() +
  226. "%", textFont);
  227. table.addCell(setCell1);
  228. table.addCell(setCell2);
  229. table.addCell(setCell3);
  230. table.addCell(setCell4);
  231. table.addCell(setCell5);
  232. }
  233. document.add(table);
  234. }
  235. public void createTableYq(PdfWriter writer,Document document) throws
  236. DocumentException, IOException {
  237. PdfPTable table = new PdfPTable(new float[] {
  238. 80, 50});
  239. table.setTotalWidth(520);
  240. table.setPaddingTop(500);
  241. table.setLockedWidth(true);
  242. table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
  243. table.writeSelectedRows(0, -1,500,800,writer.getDirectContentUnder());
  244. //每页都显示表头,输入几就是第几行的表头固定
  245. table.setHeaderRows(2);
  246. table.setHeaderRows(3);
  247. //定义数据的字体
  248. BaseFont baseFont = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",
  249. BaseFont.NOT_EMBEDDED);
  250. Font textFont = new Font(baseFont, 10, Font.NORMAL);
  251. //这个是为了区分两个表格加的一个间隔,可以去掉
  252. PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));
  253. cell.setHorizontalAlignment( Element.ALIGN_LEFT);
  254. cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
  255. cell.setBorder(Rectangle.NO_BORDER);
  256. cell.setColspan(2);
  257. table.addCell(cell);
  258. //表头信息
  259. PdfPCell heandCell = new PdfPCell();
  260. heandCell.setRowspan(1);
  261. heandCell.setColspan(2);
  262. heandCell.setFixedHeight(60);
  263. heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  264. heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  265. heandCell.setPhrase(new Phrase(TITLE + "逾期表",textFont));
  266. table.addCell(heandCell);
  267. //表字段
  268. String title[] = {
  269. "机构名称","逾期数"};
  270. for (int i = 0; i < title.length; i++) {
  271. PdfPCell heardCell = new PdfPCell();
  272. heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  273. heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  274. heardCell.setPhrase(new Phrase(title[i], textFont));
  275. heardCell.setMinimumHeight(20);
  276. table.addCell(heardCell);
  277. }
  278. //列表数据
  279. List<YqTable> yqTables = new ArrayList<>();
  280. for (int i = 1; i <= 1000; i++) {
  281. YqTable yq = new YqTable();
  282. yq.setJg("逾期机构" + i).setYqs(i);
  283. yqTables.add(yq);
  284. }
  285. for (int i = 0; i < yqTables.size(); i++) {
  286. PdfPCell setCell2 = createSetCell(yqTables.get(i).getJg(), textFont);
  287. PdfPCell setCell3 = createSetCell(yqTables.get(i).getYqs().
  288. toString(), textFont);
  289. table.addCell(setCell2);
  290. table.addCell(setCell3);
  291. }
  292. document.add(table);
  293. }
  294. }

我说一下这个生成pdf需要注意的点,可能有的朋友很疑惑为什么要调用document.newPage(); 新开一页,这个是因为,如果你不新开一页的话会导致你动态生成的表格会跟模板内容重叠,注意是重叠而不是覆盖!!!

新开一页的话,就相当于我在第二页开始动态生成表格,这个时候可能有朋友就要问了,那如果我的模板没有占到一页怎么办,这样第一页岂不是会有空白,这个问题我也想到了,因为我的需求是生成好几种不同的pdf,下面我会把这种情况如何生成的代码放出来,我们先看一下第一种生成出来后的结果,我测的数据比较多,就粘几个结果好了。

生成pdf,模板和动态表格

实体类都是一样的没有变。

生成pdf代码

  1. /**
  2. * 模板第一页不占满,生成表格
  3. */
  4. public class CreatePdfEchrtsAndTableMain3 {
  5. public void createPdfFile(HttpServletResponse response) throws IOException,
  6. DocumentException, TemplateException {
  7. //设置请求返回类型
  8. response.setHeader("Content-Disposition", "attachment; filename=测试.pdf");
  9. OutputStream outputStream = response.getOutputStream();
  10. //模板路径,放到项目里用这个ClassPathResource
  11. ClassPathResource classPathResource = new ClassPathResource("templates
  12. /test3.pdf");
  13. InputStream inputStream = classPathResource.getInputStream();
  14. PdfReader reader = new PdfReader(inputStream);
  15. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  16. PdfStamper ps = new PdfStamper(reader, bos);
  17. //设置字体
  18. final BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H"
  19. , BaseFont.NOT_EMBEDDED);
  20. ArrayList<BaseFont> fontList = new ArrayList<>();
  21. fontList.add(font);
  22. //提取表单
  23. AcroFields s = ps.getAcroFields();
  24. s.setSubstitutionFonts(fontList);
  25. s.setFieldProperty("type", "textfont", font, null);
  26. s.setFieldProperty("createTime", "textfont", font, null);
  27. s.setFieldProperty("title", "textfont", font, null);
  28. s.setField("type", "日报");
  29. s.setField("createTime", DateUtil.now());
  30. s.setField("title", "这是title,模板画的位置框");
  31. ps.setFormFlattening(true);
  32. ps.close();
  33. //*******************填充编辑好后的pdf**************
  34. reader = new PdfReader(bos.toByteArray());
  35. Rectangle pageSize = reader.getPageSize(1);
  36. Document document = new Document(pageSize);
  37. PdfWriter writer = PdfWriter.getInstance(document, outputStream);
  38. writer.setPageEvent(new PageEvent());
  39. // 打开文档
  40. document.open();
  41. PdfContentByte cbUnder = writer.getDirectContentUnder();
  42. PdfImportedPage pageTemplate = writer.getImportedPage(reader, 1);
  43. cbUnder.addTemplate(pageTemplate, 0, 0);
  44. //添加间隙,这里为进行了一个封装,因为这个模板第一页只有一些title啥的,
  45. //重开一页太浪费,只需要确定表格要在什么位置生成,添加一个间隙就可以了
  46. createBlankTable(writer, document, font, 180);
  47. createTable(writer, document);
  48. createBlankTable(writer, document, font, 20);
  49. createTableYq(writer, document);
  50. document.close();
  51. outputStream.close();
  52. }
  53. //为一个表格添加内容
  54. public PdfPCell createSetCell(String value, Font font) {
  55. PdfPCell cell = new PdfPCell();
  56. cell.setPhrase(new Phrase(value, font));
  57. cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  58. cell.setHorizontalAlignment(Element.ALIGN_CENTER);
  59. return cell;
  60. }
  61. //添加表格
  62. public void createTable(PdfWriter writer, Document document) throws
  63. DocumentException, IOException {
  64. PdfPTable table = new PdfPTable(new float[]{
  65. 30, 80, 50, 50, 50});
  66. table.setTotalWidth(520);
  67. table.setPaddingTop(500);
  68. table.setLockedWidth(true);
  69. table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
  70. table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
  71. //每页都显示表头,输入几就是第几行的表头固定
  72. table.setHeaderRows(1);
  73. table.setHeaderRows(2);
  74. //定义数据的字体
  75. BaseFont baseFont = BaseFont.createFont("STSong-Light",
  76. "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
  77. Font textFont = new Font(baseFont, 10, Font.NORMAL);
  78. //表头信息
  79. PdfPCell heandCell = new PdfPCell();
  80. heandCell.setRowspan(1);
  81. heandCell.setColspan(5);
  82. heandCell.setFixedHeight(30);
  83. heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  84. heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  85. heandCell.setPhrase(new Phrase("对账情况表", textFont));
  86. table.addCell(heandCell);
  87. //表字段
  88. String title[] = {
  89. "序号", "机构", "已对账", "未对账", "对账率%"};
  90. for (int i = 0; i < title.length; i++) {
  91. PdfPCell heardCell = new PdfPCell();
  92. heardCell.setRowspan(1);
  93. heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  94. heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  95. heardCell.setPhrase(new Phrase(title[i], textFont));
  96. heardCell.setMinimumHeight(20);
  97. table.addCell(heardCell);
  98. }
  99. //列表数据
  100. List<DuizhangDomain> duizhangDomains = new ArrayList<>();
  101. for (int i = 1; i <= 1000; i++) {
  102. DuizhangDomain duizhangDomain = new DuizhangDomain();
  103. duizhangDomain.setJg("机构" + i).setYdz(i).setWdz(i).setDzl
  104. (new BigDecimal(i));
  105. duizhangDomains.add(duizhangDomain);
  106. }
  107. for (int i = 0; i < duizhangDomains.size(); i++) {
  108. PdfPCell setCell1 = createSetCell((i + 1) + "", textFont);
  109. PdfPCell setCell2 = createSetCell(duizhangDomains.get(i).getJg(),
  110. textFont);
  111. PdfPCell setCell3 = createSetCell(duizhangDomains.get(i).getYdz().
  112. toString(), textFont);
  113. PdfPCell setCell4 = createSetCell(duizhangDomains.get(i).getWdz().
  114. toString(), textFont);
  115. PdfPCell setCell5 = createSetCell(duizhangDomains.get(i).getDzl() +
  116. "%", textFont);
  117. table.addCell(setCell1);
  118. table.addCell(setCell2);
  119. table.addCell(setCell3);
  120. table.addCell(setCell4);
  121. table.addCell(setCell5);
  122. }
  123. document.add(table);
  124. }
  125. public void createTableYq(PdfWriter writer, Document document) throws
  126. DocumentException, IOException {
  127. PdfPTable table = new PdfPTable(new float[]{
  128. 80, 50});
  129. table.setTotalWidth(520);
  130. table.setPaddingTop(500);
  131. table.setLockedWidth(true);
  132. table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
  133. table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
  134. //每页都显示表头,输入几就是第几行的表头固定
  135. table.setHeaderRows(2);
  136. table.setHeaderRows(3);
  137. //定义数据的字体
  138. BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",
  139. BaseFont.NOT_EMBEDDED);
  140. Font textFont = new Font(baseFont, 10, Font.NORMAL);
  141. //表头信息
  142. PdfPCell heandCell = new PdfPCell();
  143. heandCell.setRowspan(1);
  144. heandCell.setColspan(2);
  145. heandCell.setFixedHeight(30);
  146. heandCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  147. heandCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  148. heandCell.setPhrase(new Phrase("逾期表", textFont));
  149. table.addCell(heandCell);
  150. //表字段
  151. String title[] = {
  152. "机构名称", "逾期数"};
  153. for (int i = 0; i < title.length; i++) {
  154. PdfPCell heardCell = new PdfPCell();
  155. heardCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
  156. heardCell.setHorizontalAlignment(Element.ALIGN_CENTER);
  157. heardCell.setPhrase(new Phrase(title[i], textFont));
  158. heardCell.setMinimumHeight(20);
  159. table.addCell(heardCell);
  160. }
  161. //列表数据
  162. List<YqTable> yqTables = new ArrayList<>();
  163. for (int i = 1; i <= 1000; i++) {
  164. YqTable yq = new YqTable();
  165. yq.setJg("逾期机构" + i).setYqs(i);
  166. yqTables.add(yq);
  167. }
  168. for (int i = 0; i < yqTables.size(); i++) {
  169. PdfPCell setCell2 = createSetCell(yqTables.get(i).getJg(), textFont);
  170. PdfPCell setCell3 = createSetCell(yqTables.get(i).getYqs().toString(), textFont);
  171. table.addCell(setCell2);
  172. table.addCell(setCell3);
  173. }
  174. document.add(table);
  175. }
  176. /**
  177. * 创建表格跟表格之间的空白间隔
  178. */
  179. public void createBlankTable(PdfWriter writer, Document document,
  180. BaseFont font, int height) throws DocumentException {
  181. PdfPTable table = new PdfPTable(new float[]{
  182. 30});
  183. table.setTotalWidth(520);
  184. table.setPaddingTop(500);
  185. table.setLockedWidth(true);
  186. table.setHorizontalAlignment(Element.ALIGN_CENTER);//居中
  187. table.writeSelectedRows(0, -1, 500, 800, writer.getDirectContentUnder());
  188. Font textFont = new Font(font, 10, Font.NORMAL);
  189. PdfPCell cell = new PdfPCell(new Paragraph(" ", textFont));
  190. cell.setHorizontalAlignment(Element.ALIGN_LEFT);
  191. cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
  192. cell.setBorder(Rectangle.NO_BORDER);
  193. cell.setFixedHeight(height);
  194. cell.setColspan(1);
  195. table.addCell(cell);
  196. document.add(table);
  197. }
  198. }

这是第二种生成pdf的方法,生成的结果不一样,因为模板第一页没有太多的东西,所以会空出来很多空白,这个时候生成动态表格如果重开一页比较浪费,而且客户看着也不好看,所以我封装了一下生成间隙的方法,直接用间隙把模板内容和表格隔开即可,看一下效果。
在代码中并没有新开一页,只是加了一个间隙,就可以保证动态生成的表格和模板在一个页面,就此,基本上就算完成了。

页眉/页脚和水印类

  1. public class PageEvent extends PdfPageEventHelper {
  2. /**
  3. * 页眉
  4. */
  5. //public String header = "itext测试页眉";
  6. /**
  7. * 文档字体大小,页脚页眉最好和文本大小一致
  8. */
  9. public int presentFontSize = 10;
  10. /**
  11. * 文档页面大小,最好前面传入,否则默认为A4纸张
  12. */
  13. public Rectangle pageSize = PageSize.A4;
  14. // 模板
  15. public PdfTemplate total;
  16. // 基础字体对象
  17. public BaseFont bf = null;
  18. // 利用基础字体生成的字体对象,一般用于生成中文文字
  19. public Font fontDetail = null;
  20. /**
  21. *
  22. * Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
  23. *
  24. */
  25. public PageEvent() {
  26. }
  27. /**
  28. *
  29. * Creates a new instance of PdfReportM1HeaderFooter 构造方法.
  30. *
  31. * @param
  32. *
  33. * @param presentFontSize
  34. * 数据体字体大小
  35. * @param pageSize
  36. * 页面文档大小,A4,A5,A6横转翻转等Rectangle对象
  37. */
  38. // public PDFBuilder(String yeMei, int presentFontSize, Rectangle pageSize) {
  39. // this.header = yeMei;
  40. // this.presentFontSize = presentFontSize;
  41. // this.pageSize = pageSize;
  42. // }
  43. public PageEvent( int presentFontSize, Rectangle pageSize) {
  44. this.presentFontSize = presentFontSize;
  45. this.pageSize = pageSize;
  46. }
  47. // public void setHeader(String header) {
  48. // this.header = header;
  49. // }
  50. public void setPresentFontSize(int presentFontSize) {
  51. this.presentFontSize = presentFontSize;
  52. }
  53. /**
  54. *
  55. * TODO 文档打开时创建模板
  56. *
  57. * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument
  58. (com.itextpdf.text.pdf.PdfWriter,
  59. * com.itextpdf.text.Document)
  60. */
  61. public void onOpenDocument(PdfWriter writer, Document document) {
  62. total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
  63. }
  64. /**
  65. *
  66. * TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
  67. *
  68. * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage
  69. (com.itextpdf.text.pdf.PdfWriter,
  70. * com.itextpdf.text.Document)
  71. */
  72. public void onEndPage(PdfWriter writer, Document document) {
  73. this.addPage(writer, document);
  74. //加水印
  75. this.addWatermark(writer);
  76. }
  77. //加分页
  78. public void addPage(PdfWriter writer, Document document){
  79. //设置分页页眉页脚字体
  80. try {
  81. if (bf == null) {
  82. bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
  83. }
  84. if (fontDetail == null) {
  85. fontDetail = new Font(bf, presentFontSize, Font.NORMAL);//
  86. 数据体字体
  87. }
  88. } catch (DocumentException e) {
  89. e.printStackTrace();
  90. } catch (IOException e) {
  91. e.printStackTrace();
  92. }
  93. // 1.写入页眉
  94. // ColumnText.showTextAligned(writer.getDirectContent(),
  95. // Element.ALIGN_LEFT, new Phrase(header, fontDetail),
  96. // document.left(), document.top() + 20, 0);
  97. // 页眉添加图片
  98. // String path = ResourceUtils.getFile("classpath:").getPath();
  99. // Image img = Image.getInstance(path + "/pdfTemplates/logo.jpg");
  100. // img.setAlignment(Image.MIDDLE);
  101. // img.setWidthPercentage(80);
  102. // img.scaleToFit(50,40);
  103. // img.setAbsolutePosition(document.left(),document.top());
  104. // writer.getDirectContent().addImage(img);
  105. //页眉加下划线
  106. // PdfPTable tableHeader = new PdfPTable(1);
  107. // tableHeader.setTotalWidth(PageSize.A4.getWidth() - 60);
  108. // PdfPCell pCell = new PdfPCell();
  109. // pCell.setBorderWidthBottom(0.3f);
  110. // tableHeader.addCell(pCell);
  111. // tableHeader.writeSelectedRows(0, -1, 30, 805, writer.getDirectContent());
  112. // 2.写入前半部分的 第 X页/共
  113. int pageS = writer.getPageNumber();
  114. String foot1 = "第 " + pageS + " 页 /共";
  115. // String foot1 = pageS +"/";
  116. Phrase footer = new Phrase(foot1, fontDetail);
  117. // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,
  118. 字体长度也要计算进去 = len
  119. float len = bf.getWidthPoint(foot1, presentFontSize);
  120. // 4.拿到当前的PdfContentByte
  121. PdfContentByte cb = writer.getDirectContent();
  122. // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
  123. // 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了
  124. // ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下
  125. 往上累加的,最上方的Top值是大于Bottom好几百开外的。
  126. ColumnText
  127. .showTextAligned(
  128. cb,
  129. Element.ALIGN_CENTER,
  130. footer,
  131. (document.rightMargin() + document.right()
  132. + document.leftMargin() - document.left() -
  133. len) / 2.0F ,
  134. document.bottom() - 20, 0);
  135. // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,
  136. X=(右边界-左边界 - 前半部分的len值)/2.0F +
  137. // len , y 轴和之前的保持一致,底边界-20
  138. cb.addTemplate(total, (document.rightMargin() + document.right()
  139. + document.leftMargin() - document.left()) / 2.0F ,
  140. document.bottom() - 20); // 调节模版显示的位置
  141. }
  142. //加水印
  143. public void addWatermark(PdfWriter writer) {
  144. // 水印图片
  145. // Image image;
  146. // try {
  147. // image = Image.getInstance("./web/images/001.jpg");
  148. // PdfContentByte content = writer.getDirectContentUnder();
  149. // content.beginText();
  150. // // 开始写入水印
  151. // for(int k=0;k<5;k++){
  152. // for (int j = 0; j <4; j++) {
  153. // image.setAbsolutePosition(150*j,170*k);
  154. // content.addImage(image);
  155. // }
  156. // }
  157. // content.endText();
  158. // } catch (IOException | DocumentException e) {
  159. // // TODO Auto-generated catch block
  160. // e.printStackTrace();
  161. // }
  162. BaseFont font = null;
  163. try {
  164. font = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",
  165. BaseFont.NOT_EMBEDDED);
  166. } catch (DocumentException e) {
  167. e.printStackTrace();
  168. } catch (IOException e) {
  169. e.printStackTrace();
  170. }
  171. PdfGState gs = new PdfGState();
  172. //添加透明度
  173. gs.setFillOpacity(0.4f);
  174. PdfContentByte content = writer.getDirectContentUnder();
  175. content.beginText();
  176. //水印颜色
  177. content.setColorFill(BaseColor.DARK_GRAY);
  178. content.setGState(gs);
  179. //水印字体样式和大小
  180. content.setFontAndSize(font, 35);
  181. //插入水印 循环每页插入的条数
  182. for (int j = 0; j < 3; j++) {
  183. content.showTextAligned(Element.ALIGN_CENTER, "锦鲤飞上天测试水印",
  184. 300, 200 * (j + 1), 30);
  185. }
  186. content.endText();
  187. }
  188. /**
  189. *
  190. * TODO 关闭文档时,替换模板,完成整个页眉页脚组件
  191. *
  192. * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter,
  193. * com.itextpdf.text.Document)
  194. */
  195. public void onCloseDocument(PdfWriter writer, Document document) {
  196. // 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
  197. total.beginText();
  198. total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
  199. String foot2 = " " + (writer.getPageNumber()) + " 页"; //页脚内容拼接 如 第1页/共2页
  200. // String foot2 = String.valueOf(writer.getPageNumber()); //页脚内容拼接 如 1/2
  201. total.showText(foot2);// 模版显示的内容
  202. total.endText();
  203. total.closePath();
  204. }
  205. }

发表评论

表情:
评论列表 (有 0 条评论,166人围观)

还没有评论,来说两句吧...

相关阅读