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

这篇具有很好参考价值的文章主要介绍了JAVA读取从WPS在Excel中嵌入的图片资源。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

提取图片资源的方法

以下是用于从 WPS Excel 文件中读取图片资源的方法。我们使用了 Apache POI 库来处理 Excel 文件,并使用了 cn.hutool.json 库来处理 XML 数据。这些库可以帮助我们解析 Excel 文件中的嵌入式图片。
JAVA读取从WPS在Excel中嵌入的图片资源,JAVA,java,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;
        }
    }


}

输出结果:
JAVA读取从WPS在Excel中嵌入的图片资源,JAVA,java,excel,数据处理
拿到的图片数据
JAVA读取从WPS在Excel中嵌入的图片资源,JAVA,java,excel,数据处理文章来源地址https://www.toymoban.com/news/detail-861061.html

到了这里,关于JAVA读取从WPS在Excel中嵌入的图片资源的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity 图片资源的适配

    最近小编做Unity项目时,发现在资源处理这方面和Android有所不同;例如:Android的资源文件夹res下会有着mipmap-mdpi,mipmap-hdpi,mipmap-xhdpi,mipmap-xxhdpi,mipmap-xxxhdpi这五个文件夹,这是因为我们一般在蓝湖UI设计图上下载的图片资源都是对应这五种分辨率的图片,而在Unity中,图片

    2024年02月11日
    浏览(40)
  • python打包,图片资源打包

    1,安装pyinstaller pip install pyinstaller *,新配置的python环境,出现了两个报错 第一个通过修改配置文件解决 Invoke-Expression : 无法将参数绑定到参数“Command”,因为该参数为空字符串。 所在位置 C:Usersxxxminiconda3shellcondabinCond_invoke-expression : 所在位置 行:1 字符: 254 + ... engana

    2024年02月13日
    浏览(47)
  • Webpack5 处理图片资源

    过去在 Webpack4 时,我们处理图片资源通过 file-loader 和 url-loader 进行处理 现在 Webpack5 已经将两个 Loader 功能内置到 Webpack 里了,我们只需要简单配置即可处理图片资源 src/images/1.jpeg src/images/2.png src/images/3.gif src/less/index.less src/sass/index.sass src/styl/index.styl 打开 index.html 页面查看

    2024年02月13日
    浏览(42)
  • 05_Unity动态加载图片资源

    本文归纳了Unity中加载图片资源的常用方法,包括url和本地路径的加载。 在工具类中封装如下方法: 一般是放在单例中,如:GameManager 创建一个Image物体 在本地存放一张图片,Guide1.png 放置在: Resources/Image/Guide1.png 路径下 在物体上挂接一个测试脚本 执行前: 执行后: 还是刚

    2024年02月05日
    浏览(116)
  • vue如何动态加载显示本地图片资源

    在实际开发中,根据某一个变量动态展示图片的情况有很多。实现方法分打包构建工具的差异而不同。 1、webpack的项目 require引入图片资源 2、vite的项目 new URL(url,base).href 疑问解答:为什么vite项目不可以用require? 原因在于,vite的模块化规范是ES Modules,所以vite项目在打包构建

    2024年02月22日
    浏览(55)
  • 如何在Qt项目中引入图片资源

    首先,在Qt项目里创建一个目录 icon ,然后将图片资源放 icon 目录中 在Qt creator中创建resource file 右键项目 myqtdesign Add New... Qt Qt Resource File 输入文件名 myimage ,并在 CMakeLists.txt 加入 myimage.qrc 并保存(control + s) 3. 添加前缀 /images 右键 myimage.qrc 文件 Add Prefix... ,结果如下图: 添

    2024年02月13日
    浏览(51)
  • uniapp选取本地资源(图片,视频,文件)

    从本地相册选择图片或使用相机拍照。 App端如需要更丰富的相机拍照API(如直接调用前置摄像头),参考plus.camera OBJECT 参数说明 参数名 类型 必填 说明 平台差异说明 count Number 否 最多可以选择的图片张数,默认9 见下方说明 sizeType ArrayString 否 original 原图,compressed 压缩图,

    2024年02月11日
    浏览(52)
  • Vite静态资源处理——动态引入图片

    服务时引入一个静态资源会返回解析后的公共路径: 导入既可以使用绝对公共路径(基于开发期间的项目根路径),也可以使用相对路径。 vite 生产构建后文件名会哈希,如图: import.meta.url 是一个 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的 URL 构造器 组合使用,

    2024年02月10日
    浏览(44)
  • Qt5.15.2中加入图片资源

    以前用的Qt5.15.2之前的版本,QtCreator默认的工程文件是*.pro,现在用5.15.2创建工程默认的工程文件是CMameList.txt,当然在创建项目时,仍然可以使用pro工程文件用QtCreator打开CMakeList.txt 以前用习惯了pro文件,现在改成CMakeList很不习惯,现在我们在CMakeList.txt中加入资源文件 1.首先,

    2024年01月22日
    浏览(57)
  • Android Studio开发之路(二)添加图片资源

    第一步:复制要添加的图片 第二步:右键点击项目的res-drawable目录,选择paste粘贴 选择drawable目录 问你是否确定要复制,点击ok即可 然后就可以看到在drawable目录下出现了复制的图片 然后在xml中添加代码就可以显示在界面上了

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包