欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并等。

lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并等。

2025/2/26 14:00:22 来源:https://blog.csdn.net/qq_27413769/article/details/145854264  浏览:    关键词:lowagie(itext)老版本手绘PDF,包含页码、水印、图片、复选框、复杂行列合并等。

入口类:exportPdf

​
package xcsy.qms.webapi.service;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.StringUtils;
import com.ibm.icu.text.RuleBasedNumberFormat;
import com.lowagie.text.*;
import com.lowagie.text.Font;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.openapi.common.result.CustomApiResult;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import org.jsoup.Jsoup;
import xcsy.zjy.webapi.utils.AddImageToEachPageHeader;
import xcsy.zjy.webapi.utils.CheckBoxCellEvent;
import xcsy.zjy.webapi.utils.CheckBoxCellNotEvent;
import xcsy.zjy.webapi.utils.PdfPageUtil;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;/*** @program: xcsy-cosmic* @description: 准入报告pdf导出实现* @author: lyw* @create: 2025-02-13 09:31**/public class ReportsPDFService {private static final Log log = LogFactory.getLog(ReportsPDFService.class);// 定义全局的字体静态变量Font headFont;Font headFont2;Font contentFont;Font titleFont;Font titleFont2;Font titleFontW;SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");public CustomApiResult<String> exportPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {// 单据idString id = request.getParameter("id");DynamicObject accessReportsDO = BusinessDataServiceHelper.loadSingle(id, "eo45_access_reports");// 防止日志记录获取session异常request.getSession();// 设置编码格式response.setContentType("application/pdf;charset=UTF-8");response.setCharacterEncoding("utf-8");SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");String fileName = URLEncoder.encode(accessReportsDO.getString("eo45_fac_name") + "联盟工厂质量专项评审报告" + dateFormat.format(new Date()), "UTF-8");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");download(response, accessReportsDO);return CustomApiResult.success("成功");}private void download(HttpServletResponse response, DynamicObject reportData) {// 最大宽度try {// 不同字体(这里定义为同一种字体:包含不同字号、不同style)BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);headFont = new Font(bf, 18, Font.BOLD, new Color(0, 0, 0));headFont2 = new Font(bf, 14, Font.BOLD, new Color(0, 0, 0));titleFont = new Font(bf, 10, Font.BOLD, new Color(0, 103, 255));titleFont2 = new Font(bf, 12, Font.BOLD, new Color(0, 0, 0));titleFontW = new Font(bf, 12, Font.BOLD, new Color(251, 251, 251));contentFont = new Font(bfChinese, 10, Font.NORMAL, new Color(0, 0, 0));Document document = new Document(new RectangleReadOnly(842F, 595F));// 设置页边距document.setMargins(60, 60, 60, 30);PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());// 添加页码writer.setPageEvent(new PdfPageUtil());// 每页表头添加水印(图片)writer.setPageEvent(new AddImageToEachPageHeader());// 打开生成的pdf文件document.open();// 标题1Paragraph paragraph = new Paragraph(reportData.getString("eo45_fac_name") + "联盟工厂质量专项评审报告", headFont);paragraph.setAlignment(1);document.add(paragraph);// 评审总结DynamicObjectCollection resultsDO = reportData.getDynamicObjectCollection("eo45_report_results");DynamicObject entryResults = resultsDO.get(0);// -------基本信息buildBasicInformation(document, entryResults);// -------审核目的buildAuditAim(document, entryResults);// -------审核类型buildAuditType(document, reportData);// -------审核范围buildAuditRange(document, entryResults);// -------审核内容buildAuditContent(document, entryResults);// -------审核方法buildAuditMethod(document, entryResults);// -------审核方背景资料buildAuditData(document, entryResults);// -------审核结论buildAuditResult(document, entryResults);// 标题2Paragraph paragraph2 = new Paragraph("质量专项评审“否决项”评分标准", headFont2);paragraph2.setAlignment(1);document.add(paragraph2);float[] widthsOne = {10f, 20f, 60f, 10f};PdfPTable tableOne = new PdfPTable(widthsOne);handleTableOne(reportData, tableOne);document.add(tableOne);// 标题3Paragraph paragraph3 = new Paragraph("分值汇总", headFont2);paragraph3.setAlignment(1);document.add(paragraph3);float[] widthsTwo = {60f, 20f, 20f};PdfPTable tableTwo = new PdfPTable(widthsTwo);handleTableTwo(reportData, tableTwo);document.add(tableTwo);// 标题4Paragraph paragraph4 = new Paragraph("联盟工厂质量专项评审表", headFont2);paragraph4.setAlignment(1);document.add(paragraph4);float[] widthsThree = {5f, 15f, 30f, 25f, 5f, 5f, 5f, 7f, 25f};PdfPTable tableThree = new PdfPTable(widthsThree);handleTableThree(reportData, tableThree);document.add(tableThree);// 关闭文档document.close();} catch (DocumentException e) {log.error("导出pdf失败DocumentException:{}", e);} catch (Exception e) {log.error("导出pdf失败Exception:{}", e);}}private void handleTableThree(DynamicObject reportData, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = reportData.getDynamicObjectCollection("eo45_report_projects");// 按eo45_project_id分组Map<String, String> projectMap = new LinkedHashMap<>();// 获取项目,以项目id作为key,排除第一项否决项,按项目seq排序projectCollection.stream().filter(e -> !"0".equals(e.getString("eo45_project_seq"))).sorted(Comparator.comparing(dynamicObject -> dynamicObject.getString("eo45_project_seq"))).forEach(e -> projectMap.put(e.getString("eo45_project_id"), e.getString("eo45_project")));// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 设置表格宽度为100%// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(2);table.getDefaultCell().setHorizontalAlignment(1);// 第一行PdfPCell titleCell1 = createCenteredCellForTable("条款编号", 30, new Color(40, 120, 255), titleFontW, "border", "center");titleCell1.setRowspan(2);table.addCell(titleCell1);PdfPCell titleCell2 = createCenteredCellForTable("条款性质", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell2.setRowspan(2);table.addCell(titleCell2);PdfPCell titleCell3 = createCenteredCellForTable("审核条款标准", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell3.setRowspan(2);table.addCell(titleCell3);PdfPCell titleCell4= createCenteredCellForTable("审核正面发现", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell4.setRowspan(2);table.addCell(titleCell4);PdfPCell titleCell10 = createCenteredCellForTable("审核记录及说明", 0, new Color(40, 120, 255), titleFontW, "border", "center");titleCell10.setColspan(6);table.addCell(titleCell10);PdfPCell titleCell5 = createCenteredCellForTable("审核配分", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell5);PdfPCell titleCell6 = createCenteredCellForTable("符合程度", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell6);PdfPCell titleCell7 = createCenteredCellForTable("实际得分", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell7);PdfPCell titleCell8 = createCenteredCellForTable("不符合类型", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell8);PdfPCell titleCell9 = createCenteredCellForTable("问题描述", 0, new Color(40, 120, 255), titleFontW, "border", "center");table.addCell(titleCell9);int[] x = {0}; // 项目序号// 添加一级项目projectMap.forEach((projectId, projectName) -> {x[0]++;// 1转一RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.CHINA, RuleBasedNumberFormat.SPELLOUT);String result = formatter.format(x[0]);// 项目总分BigDecimal projectScoreAll = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_scoreall")).findFirst().orElse(BigDecimal.ZERO);PdfPCell projectCell = new PdfPCell(new Paragraph(result + "、" + projectName+ "(" + projectScoreAll.setScale(2, RoundingMode.HALF_UP)  + "分)", titleFont));projectCell.setColspan(9);tableCellStyle(projectCell, new Color(237, 239, 240), new Color(242, 247, 255), "border");table.addCell(projectCell);int y = 0; // 分类序号// 二级分类for (DynamicObject categorysDynamicObject : projectCollection) {if (projectId.equals(categorysDynamicObject.getString("eo45_project_id"))) {y++;PdfPCell cellClass = new PdfPCell(new Paragraph(x[0] + "." + y + " "+ categorysDynamicObject.getString("eo45_sort_name") + "(" + categorysDynamicObject.getBigDecimal("eo45_sort_scoreall").setScale(2, RoundingMode.HALF_UP)  + "分)", titleFont));cellClass.setColspan(9);tableCellStyle(cellClass, new Color(237, 239, 240), new Color(242, 247, 255), "border");table.addCell(cellClass);// 三级分类内容DynamicObjectCollection contents = categorysDynamicObject.getDynamicObjectCollection("eo45_report_contents");int z = 0; // 内容序号for (DynamicObject content : contents) {z++;String ratio = ""; // 系数// 单选题JSONArray optionArray = JSONArray.parseArray(content.getString("eo45_option_json_tag"));// 问题JSONArray problemArray = JSONArray.parseArray(content.getString("eo45_problem_json_tag"));// 合并行的数量int rowspan = 1;if (problemArray != null && !problemArray.isEmpty()) {rowspan = problemArray.size();}if (optionArray != null && !optionArray.isEmpty()) {for (int j = 0; j < optionArray.size(); j++) {JSONObject option = optionArray.getJSONObject(j);if (option.getInteger("choose") == 1) {if (!"N/A".equals(option.getString("scoreCoefficient"))&& StringUtils.isNotEmpty(option.getString("scoreCoefficient"))) {double decimal = Double.parseDouble(option.getString("scoreCoefficient"));// 转换为百分比并四舍五入到最接近的整数int percentage = (int) Math.round(decimal * 100);ratio = percentage + "%";}break;}}}PdfPCell cell1 = new PdfPCell(new Paragraph(x[0] + "." + y + "." + z, contentFont));cell1.setRowspan(rowspan);PdfPCell cell2 = new PdfPCell(new Paragraph(content.getString("eo45_import_area"), contentFont));cell2.setRowspan(rowspan);String contentContext = "";if (StringUtils.isNotBlank(content.getString("eo45_project_context"))) {org.jsoup.nodes.Document documentResult = Jsoup.parse(content.getString("eo45_project_context"));contentContext = documentResult.text();}PdfPCell cell3 = new PdfPCell(new Paragraph(contentContext, contentFont));cell3.setRowspan(rowspan);PdfPCell cell4 = new PdfPCell(new Paragraph(content.getString("eo45_content_suggestion"), contentFont));cell4.setRowspan(rowspan);PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(content.getBigDecimal("eo45_sum_score").setScale(2, RoundingMode.HALF_UP)), contentFont));cell5.setRowspan(rowspan);PdfPCell cell6 = new PdfPCell(new Paragraph(ratio, contentFont));cell6.setRowspan(rowspan);PdfPCell cell7 = new PdfPCell(new Paragraph(String.valueOf(content.getBigDecimal("eo45_content_score").setScale(2, RoundingMode.HALF_UP)), contentFont));cell7.setRowspan(rowspan);//单元格对齐方式水平、垂直tableCellStyle(cell1, new Color(237, 239, 240), null, "border");cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), null, "border");tableCellStyle(cell3, new Color(237, 239, 240), null, "border");tableCellStyle(cell4, new Color(237, 239, 240), null, "border");tableCellStyle(cell5, new Color(237, 239, 240), null, "border");tableCellStyle(cell6, new Color(237, 239, 240), null, "border");tableCellStyle(cell7, new Color(237, 239, 240), null, "border");table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);table.addCell(cell7);PdfPCell cell8, cell9;if (problemArray != null && !problemArray.isEmpty()) {for (int j = 0; j < problemArray.size(); j++) {JSONObject problem = problemArray.getJSONObject(j);String selectContent = "";JSONArray options = JSONArray.parseArray(problem.getString("options"));for (int k = 0; k < options.size(); k++) {JSONObject option = options.getJSONObject(k);if (option.getInteger("choose") == 1) {selectContent = option.getString("selectContent");break;}}cell8 = new PdfPCell(new Paragraph(selectContent, contentFont));cell9 = new PdfPCell(new Paragraph(problem.getString("problem_desc"), contentFont));tableCellStyle(cell8, new Color(237, 239, 240), null, "border");tableCellStyle(cell9, new Color(237, 239, 240), null, "border");table.addCell(cell8);table.addCell(cell9);}} else {cell8 = new PdfPCell(new Paragraph("", contentFont));cell9 = new PdfPCell(new Paragraph("", contentFont));tableCellStyle(cell8, new Color(237, 239, 240), null, "border");tableCellStyle(cell9, new Color(237, 239, 240), null, "border");table.addCell(cell8);table.addCell(cell9);}}}}});}private void handleTableTwo(DynamicObject reportData, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = reportData.getDynamicObjectCollection("eo45_report_projects");// 按eo45_project_id分组// Map<String, List<DynamicObject>> projectMap = projectCollection.stream().collect(Collectors.groupingBy(dynamicObject -> dynamicObject.getString("eo45_project_id")));Map<String, String> projectMap = new LinkedHashMap<>();// 获取项目,以项目id作为key,排除第一项否决项,按项目seq排序projectCollection.stream().filter(e -> !"0".equals(e.getString("eo45_project_seq"))).sorted(Comparator.comparing(dynamicObject -> dynamicObject.getString("eo45_project_seq"))).forEach(e -> projectMap.put(e.getString("eo45_project_id"), e.getString("eo45_project")));// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 距离下方空间table.setSpacingAfter(20f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(1);table.getDefaultCell().setHorizontalAlignment(1);// 第一行table.addCell(createCenteredCellForTable("主要项目", 30, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("项目配分", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("实际得分", 0, new Color(242, 247, 255), titleFont2, null, null));// 计数int[] projectSeq = {0};// 添加一级项目final BigDecimal[] allScore = {BigDecimal.ZERO}; // 审核分数合计final BigDecimal[] allGetScore = {BigDecimal.ZERO}; // 审核得分projectMap.forEach((projectId, projectName) -> {projectSeq[0]++;// 1转一RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(Locale.CHINA, RuleBasedNumberFormat.SPELLOUT);String result = formatter.format(projectSeq[0]);PdfPCell cell1 = new PdfPCell(new Paragraph(result + "、" + projectName, contentFont));// 获取对应项目的总分和得分BigDecimal eo45ProjectScoreAll = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_scoreall")).findFirst().orElse(BigDecimal.ZERO);allScore[0] = allScore[0].add(eo45ProjectScoreAll);BigDecimal eo45ProjectScore = projectCollection.stream().filter(e -> projectId.equals(e.getString("eo45_project_id"))).map(e -> e.getBigDecimal("eo45_project_score")).findFirst().orElse(BigDecimal.ZERO);allGetScore[0] = allGetScore[0].add(eo45ProjectScore);PdfPCell cell2 = new PdfPCell(new Paragraph(String.valueOf(eo45ProjectScoreAll.setScale(2, RoundingMode.HALF_UP)), contentFont));PdfPCell cell3 = new PdfPCell(new Paragraph(String.valueOf(eo45ProjectScore.setScale(2, RoundingMode.HALF_UP)), contentFont));//单元格对齐方式水平、垂直tableCellStyle(cell1, new Color(237, 239, 240), new Color(242, 247, 255), null);cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), new Color(242, 247, 255), null);tableCellStyle(cell3, new Color(237, 239, 240), new Color(242, 247, 255), null);table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);// 项目下添加二级分类int sortSeq = 0;for (DynamicObject categorysDynamicObject : projectCollection) {if (projectId.equals(categorysDynamicObject.getString("eo45_project_id"))) {sortSeq++;PdfPCell cell4 = new PdfPCell(new Paragraph(projectSeq[0] + "." + sortSeq + " " + categorysDynamicObject.getString("eo45_sort_name"), contentFont));PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(categorysDynamicObject.getBigDecimal("eo45_sort_scoreall").setScale(2, RoundingMode.HALF_UP)), contentFont));PdfPCell cell6 = new PdfPCell(new Paragraph(String.valueOf(categorysDynamicObject.getBigDecimal("eo45_sort_score").setScale(2, RoundingMode.HALF_UP)), contentFont));tableCellStyle(cell4, new Color(237, 239, 240), null, null);cell4.setFixedHeight(20);tableCellStyle(cell5, new Color(237, 239, 240), null, null);tableCellStyle(cell6, new Color(237, 239, 240), null, null);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);}}});// 添加分汇总PdfPCell cell4 = new PdfPCell(new Paragraph("审核分合计", titleFont));PdfPCell cell5 = new PdfPCell(new Paragraph(String.valueOf(allScore[0].setScale(2, RoundingMode.HALF_UP)), titleFont));PdfPCell cell6 = new PdfPCell(new Paragraph(String.valueOf(allGetScore[0].setScale(2, RoundingMode.HALF_UP)), titleFont));tableCellStyle(cell4, new Color(237, 239, 240), new Color(242, 247, 255), null);cell4.setFixedHeight(20);tableCellStyle(cell5, new Color(237, 239, 240), new Color(242, 247, 255), null);tableCellStyle(cell6, new Color(237, 239, 240), new Color(242, 247, 255), null);table.addCell(cell4);table.addCell(cell5);table.addCell(cell6);}private void handleTableOne(DynamicObject accessReportDO, PdfPTable table) {// 项目分类集合DynamicObjectCollection projectCollection = accessReportDO.getDynamicObjectCollection("eo45_report_projects");// 获取“否决项”数据DynamicObject oneProject = projectCollection.stream().filter(e -> "0".equals(e.getString("eo45_project_seq"))).collect(Collectors.toList()).get(0);DynamicObjectCollection contents = oneProject.getDynamicObjectCollection("eo45_report_contents");// 段落在其上方留出的空间量table.setSpacingBefore(10f);// 距离下方空间table.setSpacingAfter(20f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.setHeaderRows(1);table.getDefaultCell().setHorizontalAlignment(1);// 第一行table.addCell(createCenteredCellForTable("序号", 30, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("关键领域", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("检查项目内容", 0, new Color(242, 247, 255), titleFont2, null, null));table.addCell(createCenteredCellForTable("是/否", 0, new Color(242, 247, 255), titleFont2, null, null));// 数据for (int i = 0; i < contents.size(); i++) {PdfPCell cell1 = new PdfPCell(new Paragraph(String.valueOf(i + 1), contentFont));PdfPCell cell2 = new PdfPCell(new Paragraph(contents.get(i).getString("eo45_import_area"), contentFont));// 富文本处理String contentContext = "";if (StringUtils.isNotBlank(contents.get(i).getString("eo45_project_context"))) {org.jsoup.nodes.Document documentResult = Jsoup.parse(contents.get(i).getString("eo45_project_context"));contentContext = documentResult.text();}PdfPCell cell3 = new PdfPCell(new Paragraph(contentContext, contentFont));// 获取选项JSONArray optionJsonArray = JSONArray.parseArray(contents.get(i).getString("eo45_option_json_tag"));String selectContent = "";if (optionJsonArray != null && !optionJsonArray.isEmpty()) {for (int j = 0; j < optionJsonArray.size(); j++) {JSONObject optionJson = optionJsonArray.getJSONObject(j);if (optionJson.getInteger("choose") == 1) {selectContent = optionJson.getString("options_content");break;}}}PdfPCell cell4 = new PdfPCell(new Paragraph(selectContent, contentFont));tableCellStyle(cell1, new Color(237, 239, 240), null, null);//单元格对齐方式水平、垂直cell1.setFixedHeight(20);tableCellStyle(cell2, new Color(237, 239, 240), null, null);tableCellStyle(cell3, new Color(237, 239, 240), null, null);tableCellStyle(cell4, new Color(237, 239, 240), null, null);table.addCell(cell1);table.addCell(cell2);table.addCell(cell3);table.addCell(cell4);}}private void buildAuditResult(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核结论"));// 设置两列float[] widths = {20f, 80f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell("业务审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_bus"), 0, null, contentFont));table.addCell(createCenteredCell("研发审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_dev"), 0, null, contentFont));table.addCell(createCenteredCell("质量审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_obj"), 0, null, contentFont));table.addCell(createCenteredCell("数字化能力评估审核意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_qu"), 0, null, contentFont));table.addCell(createCenteredCell("综合意见:", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_conclusion_res"), 0, null, contentFont));document.add(table);}private void buildAuditData(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核方背景资料"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_information"), 0, null, contentFont));document.add(table);}private void buildAuditMethod(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核方法"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_method"), 0, null, contentFont));document.add(table);}private void buildAuditContent(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核内容"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_context"), 0, null, contentFont));document.add(table);}private void buildAuditRange(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核范围"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_scope"), 0, null, contentFont));document.add(table);}private void buildAuditType(Document document, DynamicObject data) throws DocumentException {// 设置标题document.add(createTitle("审核类型"));float[] widths = {2f, 8f, 2f, 8f, 2f, 8f, 70f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);PdfPCell cell = createCenteredCell("准入审核", 0, null, contentFont);PdfPCell cell2 = new PdfPCell();// 添加复选框绘制事件到单元格if ("0".equals(data.getString("eo45_report_type"))) {cell2.setCellEvent(new CheckBoxCellEvent());} else {cell2.setCellEvent(new CheckBoxCellNotEvent());}cell2.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell2.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell2.setBorder(Rectangle.NO_BORDER);table.addCell(cell2);table.addCell(cell);PdfPCell cell3 = createCenteredCell("年度审核", 0, null, contentFont);PdfPCell cell4 = new PdfPCell();// 添加复选框绘制事件到单元格if ("1".equals(data.getString("eo45_report_type"))) {cell4.setCellEvent(new CheckBoxCellEvent());} else {cell4.setCellEvent(new CheckBoxCellNotEvent());}cell4.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell4.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell4.setBorder(Rectangle.NO_BORDER);table.addCell(cell4);table.addCell(cell3);PdfPCell cell5 = createCenteredCell("跟踪审核", 0, null, contentFont);PdfPCell cell6 = new PdfPCell();// 添加复选框绘制事件到单元格if ("2".equals(data.getString("eo45_report_type"))) {cell6.setCellEvent(new CheckBoxCellEvent());} else {cell6.setCellEvent(new CheckBoxCellNotEvent());}cell6.setHorizontalAlignment(PdfPCell.ALIGN_RIGHT);cell6.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);cell6.setBorder(Rectangle.NO_BORDER);table.addCell(cell6);table.addCell(cell5);PdfPCell cell7 = new PdfPCell();cell7.setBorder(Rectangle.NO_BORDER);table.addCell(cell7);document.add(table);}private void buildAuditAim(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("审核目的"));PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(entryResults.getString("eo45_audit_purpose"), 0, null, contentFont));document.add(table);}private void buildBasicInformation(Document document, DynamicObject entryResults) throws DocumentException {// 设置标题document.add(createTitle("基本信息"));// 设置两列float[] widths = {17f, 83f};PdfPTable table = new PdfPTable(widths);// 段落在其上方留出的空间量table.setSpacingBefore(5f);// 设置表格宽度为100%table.setWidthPercentage(100.0F);table.addCell(createCenteredCell("审核对象", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_obj"), 0, null, contentFont));table.addCell(createCenteredCell("审核地址", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_addr"), 0, null, contentFont));table.addCell(createCenteredCell("审核日期", 15, null, contentFont));table.addCell(createCenteredCell(format.format(entryResults.getDate("eo45_audit_date")), 0, null, contentFont));table.addCell(createCenteredCell("审核人员", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_audit_person"), 0, null, contentFont));table.addCell(createCenteredCell("被审核方人员", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_beaudited_person"), 0, null, contentFont));table.addCell(createCenteredCell("本次审核后评级", 15, null, contentFont));table.addCell(createCenteredCell(entryResults.getString("eo45_score") + "级", 0, null, contentFont));document.add(table);}/*** 标题样式** @param value 标题* @return*/public PdfPTable createTitle(String value) {PdfPTable table = new PdfPTable(1);// 段落在其上方留出的空间量table.setSpacingBefore(5f);if ("基本信息".equals(value)) {table.setSpacingBefore(15f);}table.setWidthPercentage(100.0F);table.addCell(createCenteredCell(value, 20, new Color(242, 247, 255), titleFont));return table;}/*** 创建cell基本内容** @param value       值* @param fixedHeight 高度* @param color       背景色* @param font        字体样式* @return*/public PdfPCell createCenteredCell(String value, float fixedHeight, Color color, Font font) {Paragraph paragraph = new Paragraph(value, font);// paragraph.setLeading(10);PdfPCell cell = new PdfPCell(paragraph);// 水平对齐cell.setHorizontalAlignment(PdfPCell.ALIGN_LEFT);// 垂直对齐// cell.setVerticalAlignment(Element.ALIGN_MIDDLE);// 边框cell.setBorder(Rectangle.NO_BORDER);// 设置背景色if (color != null) {cell.setBackgroundColor(color);}// 设置单元格高度if (fixedHeight != 0) {cell.setFixedHeight(fixedHeight);}return cell;}/*** 表格表头** @param value* @param fixedHeight* @param color* @param font* @return*/private PdfPCell createCenteredCellForTable(String value, float fixedHeight, Color color, Font font, String border, String alignment) {PdfPCell cell = new PdfPCell(new Paragraph(value, font));cell.setHorizontalAlignment(Element.ALIGN_LEFT);if ("center".equals(alignment)) {cell.setHorizontalAlignment(Element.ALIGN_CENTER);}cell.setVerticalAlignment(Element.ALIGN_MIDDLE);cell.setBorderColor(new Color(230, 230, 230));if (border == null) {cell.setBorder(Rectangle.TOP | Rectangle.BOTTOM);}// 设置背景色if (color != null) {cell.setBackgroundColor(color);}// 设置单元格高度if (fixedHeight != 0) {cell.setFixedHeight(fixedHeight);}return cell;}/*** 设置单元格样式** @param cell*/private void tableCellStyle(PdfPCell cell, Color borderColor, Color backgroundColor, String border) {cell.setHorizontalAlignment(Element.ALIGN_LEFT);cell.setVerticalAlignment(Element.ALIGN_MIDDLE);// 只显示上下边框if (border == null) {cell.setBorder(Rectangle.TOP | Rectangle.BOTTOM);}// 边框颜色if (borderColor != null) {cell.setBorderColorTop(borderColor);cell.setBorderColorBottom(borderColor);}// 背景色if (backgroundColor != null) {cell.setBackgroundColor(backgroundColor);}cell.setBorderColor(new Color(230, 230, 230));}}​

 头部添加水印/图片工具类

package xcsy.zjy.webapi.utils;import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;import java.io.IOException;
import java.net.URL;/*** @program: xcsy-cosmic* @description: pdf添加头部水印图片* @author: lyw* @create: 2025-02-17 16:51**/public class AddImageToEachPageHeader extends PdfPageEventHelper {private static final Log log = LogFactory.getLog(AddImageToEachPageHeader.class);// 图片路径public static final String IMG = "img/logo.png";// 图片路径public static final String LINEIMG = "img/line.png";// 自定义页面事件监听器Image headerImage;Image lineImage;public AddImageToEachPageHeader() throws IOException, DocumentException {URL resourceUrl = AddImageToEachPageHeader.class.getClassLoader().getResource(IMG);assert resourceUrl != null;headerImage = Image.getInstance(resourceUrl);// scaleToFit按比例缩放图像、调整大小以适应您的需求headerImage.scaleToFit(50, 50);URL resourceUrl2 = AddImageToEachPageHeader.class.getClassLoader().getResource(LINEIMG);assert resourceUrl2 != null;lineImage = Image.getInstance(resourceUrl2);}@Overridepublic void onEndPage(PdfWriter writer, Document document) {try {// 计算图片1放置的位置// float x = (document.right() - document.left()) / 2 + document.leftMargin() - headerImage.getScaledWidth() / 2; // 居中float x = document.leftMargin();// 适当调整距离顶部的距离float y = document.top() + headerImage.getScaledHeight() + 10;headerImage.setAbsolutePosition(x, y);writer.getDirectContent().addImage(headerImage);// 图2// 获取页面宽度float pageWidth = document.getPageSize().getWidth();float x2 = 0;// 适当调整距离顶部的距离float y2 = document.top() + headerImage.getScaledHeight();// scaleAbsolute直接设置图像的确切宽度和高度,不考虑原始宽高比。lineImage.scaleAbsolute(pageWidth, 10);lineImage.setAbsolutePosition(x2, y2);writer.getDirectContent().addImage(lineImage);} catch (DocumentException e) {log.error("pdf添加头部水印图片DocumentException:{}", e);}}}

复选框(选中)绘制工具类

package xcsy.zjy.webapi.utils;import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;import java.awt.*;/*** @program: xcsy-cosmic* @description: pdf复选框* @author: lyw* @create: 2025-02-18 10:30**/public class CheckBoxCellEvent implements PdfPCellEvent {@Overridepublic void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];// 绘制复选框的位置和大小float x = position.getLeft() + 2; // X坐标,相对于单元格左下角float y = position.getBottom() + 2; // Y坐标,相对于单元格左下角float size = 10; // 复选框大小// 开始写入操作canvas.saveState();// 绘制复选框canvas.rectangle(x, y, size, size);canvas.setColorStroke(new Color( 190, 198, 205));canvas.stroke();// 确保勾选标记的起点、中点和终点位置合理,以形成一个清晰的√符号float rotatedMarkStartX = x + size - 2; // 原始markStartX关于x轴+size的对称点float rotatedMarkStartY = y + size - ((size / 2) - 2); // 原始markStartY关于y轴+size的对称点float rotatedMarkMidX = x + size - (size / 2); // 原始markMidX关于x轴+size的对称点float rotatedMarkMidY = y + 3; // 原始markMidY关于y轴+size的对称点float rotatedMarkEndX = x + 2; // 原始markEndX关于x轴+size的对称点float rotatedMarkEndY = y + size - 4; // 原始markEndY关于y轴+size的对称点canvas.moveTo(rotatedMarkStartX, rotatedMarkStartY); // 设置旋转后的起点canvas.lineTo(rotatedMarkMidX, rotatedMarkMidY); // 经过旋转后的中间点canvas.lineTo(rotatedMarkEndX, rotatedMarkEndY); // 结束于旋转后的右上角canvas.setColorStroke(new Color(0, 103, 255));canvas.setColorFill(new Color(0, 103, 255));canvas.stroke();// 结束写入操作canvas.restoreState();}
}

复选框(不选中)绘制工具类

package xcsy.zjy.webapi.utils;import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPCellEvent;
import com.lowagie.text.pdf.PdfPTable;import java.awt.*;/*** @program: xcsy-cosmic* @description: pdf复选框(不选中)* @author: lyw* @create: 2025-02-18 10:30**/public class CheckBoxCellNotEvent implements PdfPCellEvent {@Overridepublic void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];// 绘制复选框的位置和大小float x = position.getLeft() + 2; // X坐标,相对于单元格左下角float y = position.getBottom() + 2; // Y坐标,相对于单元格左下角float size = 10; // 复选框大小// 开始写入操作canvas.saveState();// 绘制复选框canvas.rectangle(x, y, size, size);canvas.setColorStroke(new Color( 190, 198, 205));canvas.stroke();// 结束写入操作canvas.restoreState();}
}

