Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片

Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片

一、问题描述

如导出PDF文件为3页

想要的样式:

  • 第一页存在图片1。

  • 第二页存在图片2。

  • 第三页存在图片3。

实际导出样式:

  • 第一页存在图片1。

  • 第二页存在图片1、图片2。

  • 第三页存在图片1、图片2、图片3。

如重置绘图后第二页报空并且无法写入数据。

java 复制代码
// 或者完全新建一个 CTDrawing 对象
CTDrawing newCTDrawing = CTDrawing.Factory.newInstance();
// 将新对象设置回绘图
drawing.setCTDrawing(newCTDrawing);

二、解决方法

1.写入图片方法代码

java 复制代码
//row 行
//col 列
//imagePath 图片路径
private void addImageToSheetCell(int row,int col, String imagePath) throws IOException{
 //读取图片文件-如怕出现路径文件为空可加入try catch进行异常抛出从而继续运行程序
 InputStream inputStream = new FileInputStream(imagePath);
 byte[] bytes = IOUtils.toByteArray(inputStream);
 //将图片添加到工作簿,并返回索引
 int pictureIdx = workbook.addPicture(bytes, imagePath.endsWith(".png") ? 
 Workbook.PICTURE_TYPE_PNG : Workbook.PICTURE_TYPE_JPEG);
 inputStream.close();
 //准备插入图片的工具
 CreationHelper helper = workbook.getCreationHelper();
 XSSFDrawing drawing = sheet.createDrawingPatriarch();
 //设置图片位置(锚点)
 ClientAnchor anchor = helper.createClientAnchor();
 //定位到第2行第3列(C2单元格),跨1列1行(--双锚点定位图片--)
 anchor.setCol1(2);
 anchor.setRow1(1);
 anchor.setCol2(3);
 anchor.setRow2(2);

 //以下代码可忽略,这没有用到
 //----获取图片宽高、单元格宽高,可用来自定义图片大小。
 XSSFPicture pict = drawing.createPicture(anchor, pictureIdx);
 // 获取图片的高和宽
 int picHeight = pict.getImageDimension().height;
 int picWidth = pict.getImageDimension().width;
 // 获取单元格的高和宽(保持原参数名)
 float totalHeight = Units.pointsToPixel(sheet.getRow(row).getHeightInPoints());
 float totalWidth = Units.pointsToPixel(sheet.getColumnWidthInPixels(col));
 //设置图片大小和位置,Units.EMU_PER_PIXEL为像素点单位
 anchor.setDy1(1* Units.EMU_PER_PIXEL);
 anchor.setDy2(1* Units.EMU_PER_PIXEL);
 anchor.setDx1(1* Units.EMU_PER_PIXEL);
 anchor.setDx2(1* Units.EMU_PER_PIXEL);

}

2.图片清除方法

java 复制代码
//写入新一页数据前清除上一页存在的的图片
public void removeAllPictures() {
  //获取绘图对象
  XSSFDrawing drawing = sheet.getDrawingPatriarch();
  //检查是否存在绘图对象
   if (drawing != null){
    //获取所有图片的锚点列表的长度(写入图片时用的是双锚点定位方式)
    int t=drawing.getCTDrawing().getTwoCellAnchorList().size();
     //每次移除后会刷新双锚点集合的长度
     //每次移除集合中的第一个参数才能实现图片移除
     for (int i = 0; i < t; i++) {
        drawing.getCTDrawing().removeTwoCellAnchor(0);
        }
    }
}

三、知识点

1.TwoCellAnchor(双锚点):

  • 使用两个单元格来定位对象(左上角和右下角)。

  • 对象的位置和大小会随着这两个单元格的位置变化而自动调整。

  • 通常用于需要动态调整大小的场景(例如,图片需要跟随单元格的行高/列宽变化)。

  • 在 Excel 中插入的图片默认使用 TwoCellAnchor。

2.OneCellAnchor(单锚点):

  • 使用一个单元格(通常是左上角)和固定的偏移量(如像素或 EMU 单位)来定位对象。

  • 对象的大小和位置是相对于该单元格的固定值,不会随单元格的行高/列宽变化而自动调整。

  • 通常用于需要固定位置和大小的场景。

相关推荐
寻星探路2 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
曹牧4 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
爬山算法5 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7255 小时前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎5 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
李少兄5 小时前
在 IntelliJ IDEA 中修改 Git 远程仓库地址
java·git·intellij-idea
忆~遂愿6 小时前
ops-cv 算子库深度解析:面向视觉任务的硬件优化与数据布局(NCHW/NHWC)策略
java·大数据·linux·人工智能
小韩学长yyds6 小时前
Java序列化避坑指南:明确这4种场景,再也不盲目实现Serializable
java·序列化
仟濹6 小时前
【Java基础】多态 | 打卡day2
java·开发语言