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

别再手动拖拽了!用Java POI + XSSFDrawing,5行代码搞定Excel单元格图片批量插入(附完整源码)

5行代码实现Excel图片批量插入Java POI XSSFDrawing高效开发指南1. 为什么需要自动化Excel图片插入在日常报表开发中我们经常遇到需要将大量图片如用户头像、产品图嵌入Excel单元格的场景。传统手动操作存在三大痛点效率低下每张图片需要手动拖拽调整位置和大小精度难控单元格与图片对齐困难容易错位批量处理难面对成百上千张图片时几乎不可行通过Java POI的XSSFDrawing组件我们可以用5行核心代码解决这些问题// 创建绘图对象 XSSFDrawing patriarch sheet.createDrawingPatriarch(); // 设置图片位置锚点 XSSFClientAnchor anchor new XSSFClientAnchor(0, 0, 0, 0, col1, row1, col2, row2); // 添加图片到工作簿 int pictureIndex workbook.addPicture(imageData, XSSFWorkbook.PICTURE_TYPE_JPEG); // 将图片绑定到指定位置 patriarch.createPicture(anchor, pictureIndex); // 调整图片大小可选 patriarch.createPicture(anchor, pictureIndex).resize();2. 环境准备与基础配置2.1 必要依赖确保pom.xml中包含最新POI依赖dependency groupIdorg.apache.poi/groupId artifactIdpoi/artifactId version5.2.3/version /dependency dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version5.2.3/version /dependency2.2 图片源处理支持三种常见图片源格式图片源类型获取方式内存占用适用场景本地文件FileInputStream低服务器本地存储网络URLHttpURLConnection中远程图片获取Base64编码Base64.getDecoder()高前端传输或数据库存储Base64转换工具方法public static byte[] base64ToBytes(String base64) { return DatatypeConverter.parseBase64Binary( base64.replace(data:image/jpeg;base64,, ) ); }3. 核心实现五步完成图片插入3.1 创建绘图控制器XSSFDrawing patriarch sheet.createDrawingPatriarch();注意每个sheet只能创建一个DrawingPatriarch实例多次创建会导致图片覆盖3.2 精确定位图片锚点XSSFClientAnchor anchor new XSSFClientAnchor( dx1, dy1, dx2, dy2, (short)col1, row1, (short)col2, row2 );参数详解dx1/dy1图片左上角在单元格内的偏移量单位1/1000dx2/dy2图片右下角在单元格内的偏移量col1/row1起始单元格坐标col2/row2结束单元格坐标3.3 图片数据预处理// 本地文件 byte[] data Files.readAllBytes(Paths.get(product.jpg)); // 网络图片 byte[] data new URL(imageUrl).openStream().readAllBytes(); // Base64编码 byte[] data Base64.getDecoder().decode(base64Str);3.4 注册图片到工作簿int pictureIdx workbook.addPicture( data, XSSFWorkbook.PICTURE_TYPE_JPEG // 支持PNG/JPEG等格式 );3.5 创建图片并自动调整XSSFPicture picture patriarch.createPicture(anchor, pictureIdx); picture.resize(); // 自适应单元格大小4. 高级技巧与避坑指南4.1 批量插入性能优化// 使用缓存减少IO操作 MapString, byte[] imageCache new HashMap(); // 并行处理提高速度 ListImageData images.parallelStream().forEach(img - { if(!imageCache.containsKey(img.getId())){ imageCache.put(img.getId(), fetchImage(img)); } insertImage(sheet, imageCache.get(img.getId()), img.getPos()); });4.2 常见问题解决方案问题1图片显示不全调整锚点参数dx120*1000, dy120*1000, dx21000*1000, dy21000*1000检查单元格行高列宽是否足够问题2多图片重叠确保每个图片使用独立的Anchor实例验证col/row坐标是否重复问题3大文件内存溢出// 使用临时文件处理 try(POIXMLDocumentPart imgPart new XSSFPictureData()){ imgPart.prepareForCommit(); imgPart.getPackagePart().save(new FileOutputStream(tempFile)); }5. 完整示例代码public class ExcelImageExporter { public static void exportWithImages(ListProduct products, String outputPath) { XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(产品目录); // 设置标题行 XSSFRow headerRow sheet.createRow(0); headerRow.createCell(0).setCellValue(产品ID); headerRow.createCell(1).setCellValue(产品图片); // 批量插入图片 XSSFDrawing drawing sheet.createDrawingPatriarch(); for(int i0; iproducts.size(); i){ Product p products.get(i); XSSFRow row sheet.createRow(i1); // 产品ID row.createCell(0).setCellValue(p.getId()); // 图片单元格 XSSFCell imgCell row.createCell(1); sheet.setColumnWidth(1, 30*256); // 设置列宽 row.setHeight((short)(200*15)); // 设置行高 // 获取图片数据 byte[] imageData ImageFetcher.fetch(p.getImageUrl()); // 创建锚点 XSSFClientAnchor anchor new XSSFClientAnchor( 0, 0, 0, 0, (short)1, i1, (short)1, i1 ); // 插入图片 int picIndex workbook.addPicture(imageData, XSSFWorkbook.PICTURE_TYPE_JPEG); drawing.createPicture(anchor, picIndex).resize(); } // 输出文件 try(FileOutputStream fos new FileOutputStream(outputPath)){ workbook.write(fos); } } }6. 扩展应用场景6.1 动态图片调整// 根据图片原始比例调整单元格尺寸 BufferedImage img ImageIO.read(new ByteArrayInputStream(imageData)); double ratio (double)img.getHeight()/img.getWidth(); sheet.setColumnWidth(colIndex, (int)(50*256)); // 基础宽度 row.setHeight((short)(50*15*ratio)); // 按比例设置高度6.2 与数据绑定// 使用Map存储图片与数据关系 MapCellAddress, String imageDataMap new HashMap(); imageDataMap.put(new CellAddress(1,1), 产品A详情...); // 添加批注 XSSFComment comment drawing.createCellComment(new XSSFClientAnchor()); comment.setString(new XSSFRichTextString(imageDataMap.get(cellAddress))); cell.setCellComment(comment);7. 性能对比测试测试数据插入1000张图片平均50KB/张方案耗时(ms)内存峰值(MB)文件大小(MB)手动操作30min-48.7基础POI584251248.5优化版218725648.3并行流142538448.3测试环境JDK17/16G内存/SSD硬盘通过合理使用缓存和并行处理性能可提升3-4倍。对于超大规模数据建议采用分sheet存储或SAX模式处理。8. 最佳实践建议统一图片格式推荐使用JPEG格式平衡质量和大小尺寸预处理提前将图片缩放至合适尺寸建议800x600以内资源清理workbook.close(); // 必须关闭释放资源 if(drawing ! null){ drawing null; // 帮助GC回收 }异常处理添加网络超时和图片校验逻辑try { byte[] data fetchImage(url); ImageIO.read(new ByteArrayInputStream(data)); // 验证图片有效性 } catch(Exception e) { log.error(图片处理失败: {}, url, e); return DEFAULT_IMAGE; }9. 替代方案对比方案优点缺点适用场景POI XSSFDrawing原生支持、功能强大内存消耗较大复杂Excel生成Apache Pivot内存效率高API较复杂大数据量导出JExcelAPI轻量简单功能有限旧格式(.xls)处理OpenXML SDK官方标准学习曲线陡峭需要精细控制对于简单需求也可以考虑// 使用HTML转Excel方式有限支持 String html tabletrtdimg srcdata:image/jpeg;base64,...//td/tr/table; Files.write(Paths.get(out.xls), html.getBytes());10. 总结通过本文介绍的Java POI XSSFDrawing方案我们实现了5行核心代码完成Excel图片插入支持本地/网络/Base64多种图片源批量处理效率提升300%像素级精确定位典型应用场景电商平台商品目录导出员工信息表带照片实验数据与图表关联导出移动端报表生成提示实际项目中建议封装为ImageExcelExporter工具类结合Spring Boot可轻松构建RESTful导出接口。完整源码可在GitHub获取包含异常处理和性能优化版本。

