JAVA读取从WPS在Excel中嵌入的图片资源

读取从WPS在Excel中嵌入的图片资源


引言

许多数据文件中可能包含嵌入式图片,这些图片对于数据分析和可视化非常重要。然而,从 WPS 在 Excel 中读取这些图片可能会有一些技术挑战。在本文中,我将展示如何从 WPS Excel 文件中读取嵌入的图片,并提供代码示例。

提取图片资源的方法

以下是用于从 WPS Excel 文件中读取图片资源的方法。我们使用了 Apache POI 库来处理 Excel 文件,并使用了 cn.hutool.json 库来处理 XML 数据。这些库可以帮助我们解析 Excel 文件中的嵌入式图片。
在这里插入图片描述

主函数

首先,我们定义了主函数 main,用于测试图片提取功能:

public static void main(String[] args) {PicturesUtils picturesUtils = new PicturesUtils();byte[] fileData = picturesUtils.getFileStream(new File("你的文件路径"));Map<String, XSSFPictureData> pictures = picturesUtils.getPictures(fileData);pictures.forEach((id, xssfPictureData) -> {System.out.println("id:" + id);String fileName = xssfPictureData.getPackagePart().getPartName().getName();System.out.println("fileName:" + fileName);File file = new File("D:\\" + fileName);File dir = file.getParentFile();dir.mkdirs();try {Files.write(Path.of(file.getPath()), xssfPictureData.getData());} catch (IOException e) {e.printStackTrace();}});
}

在这个函数中,我们创建了一个 PicturesUtils 实例,并从文件路径中获取文件数据。然后,我们调用 getPictures 方法来提取图片资源,并遍历结果将图片写入本地文件。

获取浮动图片

接下来,我们展示了如何从 Excel 文件中获取浮动图片:

public static Map<String, XSSFPictureData> getFloatingPictures(XSSFSheet xssfSheet) {Map<String, XSSFPictureData> mapFloatingPictures = new HashMap<>();XSSFDrawing drawingPatriarch = xssfSheet.getDrawingPatriarch();if (drawingPatriarch != null) {List<XSSFShape> shapes = drawingPatriarch.getShapes();for (XSSFShape shape : shapes) {if (shape instanceof XSSFPicture picture) {XSSFClientAnchor anchor = (XSSFClientAnchor) picture.getAnchor();XSSFPictureData pictureData = picture.getPictureData();String key = anchor.getRow1() + "-" + anchor.getCol1();mapFloatingPictures.put(key, pictureData);}}}return mapFloatingPictures;
}

该方法接收一个 XSSFSheet 对象,并返回一个包含浮动图片的映射。它遍历工作表中的所有形状,并将图片数据存储在映射中。

处理图片数据

最后,我们展示了如何处理 Excel 文件中的图片数据,包括嵌入式图片和浮动式图片:

public Map<String, XSSFPictureData> getPictures(byte[] data) {try {Map<String, String> mapConfig = processZipEntries(new ByteArrayInputStream(data));Map<String, XSSFPictureData> mapPictures = processPictures(new ByteArrayInputStream(data), mapConfig);Iterator<Sheet> sheetIterator = WorkbookFactory.create(new ByteArrayInputStream(data)).sheetIterator();while (sheetIterator.hasNext()) {mapPictures.putAll(getFloatingPictures((XSSFSheet) sheetIterator.next()));}return mapPictures;} catch (IOException e) {return new HashedMap<>();}
}

在该方法中,我们使用 processZipEntries 和 processPictures 方法来处理 Zip 文件中的条目和图片数据。然后,通过遍历 Excel 文件中的所有工作表,获取浮动图片。

完整代码示例

