0%

POI操作EXCEL插入图片

POI操作EXCEL插入图片:完整实现与优化技巧

在 Excel 中插入图片(如 Logo、二维码、报表图表)可增强文档的可视化效果。Apache POI 提供了灵活的图片插入功能,支持多种图片格式(PNG、JPG 等)和位置调整。本文将详细讲解插入图片的核心步骤、代码实现及常见问题解决方案。

核心原理与类

POI 插入图片的核心逻辑是:

  1. 将图片转为字节数组;
  2. 通过 Workbook.addPicture() 注册图片资源;
  3. 使用绘图对象(Drawing)将图片锚定到指定单元格位置。

关键类说明:

类名 作用描述
HSSFWorkbook/XSSFWorkbook 工作簿对象,提供 addPicture() 方法注册图片资源(返回图片索引)。
HSSFPatriarch/XSSFDrawing 绘图管理器,负责创建图片对象并关联到工作表。
ClientAnchor 图片锚点,定义图片在工作表中的位置(起始行列、偏移量等)。
Picture 图片对象,支持调整尺寸、获取图片信息等操作。

完整代码实现

以下示例支持 .xls(Excel 2003)和 .xlsx(Excel 2007+)格式,演示如何插入本地图片到指定单元格,并调整尺寸。

通用工具类(兼容两种格式)

maven依赖

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import org.apache.poi.hssf.usermodel.*;  
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class ExcelImageUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelImageUtil.class);

/**
* 向 Excel 插入图片
* @param workbook 工作簿对象(HSSFWorkbook 或 XSSFWorkbook)
* @param sheet 目标工作表
* @param imagePath 图片路径(本地文件或资源文件)
* @param rowIndex 起始行索引(0 开始)
* @param colIndex 起始列索引(0 开始)
* @param pictureType 图片类型(如 Workbook.PICTURE_TYPE_PNG)
* @param resizeRatio 缩放比例(1.0 为原尺寸)
*/
public static void insertImage(Workbook workbook, Object sheet, String imagePath,
int rowIndex, int colIndex, int pictureType, double resizeRatio) {
// 1. 读取图片为字节数组
byte[] imageBytes = getImageBytes(imagePath);
if (imageBytes == null) {
LOGGER.error("图片读取失败:{}", imagePath);
return;
}

// 2. 注册图片资源,获取图片索引
int pictureIndex = workbook.addPicture(imageBytes, pictureType);

// 3. 创建绘图管理器和锚点(区分 .xls 和 .xlsx)
if (workbook instanceof HSSFWorkbook) {
// 处理 .xls 格式
HSSFSheet hssfSheet = (HSSFSheet) sheet;
HSSFPatriarch patriarch = hssfSheet.createDrawingPatriarch();
HSSFClientAnchor anchor = (HSSFClientAnchor) workbook.getCreationHelper().createClientAnchor();
setAnchorPosition(anchor, rowIndex, colIndex);
// 创建图片并缩放
HSSFPicture picture = patriarch.createPicture(anchor, pictureIndex);
picture.resize(resizeRatio);
} else if (workbook instanceof XSSFWorkbook) {
// 处理 .xlsx 格式
XSSFSheet xssfSheet = (XSSFSheet) sheet;
XSSFDrawing drawing = xssfSheet.createDrawingPatriarch();
XSSFClientAnchor anchor = (XSSFClientAnchor) workbook.getCreationHelper().createClientAnchor();
setAnchorPosition(anchor, rowIndex, colIndex);
// 创建图片并缩放
drawing.createPicture(anchor, pictureIndex).resize(resizeRatio);
}

LOGGER.info("图片插入成功:{}(位置:行{},列{})", imagePath, rowIndex, colIndex);
}

/**
* 设置图片锚点位置(左上角对齐到指定单元格)
*/
private static void setAnchorPosition(ClientAnchor anchor, int rowIndex, int colIndex) {
anchor.setRow1(rowIndex); // 起始行
anchor.setCol1(colIndex); // 起始列
anchor.setDx1(0); // 列内 x 偏移(0 表示左对齐)
anchor.setDy1(0); // 行内 y 偏移(0 表示上对齐)
// 若需跨单元格显示,可设置 setRow2 和 setCol2
}