相关文章:

别再手动拖拽了!用Java POI + XSSFDrawing,5行代码搞定Excel单元格图片批量插入(附完整源码)

5行代码实现Excel图片批量插入:Java POI XSSFDrawing高效开发指南 1. 为什么需要自动化Excel图片插入? 在日常报表开发中,我们经常遇到需要将大量图片(如用户头像、产品图)嵌入Excel单元格的场景。传统手动操作存在三…...

MiniMax Agent 正式更名 Mavis 上线多智能体协作

如果你用过AI助手,大概都有过这种感受:一个AI同时干太多事,要么顾此失彼,要么卡在某个环节原地转圈。 MiniMax显然也看到了这个问题。 5 月 13 日,他们正式宣布旗下Agent产品全面升级,并给它起了个新名字—…...

Day33-1: Serilog(日志中间件)VS OperLogHelper(操作日志帮助类)

一、一句话分清它们的作用 1. Serilog(日志中间件) 作用:记录系统运行日志 → 给程序员看的 控制台打印文件保存报错、异常、请求信息用于排查问题、调试、监控 2. OperLogHelper(操作日志帮助类) 作用&#xff1…...

5分钟搞定U盘验货!这款绿色工具真香到离谱

兄弟们,你有没有买过那种“1TB只要39块还包邮”的U盘? 醒醒!那玩意儿大概率是扩容盘——实际容量可能只有64GB,超出部分写进去的数据全是空气,轻则文件损坏,重则项目代码全丢,救都救不回来&…...

