当前位置: 代码网 > it编程>编程语言>Java > 利用Java实现读取WPS Excel中嵌入的图片

利用Java实现读取WPS Excel中嵌入的图片

2024年11月18日 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获取到的图片资源 jdk版本17

import cn.hutool.json.jsonarray;
import cn.hutool.json.jsonobject;
import cn.hutool.json.xml;
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 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("c:\\users\\xxx\\desktop\\" + 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 = null;
                object cellimage = cellimages.get("etc:cellimage");
                if (cellimage != null && cellimage instanceof jsonarray) {
                    cellimagearray = (jsonarray) cellimage;
                } else if (cellimage != null && cellimage instanceof jsonobject cellimageobj) {
                    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 = null;
            object relationship = relationships.get("relationship");

            if (relationship != null && relationship instanceof jsonarray) {
                relationshiparray = (jsonarray) relationship;
            } else if (relationship != null && relationship instanceof jsonobject relationshipobj) {
                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读取excel嵌入的图片的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com