当前位置: 首页 > wzjs >正文

德州做网站网站在线建设方案

德州做网站,网站在线建设方案,wordpress网站怎么打开,全网营销系统是不是传销目录实现效果引言技术要点实现步骤1. 环境准备2. 代码实现2.1 左上角添加 logo2.2 添加可见标题2.3 基础单据信息2.4 动态表格渲染2.5 二维码区域2.6 添加水印2.7 辅助类和数据3. 开发中的调整经验4. 运行与测试注意事项总结引言技术要点实现步骤 1. 环境准备2. 代码实现 2.1 左…

目录

  • 实现效果
    • 引言
    • 技术要点
    • 实现步骤
      • 1. 环境准备
      • 2. 代码实现
        • 2.1 左上角添加 logo
        • 2.2 添加可见标题
        • 2.3 基础单据信息
        • 2.4 动态表格渲染
        • 2.5 二维码区域
        • 2.6 添加水印
        • 2.7 辅助类和数据
      • 3. 开发中的调整经验
      • 4. 运行与测试
      • 注意事项
    • 总结

  • 引言
  • 技术要点
  • 实现步骤
    • 1. 环境准备
    • 2. 代码实现
      • 2.1 左上角添加 logo
      • 2.2 添加可见标题
      • 2.3 基础单据信息
      • 2.4 动态表格渲染
      • 2.5 二维码区域
      • 2.6 添加水印
      • 2.7 辅助类和数据
    • 3. 开发中的调整经验
    • 4. 运行与测试
  • 总结

实现效果

在这里插入图片描述

引言

在企业开发中,动态生成 PDF(如出库单、发票)是常见需求。传统方法依赖模板,灵活性不足。本文将展示如何使用 Java 17 结合 iTextPDF 和 ZXing 库,实现在无模版情况下动态生成 PDF,嵌入 logo、渲染动态表格并添加二维码和水印。文章提供完整 demo 代码和开发经验分享。

技术要点

  1. 无模版生成:无需预设模板,纯代码构建。
  2. 图片嵌入:添加 logo 等图像。
  3. 动态表格渲染:根据数据动态生成多列表格。
  4. Java 17 环境:使用现代 Java 版本。
  5. 依赖管理:通过 Maven 配置 iTextPDF 和 ZXing。

实现步骤

1. 环境准备

使用 Java 17,依赖通过 Maven 管理。以下是 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>untitled</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><groupId>com.itextpdf.tool</groupId><artifactId>xmlworker</artifactId><version>5.5.13.3</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.3.0</version></dependency></dependencies>
</project>

运行 mvn clean install 安装依赖。

2. 代码实现

2.1 左上角添加 logo