【Java杂项】为什么 b += 1 可以,但 b = b + 1 会报错?类型提升与复合赋值详解

【Java杂项】为什么 b 1 可以,但 b b 1 会报错?复合赋值与类型提升讲清楚前言一、先给结论:它不是简单的文本替换二、先看认知冲突2.1 普通赋值为什么报错2.2 复合赋值为什么能通过三、类型提升到底是什么3.1 常见类型提升结果3.2 为什么小…...

人类的自然关系与AI的形式化关系

“人类的自然关系”与“AI的形式化关系”是理解下一代人机环境系统智能的两个核心哲学维度。它们分别代表了智能系统在物理世界中的生存根基与在数字世界中的运行逻辑。我们可以从以下三个层面来深度解析这两者的区别与融合:人类的自然关系:从“征服掠夺…...

一文搞懂工业机器人通讯协议:TCP/IP、Modbus与专用协议对比

在我十年的工控开发生涯中,通讯问题永远是项目延期的第一大原因。我见过太多团队花了几个月时间做运动控制和视觉算法,最后却卡在了机器人通讯上:要么是数据传输不稳定,要么是速度跟不上产线节拍,要么是换个品牌机器人就要全部重写代码。 很多新手工程师觉得通讯就是&quo…...

态是相关,势是因果,感是具身,知是离身

态是相关,势是因果,感是具身,知是离身,用四个高度概括的词,切中了“人机环境系统智能”中态势感知四个核心维度的本质属性。我们可以结合之前的探讨,来深入拆解一下这句“十六字真言”:态是相关…...

C#上位机开发工业机器人:从零搭建第一个机器人控制程序

作为一名在工控行业摸爬滚打了十年的老工程师,我见过太多自动化工程师卡在"机器人上位机开发"这一关。很多人C#基础不错,也懂机器人原理,但就是不知道怎么把两者结合起来,写出一个能在生产环境运行的控制程序。 今天这篇文章,我会带着你从零开始,搭建一个完整…...

Google Cloud Dataflow 背后的流式处理模型

原文:towardsdatascience.com/the-stream-processing-model-behind-google-cloud-dataflow-0d927c9506a0?sourcecollection_archive---------3-----------------------#2024-04-27 在无界数据处理中的正确性、延迟和成本平衡 https://medium.com/vutrinh274?sour…...

5分钟搞定!NewGAN-Manager终极配置指南:让Football Manager游戏体验焕然一新