/**
* 将图片转为字节数组(支持本地文件和资源文件)
*/
private static byte[] getImageBytes(String imagePath) {
try (InputStream is = imagePath.startsWith("/") ?
ExcelImageUtil.class.getResourceAsStream(imagePath) : // 资源文件
new FileInputStream(imagePath); // 本地文件
ByteArrayOutputStream out = new ByteArrayOutputStream()) {

BufferedImage image = ImageIO.read(is);
if (image == null) {
LOGGER.error("无法识别图片格式:{}", imagePath);
return null;
}
// 根据图片类型写入流(此处以 PNG 为例,可根据实际类型调整)
ImageIO.write(image, "png", out);
return out.toByteArray();
} catch (IOException e) {
LOGGER.error("图片读取异常:{}", imagePath, e);
return null;
}
}
}

调用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelImageDemo {
public static void main(String[] args) {
// 示例 1:生成 .xlsx 格式并插入图片
String xlsxPath = "带图片的Excel.xlsx";
try (Workbook xssfWorkbook = new XSSFWorkbook();
FileOutputStream fos = new FileOutputStream(xlsxPath)) {

// 创建工作表
XSSFSheet xssfSheet = xssfWorkbook.createSheet("图片示例");
// 插入图片(资源文件 logo.png,位置:行1,列1,缩放 0.5 倍)
ExcelImageUtil.insertImage(
xssfWorkbook, xssfSheet, "/logo.png", // 资源文件路径
1, 1, // 行1,列1(B2单元格)
Workbook.PICTURE_TYPE_PNG, // 图片类型
0.5 // 缩放比例
);
xssfWorkbook.write(fos);
} catch (IOException e) {
e.printStackTrace();
}

// 示例 2:生成 .xls 格式并插入图片
String xlsPath = "带图片的Excel.xls";
try (Workbook hssfWorkbook = new HSSFWorkbook();
FileOutputStream fos = new FileOutputStream(xlsPath)) {

HSSFSheet hssfSheet = hssfWorkbook.createSheet("图片示例");
ExcelImageUtil.insertImage(
hssfWorkbook, hssfSheet, "D:/qrcode.jpg", // 本地文件路径
3, 2, // 行3,列2(C4单元格)
Workbook.PICTURE_TYPE_JPEG,
1.0 // 原尺寸
);
hssfWorkbook.write(fos);
} catch (IOException e) {
e.printStackTrace();
}
}
}

关键参数与高级配置

图片位置与跨单元格显示

通过 ClientAnchorsetRow2setCol2 可设置图片跨单元格显示,例如:

1
2
3
4
5
// 图片从 B2 单元格跨到 D4 单元格  
anchor.setRow1(1); // 起始行:1(第2行)
anchor.setCol1(1); // 起始列:1(B列)
anchor.setRow2(3); // 结束行:3(第4行)
anchor.setCol2(3); // 结束列:3(D列)

图片缩放与尺寸调整

  • resize(double ratio):按比例缩放(如 0.5 表示缩小到 50%);
  • resize():无参方法,自动调整图片尺寸以适应锚定的单元格范围;
  • 注意.xls 格式的 resize() 可能存在精度问题,建议手动指定比例。

图片类型常量

Workbook 定义了常见图片类型的常量,需与实际图片格式匹配:

常量 图片格式
PICTURE_TYPE_PNG PNG
PICTURE_TYPE_JPEG JPG/JPEG
PICTURE_TYPE_GIF GIF
PICTURE_TYPE_BMP BMP

常见问题与解决方案

1. 图片插入后不显示

  • 原因
    • 图片路径错误(资源文件需以 / 开头,本地文件需绝对路径);
    • 图片格式不支持(如 SVG 格式,POI 不支持);
    • 锚点位置设置错误(如行列索引越界)。
  • 解决
    • 检查 getImageBytes() 方法是否返回有效字节数组;
    • 替换为 PNG/JPG 等支持的格式;
    • 简化锚点设置(先测试插入到 row=0, col=0 位置)。

2. 图片模糊或变形

  • 原因:缩放比例不当或图片本身分辨率过低;
  • 解决
    • 使用高分辨率图片,按原比例缩放(如 1.0);
    • 避免过度放大(超过原尺寸会模糊)。

3. 大图片导致 Excel 体积过大

  • 原因:未压缩的高清图片(如几 MB 的 PNG)会显著增加文件体积;
  • 解决
    • 插入前压缩图片(如通过工具将分辨率调整为 72dpi);
    • 转换为 JPG 格式(比 PNG 体积更小,适合照片类图片)。

4. .xls.xlsx 兼容性问题

  • 现象.xls 中插入的图片在 .xlsx 中显示异常;
  • 解决:严格区分两种格式的类(HSSF 对应 .xlsXSSF 对应 .xlsx),避免混用。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10