实际在程序中读取的内容为=DISPIMG(“ID_03BC802DDAB24510A9883DB157EAC0F8”,1)公式
将公式中的id提取出来ID_03BC802DDAB24510A9883DB157EAC0F8,最后就可以使用下面方法拿到当前id获取到的图片资源

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.XML;
import com.szjyrs.business.exhibition.product.domain.vo.ProductPlusImportLogVo;
import com.szjyrs.common.core.dev.method.MethodStatus;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;/*** @author bianhl* @version 1.0* @description 获取图片资源* @date 2024年4月28日08:44:42*/
@Slf4j
public class PicturesUtils {public static void main(String[] args) {PicturesUtils picturesUtils = new PicturesUtils();byte[] fileData = picturesUtils.getFileStream(new File("你的文件路径"));Map<String, XSSFPictureData> pictures = picturesUtils.getPictures(fileData);pictures.forEach((id, xssfPictureData) -> {System.out.println("id:" + id);String fileName = xssfPictureData.getPackagePart().getPartName().getName();System.out.println("fileName:" + fileName);File file = new File("D:\\" + fileName);File dir = file.getParentFile();dir.mkdirs();try {Files.write(Path.of(file.getPath()), xssfPictureData.getData());} catch (IOException e) {e.printStackTrace();}});}/*** 获取浮动图片,以 map 形式返回,键为行列格式 x-y。** @param xssfSheet WPS 工作表* @return 浮动图片的 map*/public static Map<String, XSSFPictureData> getFloatingPictures(XSSFSheet xssfSheet) {Map<String, XSSFPictureData> mapFloatingPictures = new HashMap<>();XSSFDrawing drawingPatriarch = xssfSheet.getDrawingPatriarch();if (drawingPatriarch != null) {List<XSSFShape> shapes = drawingPatriarch.getShapes();for (XSSFShape shape : shapes) {if (shape instanceof XSSFPicture picture) {XSSFClientAnchor anchor = (XSSFClientAnchor) picture.getAnchor();XSSFPictureData pictureData = picture.getPictureData();String key = anchor.getRow1() + "-" + anchor.getCol1();mapFloatingPictures.put(key, pictureData);}}}return mapFloatingPictures;}/*** 处理 WPS 文件中的图片数据,返回图片信息 map。** @param stream    输入流* @param mapConfig 配置映射* @return 图片信息的 map* @throws IOException*/private Map<String, XSSFPictureData> processPictures(ByteArrayInputStream stream, Map<String, String> mapConfig) throws IOException {Map<String, XSSFPictureData> mapPictures = new HashedMap<>();Workbook workbook = WorkbookFactory.create(stream);List<XSSFPictureData> allPictures = (List<XSSFPictureData>) workbook.getAllPictures();for (XSSFPictureData pictureData : allPictures) {PackagePartName partName = pictureData.getPackagePart().getPartName();String uri = partName.getURI().toString();if (mapConfig.containsKey(uri)) {String strId = mapConfig.get(uri);mapPictures.put(strId, pictureData);}}return mapPictures;}/*** 获取 WPS 文档中的图片,包括嵌入式图片和浮动式图片。** @param data 二进制数据* @return 图片信息的 map* @throws IOException*/public Map<String, XSSFPictureData> getPictures(byte[] data) {try {Map<String, String> mapConfig = processZipEntries(new ByteArrayInputStream(data));Map<String, XSSFPictureData> mapPictures = processPictures(new ByteArrayInputStream(data), mapConfig);Iterator<Sheet> sheetIterator = WorkbookFactory.create(new ByteArrayInputStream(data)).sheetIterator();while (sheetIterator.hasNext()) {mapPictures.putAll(getFloatingPictures((XSSFSheet) sheetIterator.next()));}return mapPictures;} catch (IOException e) {return new HashedMap<>();}}/*** 处理 Zip 文件中的条目,更新图片配置信息。** @param stream Zip 输入流* @return 配置信息的 map* @throws IOException*/private Map<String, String> processZipEntries(ByteArrayInputStream stream) throws IOException {Map<String, String> mapConfig = new HashedMap<>();ZipInputStream zipInputStream = new ZipInputStream(stream);ZipEntry zipEntry;while ((zipEntry = zipInputStream.getNextEntry()) != null) {try {final String fileName = zipEntry.getName();if ("xl/cellimages.xml".equals(fileName)) {processCellImages(zipInputStream, mapConfig);} else if ("xl/_rels/cellimages.xml.rels".equals(fileName)) {return processCellImagesRels(zipInputStream, mapConfig);}} finally {zipInputStream.closeEntry();}}return new HashedMap<>();}/*** 处理 Zip 文件中的 cellimages.xml 文件,更新图片配置信息。** @param zipInputStream Zip 输入流* @param mapConfig      配置信息的 map* @throws IOException*/private void processCellImages(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {String content = IOUtils.toString(zipInputStream, StandardCharsets.UTF_8);JSONObject jsonObject = XML.toJSONObject(content);if (jsonObject != null) {JSONObject cellImages = jsonObject.getJSONObject("etc:cellImages");if (cellImages != null) {JSONArray cellImageArray = cellImages.getJSONArray("etc:cellImage");if (cellImageArray == null) {JSONObject cellImageObj = cellImages.getJSONObject("etc:cellImage");if (cellImageObj != null) {cellImageArray = new JSONArray();cellImageArray.add(cellImageObj);}}if (cellImageArray != null) {processImageItems(cellImageArray, mapConfig);}}}}/*** 处理 cellImageArray 中的图片项,更新图片配置信息。** @param cellImageArray 图片项的 JSONArray* @param mapConfig      配置信息的 map*/private void processImageItems(JSONArray cellImageArray, Map<String, String> mapConfig) {for (int i = 0; i < cellImageArray.size(); i++) {JSONObject imageItem = cellImageArray.getJSONObject(i);if (imageItem != null) {JSONObject pic = imageItem.getJSONObject("xdr:pic");if (pic != null) {processPic(pic, mapConfig);}}}}/*** 处理 pic 中的图片信息,更新图片配置信息。** @param pic       图片的 JSONObject* @param mapConfig 配置信息的 map*/private void processPic(JSONObject pic, Map<String, String> mapConfig) {JSONObject nvPicPr = pic.getJSONObject("xdr:nvPicPr");if (nvPicPr != null) {JSONObject cNvPr = nvPicPr.getJSONObject("xdr:cNvPr");if (cNvPr != null) {String name = cNvPr.getStr("name");if (StringUtils.isNotEmpty(name)) {String strImageEmbed = updateImageEmbed(pic);if (strImageEmbed != null) {mapConfig.put(strImageEmbed, name);}}}}}/*** 获取嵌入式图片的 embed 信息。** @param pic 图片的 JSONObject* @return embed 信息*/private String updateImageEmbed(JSONObject pic) {JSONObject blipFill = pic.getJSONObject("xdr:blipFill");if (blipFill != null) {JSONObject blip = blipFill.getJSONObject("a:blip");if (blip != null) {return blip.getStr("r:embed");}}return null;}/*** 处理 Zip 文件中的 relationship 条目,更新配置信息。** @param zipInputStream Zip 输入流* @param mapConfig      配置信息的 map* @return 配置信息的 map* @throws IOException*/private Map<String, String> processCellImagesRels(ZipInputStream zipInputStream, Map<String, String> mapConfig) throws IOException {String content = IOUtils.toString(zipInputStream, StandardCharsets.UTF_8);JSONObject jsonObject = XML.toJSONObject(content);JSONObject relationships = jsonObject.getJSONObject("Relationships");if (relationships != null) {JSONArray relationshipArray = relationships.getJSONArray("Relationship");if (relationshipArray == null) {JSONObject relationshipObj = relationships.getJSONObject("Relationship");if (relationshipObj != null) {relationshipArray = new JSONArray();relationshipArray.add(relationshipObj);}}if (relationshipArray != null) {return processRelationships(relationshipArray, mapConfig);}}return null;}/*** 处理 relationshipArray 中的关系项,更新配置信息。** @param relationshipArray 关系项的 JSONArray* @param mapConfig         配置信息的 map* @return 配置信息的 map*/private Map<String, String> processRelationships(JSONArray relationshipArray, Map<String, String> mapConfig) {Map<String, String> mapRelationships = new HashedMap<>();for (int i = 0; i < relationshipArray.size(); i++) {JSONObject relaItem = relationshipArray.getJSONObject(i);if (relaItem != null) {String id = relaItem.getStr("Id");String value = "/xl/" + relaItem.getStr("Target");if (mapConfig.containsKey(id)) {String strImageId = mapConfig.get(id);mapRelationships.put(value, strImageId);}}}return mapRelationships;}/*** @param file                   数据文件* @return {@link byte[]}* @description* @author bianhl* @date 2024/4/26 13:52*/private byte[] getFileStream(File file) {try (InputStream inputStream = new FileInputStream(file)) {// 创建 ByteArrayOutputStream 来暂存流数据ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 将 inputStream 读取到 byteArrayOutputStream 中byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, length);}// 将 byteArrayOutputStream 的内容获取为字节数组return byteArrayOutputStream.toByteArray();} catch (IOException e) {return null;}}}

输出结果:
在这里插入图片描述
拿到的图片数据
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

海外三大AI图片生成器对比(Stable Diffusion、Midjourney、DALL·E 3)

Stable Diffusion DreamStudio 是Stable Diffusion 的官方网页&#xff0c;价格便宜&#xff0c;对图片的操作性强&#xff0c;但同时编辑页面不太直观&#xff0c;对使用者的要求较高。 与 DALLE 和 Midjourney 不同&#xff0c;Stable Diffusion 是开源的。这也意味着&…

linux tcpdump的交叉编译以及使用

一、源码下载 官网&#xff1a;点击跳转 二、编译 1、解压 tar -xf libpcap-1.10.4.tar.xz tar -xf tcpdump-4.99.4.tar.xz 2、配置及编译 //libpcap&#xff1a; ./configure --hostarm-linux --targetarm-linux CCarm-linux-gcc --with-pcaplinux --prefix$PWD/build//t…

企业如何保证内部传输文件使用的工具是安全的?

企业内部文件的频繁交换成为了日常运营不可或缺的一环。然而&#xff0c;随着数据量的爆炸式增长和网络攻击手段的日益复杂&#xff0c;内网文件传输的安全隐患也日益凸显&#xff0c;成为企业信息安全的薄弱环节。本文将探讨内网文件传输的安全风险、企业常用的防护措施。 内网…

Django之搭配内网穿透

一&#xff0c;安装coplar 二&#xff0c;开启8087的内网穿透 三&#xff0c;setting.py中加入如下配置&#xff1a; ALLOWED_HOSTS [*]CSRF_TRUSTED_ORIGINS ["https://localhost:8087", "http://localhost:8087"]四&#xff0c;启动项目 五&#xff…

STM32之HAL开发——ADC入门介绍

ADC简介 模数转换&#xff0c;即Analog-to-Digital Converter&#xff0c;常称ADC&#xff0c;是指将连续变量的模拟信号转换为离散的数字信号的器件&#xff0c;比如将模温度感器产生的电信号转为控制芯片能处理的数字信号0101&#xff0c;这样ADC就建立了模拟世界的传感器和…

第4篇:创建Nios II工程之Hello_World<三>

Q&#xff1a;接着我们再来完成Nios II软件工程设计部分。 A&#xff1a;从Quartus Tools选择Nios II Software Build Tools for Eclipse&#xff0c;打开Nios II SBT软件&#xff0c;Workspace指定到hello_world工程的software文件夹路径&#xff1b;再从File-->New-->…

Linux命令大全 以及搭建hadoop

Liunx系统目录 ├── bin -> usr/bin # 用于存放二进制命令 ├── boot # 内核及引导系统程序所在的目录 ├── dev # 所有设备文件的目录&#xff08;如磁盘、光驱等&#xff09; ├── etc # 配置文件默认路径、服务启动命令存放目录 ├── home # 用户家目录&#…

上位机图像处理和嵌入式模块部署(树莓派4b设置ftp下载)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 作为一个开发板&#xff0c;最好支持ftp下载&#xff0c;这样文件的上传和下载都会比较方便。虽然目前为止&#xff0c;利用mobaxterm和ssh也能实现…

ObjectARX特性面板OPM添加动态属性

参考资料 AutoCAD与动态属性PDF文档 https://www.progdomain.com/584/ObjectARX2016 OPM面板全攻略 https://blog.csdn.net/jfmyes/article/details/121392332 准备工作——正确安装ARX和Wizards ARX和VS的版本对应、ObjectArx(2010~2020)工程创建、类添加及错误处理 https:…

《从Paxos到Zookeeper》——第四、七章:基本概念及原理

目录 第四章 Zookeeper与Paxos 4.1 Zk是什么 4.1.1 Zk特性 4.1.2 Zk基本概念 4.1.2.1 集群角色(Follower, Leader, Observer) 4.1.2.2 数据模型 4.1.2.3 ZNode(数据节点) 4.1.2.4 Session(会话) 4.1.2.5 ACL&#xff08;Access Control Lists&#xff09; 4.1.2.6 Watcher(事件…

如何用OceanBase的 Load Data 导入CSV文件

0 前言 CSV文件&#xff08;Comma-Separated Values&#xff0c;字符分隔值&#xff09;是一种普遍采用的数据存储格式&#xff0c;有不少企业和机构都用它来进行数据的管理和存储。身为开发者&#xff0c;您可能经常遇到这样的需求&#xff1a;需要将CSV的数据导入OceanBase数…

OpenCV如何实现背投

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV直方图比较 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是背投以及它为什么有用如何使用 Ope…

stm32单片机开发二、定时器-内部时钟中断和外部时钟中断、编码器

定时器本质就是一个计数器 案例&#xff1a;定时器定时中断 内部时钟中断 Timer_Init(); //定时中断初始化 /*** 函 数&#xff1a;定时中断初始化* 参 数&#xff1a;无* 返 回 值&#xff1a;无*/ void Timer_Init(void) {/*开启时钟*/RCC_APB1PeriphClockCmd(RCC…

纯血鸿蒙APP实战开发——Navigation实现多设备适配案例

介绍 在应用开发时&#xff0c;一个应用需要适配多终端的设备&#xff0c;使用Navigation的mode属性来实现一套代码&#xff0c;多终端适配。 效果图预览 使用说明 将程序运行在折叠屏手机或者平板上观看适配效果。 实现思路 本例涉及的关键特性和实现方案如下&#xff1a…

HTML5(2)

目录 一.列表、表格、表单 1.列表标签 2.表格 4.无语义的布局标签 5.字符实体 6.综合案例--1 7.综合案例--表单 一.列表、表格、表单 1.列表标签 1.1 无序列表 1.2 有序列表 1.3 定义列表 定义列表一般用于网页底部的帮助中心 2.表格 2.1 2.2 表格结构标签 shiftaltf 格…

创建基于时间的 UUID

概述 在本文中&#xff0c;我们将会 对 UUIDs 和基于时间的 UUIDs&#xff08;time-based UUIDs&#xff09; 进行一些探讨。 当我们在对基于时间的 UUIDs 进行选择的时候&#xff0c;总会遇到一些好的方面和不好的方面&#xff0c;如何进行选择&#xff0c;也是我们将要简要…

2路模拟音频光端机 JR-CA02

概述 JR-CA02光端机由发送机JR-CA02 Tansmitter和接收机JR-CA02 Receiver组成&#xff0c;通过一定距离长度的光纤相连接&#xff0c;传输2路Audio模拟音频&#xff08;即1路立体声&#xff09;。且每路音频分配输出。 JR-CA02光端机具有运行主要技术参数的监测功能&#xff…

【AGX】Ubuntu20.04 + ROS_ noetic+ 大疆Mid360激光 雷达评测

大家好&#xff0c;我是虎哥&#xff0c;最近组装机器人&#xff0c;使用到了大疆孵化的圳市览沃科技有限公司&#xff08;简称Livox览沃科技&#xff09;推出的觅道系列全新混合固态激光雷达Mid-360&#xff0c;顺便试试效果&#xff0c;也记录一下使用入门过程。 "觅道M…

MATLAB : interp1()用法介绍

目录 一、基本语法&#xff1a; 二、实例&#xff1a; 1.样条拟合减振器阻尼曲线 ​2.PP拟合时间温度曲线 interp1 是 MATLAB 中的一个函数&#xff0c;用于在一维数据上执行插值操作。这个函数可以帮助你估计或计算已知数据点之间未知点的值。以下是 interp1 函数的基本用…

分类预测 | Matlab实现POA-BP鹈鹕算法优化BP神经网络多特征分类预测

分类预测 | Matlab实现POA-BP鹈鹕算法优化BP神经网络多特征分类预测 目录 分类预测 | Matlab实现POA-BP鹈鹕算法优化BP神经网络多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现POA-BP鹈鹕算法优化BP神经网络多特征分类预测&#xff08;Matlab实…