5分钟搞定!NewGAN-Manager终极配置指南:让Football Manager游戏体验焕然一新 【免费下载链接】NewGAN-Manager A tool to generate and manage xml configs for the Newgen Facepack. 项目地址: https://gitcode.com/gh_mirrors/ne/NewGAN-Manager …...

【MySQL百日打怪升级第8天】SELECT执行流程

【第8天】每天一个MySQL知识点,百日打怪升级 SQL基础:SELECT执行流程 大家好,我是一名拥有10年以上经验的DBA老兵。 做这个系列,源于一个朴素的愿望:把踩过的坑、总结的经验系统化输出,希望能帮到刚入行或…...

堆叠集成方法

原文:towardsdatascience.com/the-stacking-ensemble-method-984f5134463a 发现堆叠在机器学习中的力量——一种将多个模型组合成一个单一强大预测器的技术。本文从基础知识到高级技术探讨了堆叠,揭示了它是如何结合不同模型的优势以提高准确性的。无论你…...

离谱!上海交大一学生私吞 5000 奖金,还用豆包 P 假收据骗队友。网友:学历虽高但人品太低

①5 月 18 日,上海交大一则学生违纪通报冲上热搜,实锤了前几天网上曝光的一名学生侵占团队竞赛奖金、造假欺骗队友的恶劣行为。②在 2025 下半年,樊同学(上交大智慧能源学院女生)与 K 同学(电院男生&#x…...

ABAP 采购带组件收货BAPI

一、背景 有一项业务比较特殊,金靶的回收加工,既会有物料的消耗,也会收进上一批加工洗出来的物料,并且组件物料会带有批次,MIGO过账时需要填写批次,那么对应BAPI,也需要加入这一部分批次。如果…...

荣耀MagicOS 10系统游戏模式:如何启用幻影稳帧功能并调整游戏画面的流畅度与画质平衡?

用手机玩游戏,最怕遇到卡顿和画面不清晰。想开高帧率保证流畅,画质就可能下降;想开高画质享受视觉盛宴,又容易掉帧卡顿。这真是让不少玩家头疼的问题。如果你的荣耀手机升级到了MagicOS 10系统,那么恭喜你,…...

Perplexity不是越低越好!资深NLP架构师亲授:3类典型查询场景下的阈值黄金区间

更多请点击: https://kaifayun.com 第一章:Perplexity不是越低越好!资深NLP架构师亲授:3类典型查询场景下的阈值黄金区间 Perplexity(困惑度)常被误认为语言模型性能的“万能标尺”,但实际部署…...

一小时搞懂Python函数:原理+实践

目录 🙄什么是Python函数(了解函数的概念) 🤔为什么需要它?(背景和痛点) 😮函数的分类(函数有哪些?) 内置函数 标准库函数 第三方库函数 定…...

互联网大厂 Java 求职者面试:音视频场景下的技术挑战

互联网大厂 Java 求职者面试:音视频场景下的技术挑战在一次互联网大厂的面试中,面试官和候选人燕双非之间展开了一场精彩的对话。燕双非是一位幽默风趣的程序员,尽管他在技术上并不是特别扎实,但他总是能用他的幽默化解紧张氛围。…...

软件设计师下午题训练2-3题+2020下上午题错题解析 练习真题训练15

一、训练题2 1、2021上 (1) (2) a:团购点编号 b:客户电话 供货 主键 :(供货商编号,团购点编号) 外键:供货商编号、团购点编号 订单 主键:订单编号…...

PHP SimpleXML:深入解析与高效使用

PHP SimpleXML:深入解析与高效使用 引言 PHP 是一种广泛使用的服务器端脚本语言,它以其灵活性和强大的功能而闻名。在处理 XML 数据时,PHP 提供了多种方法,其中 SimpleXML 是一个简单且强大的库,它允许开发者轻松地解析和操作 XML 数据。本文将深入探讨 PHP SimpleXML 的…...

远洋边缘计算实战:基于 Linux 的客滚船高并发网络 QoS 调度与隔离策略

摘要:客滚船直连卫星网络面对几百名旅客并发时存在瘫痪与越权风险。本文记录了基于 Linux 构建标准工业级边缘网关多链路 QoS 调度与隔离的实操复盘。导语:在主导一艘国际客滚船的网络重构项目时,我们面临一个典型的高并发调度与合规挑战&…...

RAG检索体系①【第十一篇】:混合检索架构(BM25+向量+过滤),工业级召回落地方案

生产级 RAG 避坑实战合集【第十一篇】文章简介:前十篇我们彻底打通数据层改写层:文档清洗、Chunk切块、元数据、生命周期、Query双层改写。绝大多数人做完这些,直接无脑上单向量检索。线上投产全部翻车。本文直击行业痛点:纯向量检…...

c++11的初见

列表初始化 c11以后支持{ }的列表初始可以使用{ }括住数据来进行初始化&#xff0c;使用{ }初始化时可以省略号{ }中的数据要匹配构造&#xff1b;使用{ }可以统一初始化方式。#include<iostream> #include<vector> using namespace std; int main(){vector<pai…...

YOLO26优化:TIP2026 FourierSR | FourierSR引入YOLO C3k2:解决感受野局限,实现高效全局特征交互

💡💡💡现有 YOLO C3k2 模块主要基于卷积与跨阶段部分连接,虽能平衡计算与精度,但仍存在以下问题: 感受野受限:堆叠的小核卷积(如 33)感受野有限,难以捕获全局上下文,对尺度变化大或远距离依赖的目标(如小目标、遮挡目标)特征提取能力不足。 特征混合效率低:通…...

基于 HarmonyOS 6.0 的智能家政预约页面实战开发:从页面构建到跨端体验优化

基于 HarmonyOS 6.0 的智能家政预约页面实战开发&#xff1a;从页面构建到跨端体验优化 前言 随着 HarmonyOS 生态不断完善&#xff0c;HarmonyOS 6.0 已经不仅仅是一个移动端操作系统&#xff0c;而是逐渐演变为一个真正意义上的全场景分布式操作平台。对于开发者而言&#xf…...

基于 HarmonyOS 6.0 的家政服务预约页面实战开发:ArkUI 页面构建与跨端设计深度解析

基于 HarmonyOS 6.0 的家政服务预约页面实战开发&#xff1a;ArkUI 页面构建与跨端设计深度解析 前言 随着 HarmonyOS 生态逐渐成熟&#xff0c;HarmonyOS NEXT 与 HarmonyOS 6.0 的持续推进&#xff0c;越来越多开发者开始从传统 Android、Flutter、Web 技术栈逐步迁移到鸿蒙原…...

Ubuntu 下 P106-100 矿卡 `nvidia-smi No devices were found` 问题解决全过程

Ubuntu 下 P106-100 矿卡 nvidia-smi No devices were found 问题解决全过程 最近折腾一张老矿卡 P106-100,在 Ubuntu 下遇到一个非常经典的问题: nvidia-smi No devices were found但是: lspci | grep -i nvidia却能看到显卡: 01:00.0 3D controller: NVIDIA Corporat…...

《龙虾OpenClaw系列:从嵌入式裸机到芯片级系统深度实战60课》060、未来趋势与芯片设计者的思考

OpenClaw系列总结:未来趋势与芯片设计者的思考 昨晚调试一块RISC-V核的cache一致性,波形里看到一条store指令被莫名其妙地重复执行了两次。我盯着GTKWave看了半小时,最后发现是写缓冲的valid信号在复位释放后没有清零——一个典型的“芯片级”bug,在嵌入式裸机里永远不会遇…...

3分钟学会:免费飞书文档转Markdown终极指南

3分钟学会&#xff1a;免费飞书文档转Markdown终极指南 【免费下载链接】cloud-document-converter Convert Lark Doc to Markdown 项目地址: https://gitcode.com/gh_mirrors/cl/cloud-document-converter 想象一下&#xff0c;你花了好几个小时在飞书上精心排版的技术…...