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();}
}

最后大致效果圖

靜態圖片文件存放位置項目下:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/70718.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/70718.shtml
英文地址,請注明出處:http://en.pswp.cn/web/70718.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

3-2 WPS JS宏 工作簿的打開與保存(模板批量另存為工作)學習筆記

************************************************************************************************************** 點擊進入 -我要自學網-國內領先的專業視頻教程學習網站 *******************************************************************************************…

Ubuntu20.04之VNC的安裝使用與常見問題

Ubuntu20.04之VNC的安裝與使用 安裝圖形桌面選擇安裝gnome桌面選擇安裝xface桌面 VNC-Server安裝配置開機自啟 VNC Clientroot用戶無法登入問題臨時方案永久方案 安裝圖形桌面 Ubuntu20.04主流的圖形桌面有gnome和xface兩種&#xff0c;兩種桌面的安裝方式我都會寫&#xff0c…

Day46 反轉字符串

I. 編寫一個函數&#xff0c;其作用是將輸入的字符串反轉過來。輸入字符串以字符數組 s 的形式給出。 不要給另外的數組分配額外的空間&#xff0c;你必須原地修改輸入數組、使用 O(1) 的額外空間解決這一問題。 class Solution {public void reverseString(char[] s) {int i …

用FileZilla Server 1.9.4給Windows Server 2025搭建FTP服務端

FileZilla Server 是一款免費的開源 FTP 和 FTPS 服務器軟件&#xff0c;分為服務器版和客戶端版。服務器版原本只支持Windows操作系統&#xff0c;比如筆者曾長期使用過0.9.60版&#xff0c;那時候就只支持Windows操作系統。當時我們生產環境對FTP穩定性要求較高&#xff0c;比…

【愚公系列】《Python網絡爬蟲從入門到精通》033-DataFrame的數據排序

標題詳情作者簡介愚公搬代碼頭銜華為云特約編輯,華為云云享專家,華為開發者專家,華為產品云測專家,CSDN博客專家,CSDN商業化專家,阿里云專家博主,阿里云簽約作者,騰訊云優秀博主,騰訊云內容共創官,掘金優秀博主,亞馬遜技領云博主,51CTO博客專家等。近期榮譽2022年度…

營銷過程烏龜圖模版

營銷過程烏龜圖模版 輸入 公司現狀產品服務客戶問詢客戶期望電話、電腦系統品牌軟件硬件材料 售前 - 溝通 - 確定需求 - 滿足需求 - 售后 機料環 電話、電腦等設備軟件硬件、系統品牌等工具材料 人 責任人協助者生產者客戶 法 訂單由誰評審控制程序營銷過程控制程序顧客滿意度…

Kubernetes (K8S) 高效使用技巧與實踐指南

Kubernetes&#xff08;K8S&#xff09;作為容器編排領域的核心工具&#xff0c;其靈活性和復雜性并存。本文結合實戰經驗&#xff0c;從運維效率提升、生產環境避坑、核心功能應用等維度&#xff0c;總結高頻使用技巧與最佳實踐&#xff0c;分享如何快速掌握 K8S。 一、kubect…

Idea java項目結構介紹

一般來說&#xff0c;一個典型的 IntelliJ IDEA Java 項目具有特定的結構&#xff0c;以下是對其主要部分的介紹&#xff1a; 項目根目錄 項目的最頂層目錄&#xff0c;包含了整個項目的所有文件和文件夾&#xff0c;通常以項目名稱命名。在這個目錄下可以找到.idea文件夾、.g…

C++大整數類的設計與實現

1. 簡介 我們知道現代的計算機大多數都是64位的&#xff0c;因此能處理最大整數為 2 64 ? 1 2^{64}-1 264?1。那如果是超過了這個數怎么辦呢&#xff0c;那就需要我們自己手動模擬數的加減乘除了。 2. 思路 我們可以用一個數組來存儲大數&#xff0c;數組中的每一個位置表…

2024年第十五屆藍橋杯大賽軟件賽省賽Python大學A組真題解析

文章目錄 試題A: 拼正方形(本題總分:5 分)解析答案試題B: 召喚數學精靈(本題總分:5 分)解析答案試題C: 數字詩意解析答案試題A: 拼正方形(本題總分:5 分) 【問題描述】 小藍正在玩拼圖游戲,他有7385137888721 個2 2 的方塊和10470245 個1 1 的方塊,他需要從中挑出一些…

