如何使用Apache POI在Excel中裁剪图片仅显示中间相关区域?
Apache POI 实现Excel图片裁剪(仅显示中间区域)
Apache POI 并没有提供直接的图片裁剪API,但可以通过调整图片在单元格内的偏移量和显示范围来模拟裁剪效果——本质是把图片的多余部分移出单元格的可视区域,只保留中间目标区域。以下是具体实现步骤和代码示例:
核心思路
- 计算原始图片与目标裁剪区域的尺寸差值,得到需要偏移的像素数(比如取中间矩形时,左右偏移量=(原图宽-目标宽)/2,上下偏移量=(原图高-目标高)/2)
- 将像素单位转换为Excel使用的EMU单位(1EMU = 1/96000英寸,POI提供工具方法完成转换)
- 通过
ClientAnchor设置图片在单元格内的起始/结束偏移,让仅中间区域显示在单元格中
代码示例
假设要将一张800x600的图片,裁剪中间400x300的区域,放入Excel的A1单元格:
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.util.Units; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class ImageCropInExcel { public static void main(String[] args) throws IOException { // 1. 创建工作簿和工作表 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("图片裁剪示例"); // 2. 加载原始图片 String imagePath = "original-image.png"; byte[] imageBytes; try (FileInputStream fis = new FileInputStream(imagePath)) { imageBytes = fis.readAllBytes(); } // 3. 定义尺寸参数(单位:像素) int originalWidth = 800; int originalHeight = 600; int targetWidth = 400; int targetHeight = 300; // 计算中间区域的偏移量 int offsetX = (originalWidth - targetWidth) / 2; int offsetY = (originalHeight - targetHeight) / 2; // 4. 像素转Excel的EMU单位 int emuOffsetX = Units.pixelToEMU(offsetX); int emuOffsetY = Units.pixelToEMU(offsetY); int emuTargetWidth = Units.pixelToEMU(targetWidth); int emuTargetHeight = Units.pixelToEMU(targetHeight); // 5. 创建图片锚点,设置显示范围 CreationHelper helper = workbook.getCreationHelper(); ClientAnchor anchor = helper.createClientAnchor(); // 指定图片所在单元格(A1) anchor.setCol1(0); anchor.setRow1(0); anchor.setCol2(0); anchor.setRow2(0); // 关键:设置图片偏移,仅显示中间区域 anchor.setDx1(emuOffsetX); // 跳过图片左侧多余部分 anchor.setDy1(emuOffsetY); // 跳过图片上方多余部分 anchor.setDx2(emuOffsetX + emuTargetWidth); // 限定图片右侧显示边界 anchor.setDy2(emuOffsetY + emuTargetHeight); // 限定图片下方显示边界 // 6. 插入图片到工作表 int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG); Drawing<?> drawing = sheet.createDrawingPatriarch(); drawing.createPicture(anchor, pictureIdx); // 调整单元格大小匹配裁剪后的图片(可选) sheet.setColumnWidth(0, Units.pixelToWidthUnits(targetWidth)); sheet.getRow(0).setHeightInPoints(Units.pixelToPoints(targetHeight)); // 7. 保存工作簿 try (FileOutputStream fos = new FileOutputStream("cropped-image.xlsx")) { workbook.write(fos); } workbook.close(); } }
关键说明
Units.pixelToEMU():POI内置工具方法,避免手动单位换算的误差ClientAnchor偏移逻辑:通过dx1/dy1跳过图片的冗余部分,dx2/dy2锁定显示的结束位置,最终仅中间目标区域会在单元格内展示- 单元格尺寸调整:可选步骤,让单元格大小刚好适配裁剪后的图片,视觉效果更自然
这种方法实现的效果和Excel手动裁剪完全一致,虽然原始图片会完整嵌入Excel文件,但显示时仅保留指定的中间区域。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

