package com.brilliance.utils; import com.brilliance.bo.Receipt; import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.Loader; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.TextPosition; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.*; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType0Font; @Slf4j public class ReceiptXY { public static void main(String[] args) { // 创建一个Date对象,表示当前日期和时间 Date now = new Date(); // 创建一个SimpleDateFormat对象,并定义日期格式 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); // 使用format方法格式化日期 String formattedDate = dateFormat.format(now); String str = new Date().getTime() + ""; String id = formattedDate + str.substring(str.length() - 8); String pdfFilePath = ".\\src\\main\\resources\\doc\\receipt2.pdf"; String targetText = "户名"; String outputFilePath = "C:\\Users\\zhaojg\\.m2\\repository\\cn\\output" + id + ".pdf"; String fontPath = ".\\src\\main\\resources\\doc\\Fsong.ttf"; log.info("targetText:" + targetText.length()); List<String> textBehind = new ArrayList<>(); textBehind.add("银" + (char) 12175); textBehind.add("数字凭证编号"); textBehind.add("凭证编号"); textBehind.add("账号"); textBehind.add("户名"); textBehind.add("⾦额 (⼤、小写)"); textBehind.add("备案状态"); textBehind.add("备案编号"); List<String> text = new ArrayList<>(); text.add("银" + (char) 12175); text.add("数字凭证编号"); text.add("凭证编号"); text.add("账号"); text.add("户名"); text.add("⾦额 (⼤、小写)"); text.add("备案状态"); text.add("备案编号"); text.add("购买日期"); text.add("起息日期"); text.add("印密"); text.add("年度"); text.add("期次"); text.add("期限"); text.add("年利率"); text.add("到期日期"); text.add("柜员号"); text.add("兑取日期"); text.add("计息天数"); text.add("利息"); Receipt receipt = new Receipt(); receipt.setReceiptNum(id); receipt.setReceiptNo(id + "123"); receipt.setBankName("中国人民"); receipt.setBuyDate("2022/3/12"); receipt.setStartDate("2022/3/12"); receipt.setSeal("印密"); receipt.setYear("2022"); receipt.setPeriod("01"); receipt.setDeadline("三年"); receipt.setRate("3.45%"); receipt.setEndDate("2025/3/12"); receipt.setTellerNum("9527"); receipt.setAccountNum("130503196701010001"); receipt.setAccountName("张三"); receipt.setMoney("人民币壹百万元整 RMB1,000,000.00"); receipt.setRedemptionDate("2023/3/12"); receipt.setInterestAccDays("365"); receipt.setInterest("34500"); receipt.setRate2("3.67%"); receipt.setTellerNum2("9528"); receipt.setOperator("经办员"); receipt.setStatus("有效"); receipt.setRecordNum("NO." + id); // 准备数据 Map<String, String> data = new HashMap<>(); data.put("receiptNum", receipt.receiptNum); data.put("receiptNo", receipt.receiptNo); data.put("bankName", receipt.bankName); data.put("buyDate", receipt.buyDate); data.put("startDate", receipt.startDate); data.put("seal", receipt.seal); data.put("year", receipt.year); data.put("period", receipt.period); data.put("deadline", receipt.deadline); data.put("rate", receipt.rate); data.put("endDate", receipt.endDate); data.put("tellerNum", receipt.tellerNum); data.put("accountNum", receipt.accountNum); data.put("accountName", receipt.accountName); data.put("money", receipt.money); data.put("redemptionDate", receipt.redemptionDate); data.put("interestAccDays", receipt.interestAccDays); data.put("interest", receipt.interest); data.put("rate2", receipt.rate2); data.put("tellerNum2", receipt.tellerNum2); data.put("operator", receipt.operator); data.put("status", receipt.status); data.put("recordNum", receipt.recordNum); getTextLocations(pdfFilePath, outputFilePath, fontPath, textBehind, data, text); } public static void getTextLocations(String pdfFilePath, String outputFilePath, String fontPath, List<String> textBehind, Map<String, String> data, List<String> text) { try { PDDocument document = Loader.loadPDF(new File(pdfFilePath)); List<Float> fontSize = new ArrayList<>(); List<TextLocation> textLocations = new ArrayList<>(); // 移除所有安全限制 document.setAllSecurityToBeRemoved(true); // 获取第一页 PDPage page = document.getPage(0); PDRectangle pageSize = page.getMediaBox(); // 加载中文字体(如果需要) // 注意:这里的字体路径需要替换为你自己的中文字体文件路径 PDType0Font chineseFont = PDType0Font.load(document, new File(fontPath)); //PDType0Font.SimSun; // 使用PDFBox默认字体(如果需要中文,请取消上面中文字体的注释,并使用chineseFont) //PDType1Font font = PDType1Font.HELVETICA_BOLD; //加载文本 for (String str : text) { setOnlyTextBehind(document, str, fontPath, fontSize, data, textBehind, textLocations, pageSize, chineseFont, page); } // 保存并关闭文档 document.save(outputFilePath); document.close(); } catch (IOException e) { e.printStackTrace(); } } public static void setOnlyTextBehind(PDDocument document, String targetText, String fontPath, List<Float> fontSize, Map<String, String> data, List<String> textBehind, List<TextLocation> textLocations, PDRectangle pageSize, PDType0Font chineseFont, PDPage page) throws IOException { textLocations.clear(); fontSize.clear(); PDFTextStripper stripper = new PDFTextStripper() { @Override protected void writeString(String text, List<TextPosition> textPositions) throws IOException { if (text.contains(targetText)) { for (TextPosition position : textPositions) { TextLocation location = new TextLocation(text, position.getXDirAdj(), position.getYDirAdj()); textLocations.add(location); log.info("text:" + text + " X:" + position.getXDirAdj() + " Y:" + position.getYDirAdj()); float size = position.getFontSizeInPt(); log.info("size+++++" + size); fontSize.add(position.getFontSizeInPt()); } } super.writeString(text, textPositions); } }; stripper.getText(document); // 创建内容流 try (PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true)) { // 设置字体和大小 contentStream.setFont(chineseFont, fontSize.get(0)); // 计算居中偏移 String text = data.get(ReceiptConstant.getName(targetText)); float fontwidth = chineseFont.getStringWidth(text) * 14 / 1000f; log.info("fontwidth:" + fontwidth); float x; float y; if (textBehind.contains(targetText)) { // 指定文本位置(坐标) if (("银" + (char) 12175).equals(targetText)) { x = textLocations.get(0).getX() - fontwidth - fontSize.get(0); y = pageSize.getUpperRightY() - textLocations.get(targetText.length() - 1).getY(); // 注意:PDF的坐标系是左下角为原点,Y轴向上 } else { x = textLocations.get(targetText.length() - 1).getX() + fontSize.get(0) * 2; y = pageSize.getUpperRightY() - textLocations.get(targetText.length() - 1).getY(); // 注意:PDF的坐标系是左下角为原点,Y轴向上 } } else { if ("柜员号".equals(targetText) || "年利率".equals(targetText)) { x = textLocations.get(targetText.length()).getX(); y = pageSize.getUpperRightY() - textLocations.get(textLocations.size() - 1).getY() - fontSize.get(0) * 2; text = data.get(ReceiptConstant.getName(targetText + "2")); // 添加文本 contentStream.beginText(); contentStream.newLineAtOffset(x, y); // 如果需要中文,请使用chineseFont并取消下面这行代码的注释,使用showText添加中文文本 contentStream.showText(text); //contentStream.showText("Hello, PDFBox!"); contentStream.endText(); x = textLocations.get(0).getX(); y = pageSize.getUpperRightY() - textLocations.get(targetText.length() - 1).getY() - fontSize.get(0) * 2; text = data.get(ReceiptConstant.getName(targetText)); } else { x = textLocations.get(0).getX(); y = pageSize.getUpperRightY() - textLocations.get(targetText.length() - 1).getY() - fontSize.get(0) * 2; } } // 添加文本 contentStream.beginText(); contentStream.newLineAtOffset(x, y); // 如果需要中文,请使用chineseFont并取消下面这行代码的注释,使用showText添加中文文本 contentStream.showText(text); //contentStream.showText("Hello, PDFBox!"); contentStream.endText(); contentStream.close(); } catch (IOException e) { e.printStackTrace(); } } }