添加 logo 图片到 PDF 左上角:

    private static void addLogo(Document document, PdfWriter writer) throws DocumentException, IOException {// 替换为实际 logo 图片路径,例如 "src/main/resources/logo.jpeg"Image logo = Image.getInstance("src/main/resources/logo.jpeg");logo.scaleToFit(100, 100); // 调整 logo 大小logo.setAlignment(Image.ALIGN_LEFT);document.add(logo); // 使用文档流插入}

在这里插入图片描述

	好吧,其实并不是这样的logo,往下慢慢看吧。
2.2 添加可见标题

在文档顶部添加居中标题:

    private static void addDocumentTitle(Document document) throws DocumentException, IOException {BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font titleFont = new Font(bfChinese, 20, Font.BOLD);Paragraph title = new Paragraph("出库单", titleFont);title.setAlignment(Element.ALIGN_CENTER);
//        title.setSpacingBefore(5f);
//        title.setSpacingAfter(5f);document.add(title);}
2.3 基础单据信息

使用 4 列表格展示基础信息,动态从 API 数据填充:

// 添加基础单据信息 (4列布局,增加间距)
private static void addBasicInfo(Document document) throws DocumentException, IOException {PdfPTable table = new PdfPTable(4);table.setWidthPercentage(100);table.setSpacingBefore(150f);table.setSpacingAfter(50f);BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font headerFont = new Font(bfChinese, 14, Font.BOLD);Font contentFont = new Font(bfChinese, 14);Map<String, String> apiData = getBaseInfoFromApi();List<String> keys = new ArrayList<>(fieldNameToLabelMap.keySet());for (int i = 0; i < keys.size(); i += 2) {String key1 = keys.get(i);String key2 = (i + 1 < keys.size()) ? keys.get(i + 1) : "";String label1 = fieldNameToLabelMap.get(key1);String value1 = apiData.getOrDefault(key1, "");String label2 = key2.isEmpty() ? "" : fieldNameToLabelMap.get(key2);String value2 = key2.isEmpty() ? "" : apiData.getOrDefault(key2, "");addInfoRow(table, label1, value1, label2, value2, headerFont, contentFont);}document.add(table);
}// 工具方法:添加单行 (4列)
private static void addInfoRow(PdfPTable table, String key1, String value1, String key2, String value2, Font keyFont, Font valueFont) {PdfPCell keyCell1 = new PdfPCell(new Phrase(key1, keyFont));keyCell1.setHorizontalAlignment(Element.ALIGN_LEFT);keyCell1.setBorderWidth(0.5f);keyCell1.setPadding(10f);keyCell1.setMinimumHeight(25f);PdfPCell valueCell1 = new PdfPCell(new Phrase(value1, valueFont));valueCell1.setHorizontalAlignment(Element.ALIGN_LEFT);valueCell1.setBorderWidth(0.5f);valueCell1.setPadding(10f);valueCell1.setMinimumHeight(25f);PdfPCell keyCell2 = new PdfPCell(new Phrase(key2, keyFont));keyCell2.setHorizontalAlignment(Element.ALIGN_LEFT);keyCell2.setBorderWidth(0.5f);keyCell2.setPadding(10f);keyCell2.setMinimumHeight(25f);PdfPCell valueCell2 = new PdfPCell(new Phrase(value2, valueFont));valueCell2.setHorizontalAlignment(Element.ALIGN_LEFT);valueCell2.setBorderWidth(0.5f);valueCell2.setPadding(10f);valueCell2.setMinimumHeight(25f);table.addCell(keyCell1);table.addCell(valueCell1);table.addCell(keyCell2);table.addCell(valueCell2);
}
2.4 动态表格渲染

动态生成出库单明细表格:

private static void addOutboundDetails(Document document) throws DocumentException, IOException {// 模拟从接口获取的动态数据List<OutboundDetail> details = generateSampleDetails();// 创建表格 (7列: 序号, 订单号, 订单明细号, 产品名称, 单位, 数量, 单价)PdfPTable table = new PdfPTable(7);table.setWidthPercentage(100);table.setSpacingBefore(50f); // 增加间距,向下移动以避免被上部内容覆盖// 使用支持中文的字体BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);Font headerFont = new Font(bfChinese, 12, Font.BOLD);Font contentFont = new Font(bfChinese, 12);// 表头addTableHeader(table, headerFont);// 动态添加数据for (int i = 0; i < details.size(); i++) {OutboundDetail detail = details.get(i);table.addCell(createCell(String.valueOf(i + 1), contentFont));table.addCell(createCell(detail.getOrderId(), contentFont));table.addCell(createCell(detail.getDetailId(), contentFont));table.addCell(createCell(detail.getProductName(), contentFont));table.addCell(createCell(detail.getUnit(), contentFont));table.addCell(createCell(String.valueOf(detail.getQuantity()), contentFont));table.addCell(createCell(String.format("%.2f", detail.getUnitPrice()), contentFont));}document.add(table);}// 添加表格表头private static void addTableHeader(PdfPTable table, Font font) {String[] headers = {"序号", "订单号", "订单明细号", "产品名称", "单位", "数量", "单价"};for (String header : headers) {PdfPCell cell = new PdfPCell(new Phrase(header, font));cell.setHorizontalAlignment(Element.ALIGN_CENTER);cell.setBackgroundColor(BaseColor.LIGHT_GRAY);cell.setMinimumHeight(25f);table.addCell(cell);}}// 创建单元格private static PdfPCell createCell(String content, Font font) {PdfPCell cell = new PdfPCell(new Phrase(content, font));cell.setHorizontalAlignment(Element.ALIGN_CENTER);cell.setBorderWidth(0.5f);cell.setMinimumHeight(25f);cell.setPadding(8f);return cell;}
2.5 二维码区域

在右上角添加二维码:

private static void addQRCodePlaceholder(Document document, PdfWriter writer) throws DocumentException {try {// 获取第一个订单信息作为二维码内容List<OutboundDetail> details = generateSampleDetails();if (!details.isEmpty()) {OutboundDetail detail = details.get(0);String qrContent = "OrderID: " + detail.getOrderId() + "\nUnitPrice: " + detail.getUnitPrice() +"\nQuantity: " + detail.getQuantity() + "\nDate: 2025-07-10";// 生成二维码图像int size = 100;BitMatrix bitMatrix = new MultiFormatWriter().encode(qrContent, BarcodeFormat.QR_CODE, size, size);ByteArrayOutputStream baos = new ByteArrayOutputStream();MatrixToImageWriter.writeToStream(bitMatrix, "png", baos);Image qrImage = Image.getInstance(baos.toByteArray());qrImage.scaleToFit(size, size);// 设置二维码位置 —— 保持原有位置float x = PageSize.A4.getWidth() - size - 10f;float y = PageSize.A4.getHeight() - qrImage.getScaledHeight() - 10f;qrImage.setAbsolutePosition(x, y);writer.getDirectContent().addImage(qrImage);} else {Paragraph qr = new Paragraph();qr.add(new Chunk("二维码区域 (无数据)\n", FontFactory.getFont(FontFactory.HELVETICA, 14, Font.BOLD)));qr.setAlignment(Element.ALIGN_RIGHT);document.add(qr);}} catch (Exception e) {e.printStackTrace();Paragraph qr = new Paragraph();qr.add(new Chunk("二维码区域 (生成失败)\n", FontFactory.getFont(FontFactory.HELVETICA, 14, Font.BOLD)));qr.setAlignment(Element.ALIGN_RIGHT);document.add(qr);}}
2.6 添加水印

在 PDF 背景添加倾斜水印:

private static void addTextWatermark(PdfWriter writer, String watermarkText) throws IOException, DocumentException {PdfContentByte under = writer.getDirectContentUnder();// 设置字体BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);under.saveState();// 设置透明度PdfGState gs1 = new PdfGState();gs1.setFillOpacity(0.1f); // 越小越淡under.setGState(gs1);// 设置字体大小和颜色under.beginText();under.setFontAndSize(baseFont, 60); // 字体大小under.setColorFill(BaseColor.LIGHT_GRAY);// 页面宽高float pageWidth = PageSize.A4.getWidth();float pageHeight = PageSize.A4.getHeight();// 网格循环:每隔一定间距绘制一行水印(x 横向,y 纵向)for (float x = -100; x < pageWidth + 100; x += 200) {for (float y = -100; y < pageHeight + 100; y += 150) {under.showTextAligned(Element.ALIGN_CENTER, watermarkText, x, y, 45); // 倾斜 45 度}}under.endText();under.restoreState();}}
2.7 辅助类和数据

数据模型和模拟 API 数据,包括 fieldNameToLabelMap 初始化:

static class OutboundDetail {private String orderId;private String detailId;private String productName;private String unit;private double quantity;private double unitPrice;public OutboundDetail(String orderId, String detailId, String productName, String unit, double quantity, double unitPrice) {this.orderId = orderId;this.detailId = detailId;this.productName = productName;this.unit = unit;this.quantity = quantity;this.unitPrice = unitPrice;}public String getOrderId() { return orderId; }public String getDetailId() { return detailId; }public String getProductName() { return productName; }public String getUnit() { return unit; }public double getQuantity() { return quantity; }public double getUnitPrice() { return unitPrice; }
}private static final Map<String, String> fieldNameToLabelMap = new LinkedHashMap<>();static {fieldNameToLabelMap.put("orderCode", "单据编号");fieldNameToLabelMap.put("outboundDate", "出库日期");fieldNameToLabelMap.put("customerName", "客户名称");fieldNameToLabelMap.put("warehouseCode", "仓库编号");fieldNameToLabelMap.put("creator", "制单人");fieldNameToLabelMap.put("auditor", "审核人");fieldNameToLabelMap.put("createTime", "制单时间");fieldNameToLabelMap.put("outboundOrderId", "出库单据ID");
}private static Map<String, String> getBaseInfoFromApi() {Map<String, String> data = new HashMap<>();data.put("orderCode", "BF-03-05-1");data.put("outboundDate", "2025-06-04");data.put("customerName", "某某公司");data.put("warehouseCode", "CK_7525080416537318");data.put("creator", "张三");data.put("auditor", "李四");data.put("createTime", "2025-06-04 16:15:48");data.put("outboundOrderId", "13500135000");return data;
}private static List<OutboundDetail> generateSampleDetails() {List<OutboundDetail> details = new ArrayList<>();details.add(new OutboundDetail("BF-03-05-1", "no1", "34CrNiMo6", "原材料", 6.60, 100.00));details.add(new OutboundDetail("BF-03-05-2", "no2", "35CrMo", "半成品", 5.5, 120.00));details.add(new OutboundDetail("BF-03-05-3", "no3", "Q235", "成品", 10.0, 80.00));return details;
}public static void main(String[] args) {try {Document document = new Document(PageSize.A4);PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("outbound_document.pdf"));document.open();addLogo(document, writer);addDocumentTitle(document);addBasicInfo(document);addOutboundDetails(document);addQRCodePlaceholder(document, writer);addTextWatermark(writer, "ikun");document.close();System.out.println("PDF 生成成功!文件位置: outbound_document.pdf");} catch (Exception e) {e.printStackTrace();}
}

3. 开发中的调整经验

开发初期,我将二维码位置使用 setAbsolutePosition 固定在右上角(例如 x = PageSize.A4.getWidth() - 100f, y = PageSize.A4.getHeight() - 100f),导致基础信息表格始终被覆盖。问题出在绝对定位与文档流冲突上。调整过程:

  • 增加间距:将 addBasicInfo 中的 setSpacingBefore 从 50f 调整到 150f,确保表格向下移动。
  • 动态布局:改为使用 document.add() 添加元素,避免固定位置重叠。
  • 调试优化:通过生成 PDF 逐一检查布局,逐步调整 setSpacingBefore 值(例如增至 100f 或 150f),确保内容可见。

4. 运行与测试

  • logo.jpeg 放入 src/main/resources/ 目录。
  • 运行 main 方法,生成 outbound_document.pdf
  • 检查 PDF 是否包含 logo、标题、基础信息表格、动态表格、二维码和水印。

注意事项

  • 图片路径:确保 logo.jpeg 路径正确。
  • 字体支持:依赖 itext-asian,若字体加载失败,可替换为本地字体(如 SimSun.ttf)。
  • 依赖冲突:若版本冲突,调整 pom.xml 中的依赖版本。
    在这里插入图片描述

总结

本文通过 Java 17 实现了无模版动态生成 PDF,结合 iTextPDF 嵌入图片和渲染动态表格,ZXing 生成二维码,并添加水印。完整 demo 代码提供参考,开发中通过调整间距解决了布局冲突问题。欢迎评论区交流优化建议!

作者:@Brain

demo:代码请见gitee



文章转载自:

http://pOA1z5xw.mhsmj.cn
http://6NKBsaT7.mhsmj.cn
http://xh5tHwqT.mhsmj.cn
http://rtJAI8VP.mhsmj.cn
http://qyxCvLxJ.mhsmj.cn
http://uk23XFCy.mhsmj.cn
http://TcQTpGqg.mhsmj.cn
http://NjLTUQpk.mhsmj.cn
http://aL5bGfPn.mhsmj.cn
http://VR0tiH8D.mhsmj.cn
http://Jq1SL3ar.mhsmj.cn
http://oxtE2GOT.mhsmj.cn
http://LwN43B2c.mhsmj.cn
http://phBb1FTC.mhsmj.cn
http://IHxfEFHm.mhsmj.cn
http://GKvZi7aG.mhsmj.cn
http://Yr1jMQZk.mhsmj.cn
http://52NDNUKL.mhsmj.cn
http://DWU8XC90.mhsmj.cn
http://yPZDVKoE.mhsmj.cn
http://rLgeQXz3.mhsmj.cn
http://cKFWXn92.mhsmj.cn
http://NXcPTtla.mhsmj.cn
http://4CDCalPE.mhsmj.cn
http://tCy6hfhs.mhsmj.cn
http://f5wHakzm.mhsmj.cn
http://vvP1yx9Z.mhsmj.cn
http://osfAVn8J.mhsmj.cn
http://JpFqvIQr.mhsmj.cn
http://w3AOEe5I.mhsmj.cn
http://www.dtcms.com/wzjs/732839.html

相关文章:

  • 泰安网站建设如何中低端网站建设客户网
  • 网站上传模板后商业网站域名后缀
  • 学校网站建设的作用公司测名网
  • 汕头多语种网站制作怎么做查询数据输入的网站
  • 工业和信息化部网站备案查询广告设计app免费
  • 做网站的字体大小有没有类似wordpress
  • 河间做网站的公司电子硬件工程师培训机构
  • 最新免费网站源码资源网站人工智能网站应怎么做
  • phpcms 怎么做视频网站怎么选择郑州网站建设
  • 制作链接的小程序怎么看网站做没做seo
  • 内存做硬盘缓存软件网站建立充电站需要多少钱
  • 自己切片视频做网站网站备案资质
  • 广州站西手表公司简介50字
  • 站酷设计网页版怎么开发自己的商城
  • 网站制作顺序网站怎么做微信接口
  • 网站开发公司有哪些网站开发要注意安全性
  • 东莞东城做网站公司快速建设企业门户网站
  • python做网站的案例宣城市网站集约化建设
  • 手机便宜电商网站建设金融行业网站模板
  • 公益广告不浪费水网站怎么做长沙有家具网站建设的吗
  • 网站建设需要缴纳印花税么建设会计协会网站
  • 网站动态页面打不开局域网搭建wordpress怎么访问不了
  • 网站页面建设规划文案以下属于网站的管理 更新 维护
  • 塑胶加工 技术支持 东莞网站建设优化网站内容
  • 如何做好一个企业网站设计建立个机密网站
  • 网站海外推广资源常熟公司做网站
  • 慈溪企业网站建设公司硬件开发软件有哪些
  • 电子商务网站功能介绍如何做网站实名认证
  • 江苏省建设通官方网站便利的龙岗网站设计
  • 怎么样把以前做的网站删除无锡哪里有做网站