页码工具类

package xcsy.zjy.webapi.utils;import com.lowagie.text.*;
import com.lowagie.text.pdf.*;import java.io.IOException;/*** @Author xx* @Date 2023/12/15 10:05* @Description: 导出pdf添加页数* @Version 1.0*/
public class PdfPageUtil extends PdfPageEventHelper {/*** 页眉*///public String header = "itext测试页眉";/*** 文档字体大小,页脚页眉最好和文本大小一致*/public int presentFontSize = 9;/*** 文档页面大小,最好前面传入,否则默认为A4纸张*/public Rectangle pageSize = PageSize.A4;// 模板public PdfTemplate total;// 基础字体对象public BaseFont bf = null;// 利用基础字体生成的字体对象,一般用于生成中文文字public Font fontDetail = null;/****  无参构造方法.**/public PdfPageUtil() {}/****  构造方法.** @param** @param presentFontSize*            数据体字体大小* @param pageSize*            页面文档大小,A4,A5,A6横转翻转等Rectangle对象*/public PdfPageUtil( int presentFontSize, Rectangle pageSize) {this.presentFontSize = presentFontSize;this.pageSize = pageSize;}public void setPresentFontSize(int presentFontSize) {this.presentFontSize = presentFontSize;}/**** 文档打开时创建模板*/@Overridepublic void onOpenDocument(PdfWriter writer, Document document) {// 共 页 的矩形的长宽高total = writer.getDirectContent().createTemplate(50, 50);}/****关闭每页的时候,写入页眉,写入'第几页共'这几个字。*/@Overridepublic void onEndPage(PdfWriter writer, Document document) {this.addPage(writer, document);}//加分页public void addPage(PdfWriter writer, Document document){//设置分页页眉页脚字体try {if (bf == null) {bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);}if (fontDetail == null) {fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体}} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}// 1.写入页眉
//        ColumnText.showTextAligned(writer.getDirectContent(),
//                Element.ALIGN_LEFT, new Phrase(header, fontDetail),
//                document.left(), document.top() + 20, 0);// 2.写入前半部分的 第 X页/共int pageS = writer.getPageNumber();//String foot1 = "第 " + pageS + " 页 /共";String foot1 = pageS  +"/";Phrase footer = new Phrase(foot1, fontDetail);// 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = lenfloat len = bf.getWidthPoint(foot1, presentFontSize);// 4.拿到当前的PdfContentBytePdfContentByte cb = writer.getDirectContent();// 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0FColumnText.showTextAligned(cb,Element.ALIGN_CENTER,footer,(document.rightMargin() + document.right()+ document.leftMargin() - document.left() - len) / 2.0F ,document.bottom() - 10, 0);cb.addTemplate(total, (document.rightMargin() + document.right()+ document.leftMargin() - document.left()) / 2.0F ,document.bottom() - 10); // 调节模版显示的位置}//    //加水印
//    public void addWatermark(PdfWriter writer){
//        // 水印图片
//        Image image;
//        try {
//            image = Image.getInstance("./web/images/001.jpg");
//            PdfContentByte content = writer.getDirectContentUnder();
//            content.beginText();
//            // 开始写入水印
//            for(int k=0;k<5;k++){
//                for (int j = 0; j <4; j++) {
//                    image.setAbsolutePosition(150*j,170*k);
//                    content.addImage(image);
//                }
//            }
//            content.endText();
//        } catch (IOException | DocumentException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
//    }/**** 关闭文档时,替换模板,完成整个页眉页脚组件*/@Overridepublic void onCloseDocument(PdfWriter writer, Document document) {// 关闭文档的时候,将模板替换成实际的 Y 值total.beginText();// 生成的模版的字体、颜色total.setFontAndSize(bf, presentFontSize);//页脚内容拼接  如  第1页/共2页//String foot2 = " " + (writer.getPageNumber()) + " 页";//页脚内容拼接  如  第1页/共2页String foot2 = String.valueOf(writer.getPageNumber() - 1);// 模版显示的内容total.showText(foot2);total.endText();total.closePath();}
}

最后大致效果图

静态图片文件存放位置项目下:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词