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

Java使用Apache Poi 生成带图片的嵌套表格

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;public class NestedTableWithImageDemo {public static void main(String[] args) throws Exception {XWPFDocument document = new XWPFDocument();// ============ 标题 ============XWPFParagraph title = document.createParagraph();title.setAlignment(ParagraphAlignment.CENTER);XWPFRun titleRun = title.createRun();titleRun.setText("单元格内:图片 + 嵌套表格 示例");titleRun.setBold(true);titleRun.setFontSize(16);titleRun.setFontFamily("微软雅黑");// ============ 创建外层表格 (2行2列) ============XWPFTable outerTable = document.createTable(2, 2);outerTable.setWidth("100%");setTableBorder(outerTable);// 表头setCellText(outerTable.getRow(0).getCell(0), "名称", true, "D9E2F3");setCellText(outerTable.getRow(0).getCell(1), "图片 + 详情", true, "D9E2F3");// 第1行setCellText(outerTable.getRow(1).getCell(0), "项目A", false, null);// ★★★ 核心:在第1行第2列 → 先插图片,再插嵌套表格 ★★★XWPFTableCell targetCell = outerTable.getRow(1).getCell(1);insertImageAndNestedTable(targetCell, "demo.png");// ============ 输出文件 ============String filePath = "image_with_nested_table.docx";try (FileOutputStream out = new FileOutputStream(filePath)) {document.write(out);}document.close();System.out.println("文档已生成: " + filePath);}/*** ★★★ 核心方法:在同一个单元格中,上方插入图片,下方插入嵌套表格 ★★★*/public static void insertImageAndNestedTable(XWPFTableCell cell, String imagePath)throws Exception {// ---------- 第1步:清空单元格默认段落 ----------while (cell.getParagraphs().size() > 0) {cell.removeParagraph(0);}// ---------- 第2步:创建段落并插入图片(在上方) ----------// 手动添加一个新段落用于放图片CTP ctpImage = cell.getCTTc().addNewP();XWPFParagraph imageParagraph = new XWPFParagraph(ctpImage, cell);imageParagraph.setAlignment(ParagraphAlignment.CENTER);imageParagraph.setSpacingAfter(100); // 图片与表格之间留间距XWPFRun imageRun = imageParagraph.createRun();// 插入图片(支持 PNG / JPEG / GIF 等)try (FileInputStream fis = new FileInputStream(imagePath)) {imageRun.addPicture(fis,XWPFDocument.PICTURE_TYPE_PNG,   // 图片类型imagePath,Units.toEMU(200),   // 宽度 200pt(可自行调整)Units.toEMU(120)    // 高度 120pt(可自行调整));}// 图片下方加一行说明文字(可选)XWPFRun captionRun = imageParagraph.createRun();captionRun.addBreak();  // 换行captionRun.setText("▲ 项目效果图");captionRun.setFontSize(8);captionRun.setColor("888888");captionRun.setFontFamily("微软雅黑");// ---------- 第3步:在图片下方创建嵌套表格 ----------CTTbl ctTbl = cell.getCTTc().addNewTbl();// 设置嵌套表格宽度 100%CTTblPr tblPr = ctTbl.addNewTblPr();CTTblWidth tblWidth = tblPr.addNewTblW();tblWidth.setType(STTblWidth.PCT);tblWidth.setW(BigInteger.valueOf(5000)); // 5000 = 100%// 创建 3行2列 的嵌套表格结构int rows = 3, cols = 2;for (int i = 0; i < rows; i++) {CTRow ctRow = ctTbl.addNewTr();for (int j = 0; j < cols; j++) {CTTc ctTc = ctRow.addNewTc();ctTc.addNewP(); // 每个单元格必须有段落}}// ---------- 第4步:表格后面必须跟一个空段落(Word规范) ----------cell.getCTTc().addNewP();// ---------- 第5步:包装为 XWPFTable 并填充内容 ----------XWPFTable nestedTable = new XWPFTable(ctTbl, cell);setTableBorder(nestedTable);// 填充嵌套表格setCellText(nestedTable.getRow(0).getCell(0), "子项", true, "E2EFDA");setCellText(nestedTable.getRow(0).getCell(1), "金额(万元)", true, "E2EFDA");setCellText(nestedTable.getRow(1).getCell(0), "设计费", false, null);setCellText(nestedTable.getRow(1).getCell(1), "50.00", false, null);setCellText(nestedTable.getRow(2).getCell(0), "施工费", false, null);setCellText(nestedTable.getRow(2).getCell(1), "200.00", false, null);}/*** ★ 通用方法:在单元格中插入图片(不含嵌套表格的简化版)*/public static void insertImageToCell(XWPFTableCell cell, String imagePath,int widthPt, int heightPt,int pictureType) throws Exception {XWPFParagraph paragraph;if (cell.getParagraphs().size() > 0) {paragraph = cell.getParagraphs().get(0);} else {paragraph = cell.addParagraph();}paragraph.setAlignment(ParagraphAlignment.CENTER);XWPFRun run = paragraph.createRun();try (FileInputStream fis = new FileInputStream(imagePath)) {run.addPicture(fis, pictureType, imagePath,Units.toEMU(widthPt), Units.toEMU(heightPt));}}/*** 设置单元格文本*/public static void setCellText(XWPFTableCell cell, String text,boolean bold, String bgColor) {XWPFParagraph para;if (cell.getParagraphs().size() > 0) {para = cell.getParagraphs().get(0);} else {para = cell.addParagraph();}para.setAlignment(ParagraphAlignment.CENTER);para.setSpacingBefore(30);para.setSpacingAfter(30);XWPFRun run;if (para.getRuns().size() > 0) {run = para.getRuns().get(0);} else {run = para.createRun();}run.setText(text, 0);run.setBold(bold);run.setFontSize(10);run.setFontFamily("微软雅黑");cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);if (bgColor != null) {CTTc ctTc = cell.getCTTc();CTTcPr tcPr = ctTc.isSetTcPr() ? ctTc.getTcPr() : ctTc.addNewTcPr();CTShd shd = tcPr.isSetShd() ? tcPr.getShd() : tcPr.addNewShd();shd.setFill(bgColor);shd.setVal(STShd.CLEAR);}}/*** 设置表格边框*/public static void setTableBorder(XWPFTable table) {CTTblPr tblPr = table.getCTTbl().getTblPr();if (tblPr == null) {tblPr = table.getCTTbl().addNewTblPr();}CTTblBorders borders = tblPr.isSetTblBorders()? tblPr.getTblBorders() : tblPr.addNewTblBorders();setBorder(borders.addNewTop());setBorder(borders.addNewBottom());setBorder(borders.addNewLeft());setBorder(borders.addNewRight());setBorder(borders.addNewInsideH());setBorder(borders.addNewInsideV());}private static void setBorder(CTBorder border) {border.setVal(STBorder.SINGLE);border.setSz(BigInteger.valueOf(4));border.setColor("000000");border.setSpace(BigInteger.ZERO);}
}

  

http://www.jsqmd.com/news/534007/

相关文章:

  • 老旧电脑卡顿?用Tiny11Builder让它再战三年
  • FlowState Lab助力前端3D渲染:WebGL中的实时波动表面生成
  • 分期乐微信立减金如何回收,盘点95折变现攻略 - 淘淘收小程序
  • Cool Edit读取PCM音频数据的完整指南:从基础原理到实战解析
  • 2026年苏州热门的亚克力加工实力厂家,排名情况如何 - 工业品网
  • 兼顾能效管理、系统安全与后期扩展的工业数据中心,应优先选型哪些连接+自控一体化厂商?——基于系统结构完整性的工程判断与解析
  • 服务器硬件小白必看:从CPU到网卡,一文搞懂各部件作用与选购指南
  • 如何统计一个数字的位数?
  • Wan2.1 VAE在网络安全中的应用:生成对抗样本进行模型鲁棒性测试
  • 大模型应用开发:小白也能学会的RAG系统优化全攻略(收藏版)
  • 突破JetBrains IDE试用期限制:ide-eval-resetter工具全解析
  • 资源
  • SeqGPT-560M入门指南:Streamlit组件封装——可复用NER输入/输出UI组件
  • 【管理架构】从“流程约束”到“系统赋能”:如何构建高效运转的组织闭环?
  • 我决定使用自己的公网服务器作为支付回调接口
  • GBase 8a 运维巡检与监控告警实践:别等故障来了,才想起看日志
  • 如何禁止微信发文件、禁止QQ发送文件、防止聊天软件泄密电脑文件的行为?
  • 四川省挤塑聚苯板(XPS)采购选型指南——破解选择困境 - 深度智识库
  • 垂直领域破局者:2026 AI超级员工系统细分赛道实战报告
  • 新手也能搞定!STM32F407ZGT6最小系统板PCB设计全流程(附原理图/3D图)
  • YOLOv8改进:引入BiFormer双层路由注意力机制,让目标检测更高效更精准
  • yfinance终极指南:5分钟快速获取免费金融数据的完整教程
  • clip的底层原理---深入源码:手把手剖析OpenAI CLIP的实现结构与细节 - Sanny.Liu
  • LLM+HTN智能任务分解在AI客服系统中的实战应用与架构解析
  • Agent智能体架构解析:如何用百川2-13B构建自主任务执行系统
  • 微软MOS认证,这些考生满分通过了~
  • 知名的铁锅炖加盟企业靠谱推荐,覆盖山东河南等地 - myqiye
  • HunyuanVideo-Foley行业应用:电商商品视频自动配环境音、AR营销素材生成
  • 托盘姿态检测关键点检测数据集YOLO格式1943张1类别3关键点
  • 2026年山东、陕西等地口碑好的省煤器厂家推荐,诚信源头厂家全解读 - mypinpai