開源RAG主流框架有哪些?如何選型?

開源RAG主流框架有哪些?如何選型? 一、開源RAG框架全景圖 (一)核心框架類型對比 類型典型工具技術特征適用場景傳統RAGLangChain, Haystack線性流程(檢索→生成)通用問答、知識庫檢索增強型RAGRAGFlow, AutoRAG支持重排序、多路召回優化高精度問答、復雜文檔處理輕量級…

Java SE與Java EE

Java SE&#xff08;Java 平臺標準版&#xff09; Java SE 是 Java 平臺的核心&#xff0c;提供了 Java 語言的基礎功能。它包含了 Java 開發工具包&#xff08;JDK&#xff09;&#xff0c;其中有 Java 編譯器&#xff08;javac&#xff09;、Java 虛擬機&#xff08;JVM&…

【Java企業生態系統的演進】從單體J2EE到云原生微服務

Java企業生態系統的演進&#xff1a;從單體J2EE到云原生微服務 目錄標題 Java企業生態系統的演進&#xff1a;從單體J2EE到云原生微服務摘要1. 引言2. 整體框架演進&#xff1a;從原始Java到Spring Cloud2.1 原始Java階段&#xff08;1995-1999&#xff09;2.2 J2EE階段&#x…

kicad中R樹的使用

在 KiCad 中&#xff0c;使用 R樹&#xff08;R-tree&#xff09;進行空間索引和加速查詢通常不在用戶層面直接操作&#xff0c;而是作為工具的一部分用于優化電路板設計的性能&#xff0c;尤其在布局、碰撞檢測、設計規則檢查&#xff08;DRC&#xff09;以及元件搜索等方面。…

org.springframework.boot不存在的其中一個解決辦法

最近做項目的時候發現問題&#xff0c;改了幾次pom.xml文件之后突然發現項目中的注解全部爆紅。 可以嘗試點擊左上角的循環小圖標&#xff0c;同步所有maven項目。 建議順便檢查一下Project Structure中的SDK和Language Level是否對應&#xff0c;否則可能報類似&#xff1a;“…

C語言實現通訊錄項目

一、通訊錄功能 實現一個可以存放100個人的信息的通訊錄&#xff08;這里采用靜態版本&#xff09;&#xff0c;每個人的信息有姓名、性別、年齡、電話、地址等。 通訊錄可以執行的操作有添加聯系人信息、刪除指定聯系人、查找指定聯系人信息、修改指定聯系人信息、顯示聯系人信…

HO3D_v3(handposeX-json 格式)數據集-release >> DataBall

注意&#xff1a; 1)為了方便使用&#xff0c;按照 handposeX json 自定義格式存儲 2)使用常見依賴庫進行調用,降低數據集使用難度。 3)部分數據集獲取請加入&#xff1a;DataBall-X數據球(free) 4)完整數據集獲取請加入&#xff1a;DataBall-X數據球(vip) HO3D 數據集官方…

Java線程池入門04

1. 提交任務的兩種方式 executorsubmit 2. executor executor位于Executor接口中 public interface Executor {void executor(Runnable command); }executor提交的是無返回值的任務 下面是一個具體的例子 package LearnThreadPool; import java.util.concurrent.ExecutorSe…

2025-02-26 學習記錄--C/C++-C語言 整數格式說明符

合抱之木&#xff0c;生于毫末&#xff1b;九層之臺&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; C語言 整數格式說明符 【例如 】&#x1f380; &#xff1a;在 C 語言中&#xff0c;%ld 是 printf 或 scanf 等格式化輸入輸出函…

【QT 一 | 信號和槽】

Qt5基本模塊 Qt Creator 中的快捷鍵 ? 注釋&#xff1a;ctrl / ? 運?&#xff1a;ctrl R ? 編譯&#xff1a;ctrl B ? 字體縮放&#xff1a;ctrl 鼠標滑輪 ? 查找&#xff1a;ctrl F ? 整行移動&#xff1a;ctrl shift ?/? ? 幫助?檔&#xff1a;F1 ? 自動…