Java Web导出等比例图片到Excel

做个Excel导入导出的Java开发户都知道,可以利用Apache的POI来实现,为Excel创建每一行,每一单元及对应的内容。当然,图片的话需要用到POI中的HSSFClientAnchor这个类型来实现, HSSFClientAnchor的构造函数中有八个参数,分类为:int dx1,int dy1,int dx2,int dy2,short col1,int row1,short col2, int row2,其中dx1、dy1定义了该图片在开始cell的起始位置,dx2、dy2定义了在终cell的结束位置,col1、row1定义了开始cell、col2、row2定义了结束cell。

那么,我们就可以用这个方法来讲图片定位到每一个单元格中。我的做法是:

铺满整个单元格,这里的j和i是代码中要到处多张图做了循环定义的变量HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) j, i + 1, (short) j, i + 1);

很顺利,成功导出!

问题来了,打开成功到处的Excel一看,商品对应的图片都很规矩的按照我的设置铺满了整个单元格。但是,商品图片却都变形了,也就是图片的 宽高被强行设置了成对应单元格的宽高。

这样肯定是不行的,于是第一反应就是将图片等比例导出,但是怎么让图片等比例的导出在Excel中呢,苦恼了许久,终于想到了一个可行的方案。就是利用POI设置每一行对应要放图片的那个单元格的宽度固定,也就是所有导出的图片的宽度固定,然后根据这个固定宽度与原图宽高对比,算出该固定宽度的等比例高度,然后动态设置该单元格的高度,然后再利用HSSFClientAnchor来铺满整个单元格,这样看起来就不会变形,而且等比例缩放到指定单元格中。

关键2步实现:

第一步 设置单元格固定宽度: 循环创建每一行的时候,如何设置要放图片的那个单元的宽度呢?大家都知道,在Excel中,同一列的单元格的宽度都是一样的,故可以在创建工作簿的时候,就设定好要放图片的那个单元格的宽度,我是这样做的:

生成一个表格 HSSFSheet sheet = workbook.createSheet(title);

设置B列的宽度为 30*256; sheet.setColumnWidth(1, 30 * 256);

这里我们看到,SetColumnWidth的第二个参数要乘以256,是因为这个参数的单位是1/256个字符宽度,也就是说这里我设置的是30个字符的宽度,至于一个字符宽度是多少,可以用FontDesignMetrics来获得,一般一个12号字体的宽度大约是13像素。

第二步,设置单元等比率高度:在循环每一行中,当创建对应放图片的单元的时候,设置对应的高度。我的做法是,先获取要导出的图片,在获取图片的原始宽度和高度(主要,这里获取的是像素宽高),然后根据前面设置的固定宽度算出等比例的高度:

java 复制代码
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
BufferedImage bufferImg = ImageIO.read(new File(savePath + System.getProperty("file.separator") + map.get("productImg")));
ImageIO.write(bufferImg, "jpg", byteArrayOut);
int width = bufferImg.getWidth();//原始宽度
int height = bufferImg.getHeight();//原始高度
// 一个12号字体的宽度为13,前面已设置了列的宽度为30*256,故这里的等比例高度计算如下
height = (int) Math.round((height * (30 * 13) * 1.0 / width));
// excel单元格高度是以点单位,1点=2像素; POI中Height的单位是1/20个点,故设置单元的等比例高度如下
row.setHeight((short) (height / 2 * 20));
// 画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
HSSFPatriarch patriarch = sheet.createDrawingPatriarch();
// anchor主要用于设置图片的属性
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255, (short) j, i + 1, (short) j, i + 1);
anchor.setAnchorType(3);
// 插入图片
patriarch.createPicture(anchor,workbook.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG));

至此,等比率图片及相关信息以完美导出到Excel中。

相关推荐
用户4702784004055 分钟前
C语言编译与链接
后端·开源
你三大爷8 分钟前
从 Hessian 迁移到 protostuff:深嵌套模型反序列化耗时与高并发类加载锁的根治实战
后端·架构
IT枫斗者枫哥9 分钟前
子线程断言失败,JUnit 为什么还显示通过?
java·后端
stark张宇2 小时前
Vibe Coding 入门实战:用 Claude Code 跑通 AI 产品开发流程(上)
后端·claude·vibecoding
考虑考虑2 小时前
JDK27中的Set.ofLazy
java·后端·java ee
乌暮4 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
我不会起名字3225 小时前
未接入最终读上限的参数:`websocketMaxMsgLen` 与 12.5 倍差距
后端·websocket·go·即时通讯·im·故障排查
一条Go5 小时前
接收方合并去重:同一个人为什么只该收到一次通知
后端·架构·github
张一凡936 小时前
给 Coding Agent 加一道"架构闸门":Jin 是如何做到"先审架构、再写代码、不漂移"的
前端·后端·agent
Jvav练习生6 小时前
AI Agent 总在关键时刻“失忆”翻车?一文讲透上下文工程(附可运行 Python 代码)
后端