java读取wps嵌入式图片思路

这个只写了思路具体代码在文章最后,不想了解得直接去拿代码

  1. 了解Excel数据结构

Excel 文件格式后缀xls,xlsx 其实是一个压缩文件,是由多个文件夹以及xml 文件组程,xml文件记录了Excel得内容以及样式等信息。现在在桌面新建一个xlsx文件,插入一个嵌入式图片,文件后缀为.zip ,然后解压我们得到以下一个文件夹

可以看到又几个文件夹以及xml,,poi 不能读取wps嵌入式图片,是因为这个cellimages是wps自己独有得并不属于office标准,新增一个悬浮图片然后解压得到以下一个文件列表

会有一个drawings得文件夹,这个是office支持得格式正常获取图片是可以的 ,直接使用poi 的api 就可以获取到,自己去百度吧

复制代码
<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
<xdr:twoCellAnchor editAs="oneCell">
<xdr:from>
<xdr:col>6</xdr:col>
<xdr:colOff>0</xdr:colOff>
<xdr:row>4</xdr:row>
<xdr:rowOff>0</xdr:rowOff>
</xdr:from>
<xdr:to>
<xdr:col>21</xdr:col>
<xdr:colOff>548640</xdr:colOff>
<xdr:row>46</xdr:row>
<xdr:rowOff>7620</xdr:rowOff>
</xdr:to>
<xdr:pic>
<xdr:nvPicPr>
<xdr:cNvPr id="2" name="图片 1"/>
<xdr:cNvPicPr>
<a:picLocks noChangeAspect="1"/>
</xdr:cNvPicPr>
</xdr:nvPicPr>
<xdr:blipFill>
<a:blip r:embed="rId1"/>
<a:stretch>
<a:fillRect/>
</a:stretch>
</xdr:blipFill>
<xdr:spPr>
<a:xfrm>
<a:off x="3703320" y="731520"/>
<a:ext cx="9806940" cy="7688580"/>
</a:xfrm>
<a:prstGeom prst="rect">
<a:avLst/>
</a:prstGeom>
<a:noFill/>
<a:ln w="9525">
<a:noFill/>
</a:ln>
</xdr:spPr>
</xdr:pic>
<xdr:clientData/>
</xdr:twoCellAnchor>
</xdr:wsDr>

打开drawing1.xml 可以看到from 标签记录了图片得位置但是使用wps 生成得cellImages如图一所示

生成得是wps 得自定义标签这个没有from 不存储位置信息但是可以看到ID ID_6702DEA2ADBA44AE8C65065BD13FF23D 这个东西

wps 嵌入单元格信息是这样得,只要找出id和图片对应得信息就可以获取到图片

2.wps xml 中找对应关系

//这个是relations

图片存储在以下得位置:

可以看出 ID 关联了rid ,rid 又和图片关联 比如你上传多个图片一样的,引用得其实是一张图片

3.poi 代码解析找出对应关系

首先就要读取一下这个xml

我是使用xmlBean来解析cellimages.xml pio底层也是用这个

主要过程就是-》基于xml 生成xsd 文件->xsd 文件生成java 代码 -》java 代码解析xml 内容获取关系,rid1和图片路径得关系poi 已经支持不用做,获取图片信息得方法poi 也不用做利用poi的方法就可以获取(不会或者不了解xmlBean得可以自己去学习)

1.根据xml 文件成成xsd 文件 下载 Download trang-20091111.jar : trang << t << Jar File Download

复制代码
java -jar trang.jar cellimages.xml cellimages.xsd

2.下载xmlBean

Apache Download Mirrors

下载完成后解压

利用scomp 指令生成对用得jar 包

XMLBeans Tools 这个是官方文档

运行指令

scomp -out c:\xmltypes.jar c:\cellimages.xsd -compiler C:\java\jdk1.6.0_10\bin\javac customer.xsdconfig

意思是根据xsd 生成java 解析xml 对应得jar customer.xsdconfig内容如下

复制代码
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">   <xb:namespace>   <xb:package>com.chenkang.demo.util.excel</xb:package>   </xb:namespace></xb:config>

然后后得到一个jar 包项目值引入依赖

4.开始代码解析

复制代码
   /**
     * {ID_581F75328A584939A51CC44E17945975:rid1,ID_6702DEA2ADBA44AE8C65065BD13FF23D:rid1}
     * 行rid 以及图片id关系
     *
     * @param cellImagePart cellImagePart
     * @return Map
     * @throws Exception 异常
     */
    public static Map<String, String> getRidAndPidMap(PackagePart cellImagePart) throws Exception {
        CellImagesDocument cellImagesDocument = CellImagesDocument.Factory.parse(cellImagePart.getInputStream());
        CellImagesDocument.CellImages cellImages = cellImagesDocument.getCellImages();
        Map<String, String> result = new HashMap<>(4);
        cellImages.getCellImageList().forEach(cellImage -> {
            result.put(cellImage.getPic().getNvPicPr().getCNvPr().getName().getStringValue(), cellImage.getPic().getBlipFill().getBlip().getEmbed());
        });
        return result;
    }

这个就是解析cellImages.xml 来获取rid 和id 得关系

复制代码
    /**
     *   //relationships 绑定了rid 和 图片 路径得地址
     * 获取rid和path的关系
     * @param packagePart cellImagePart
     * @return Map
     * @throws Exception 异常
     */
    public static Map<String, String> getRidAndPathMap(PackagePart packagePart) throws Exception {
        Map<String, String> ridAndPathMap = new HashMap<>(4);
        PackageRelationshipCollection relationships = packagePart.getRelationships();
        relationships.forEach(relationship -> ridAndPathMap.put(relationship.getId(), relationship.getTargetURI().getPath()));
        return ridAndPathMap;
    }

这个是获取rid 和图片路径得关系

复制代码
    /**
     *图片ID和 XSSFPictureData
     *
     * @param workbook workbook
     * @return List<Map < String, String>>
     * @throws Exception 异常
     */
    public static Map<String, XSSFPictureData> getPictureMap(XSSFWorkbook workbook) throws Exception {
        OPCPackage opcPackage = workbook.getPackage();
        List<PackagePart> partsByContentType = opcPackage.getPartsByContentType("application/vnd.wps-officedocument.cellimage+xml");
        PackagePart packagePart = partsByContentType.get(0);
        List<XSSFPictureData> allPictures = workbook.getAllPictures();
        Map<String,XSSFPictureData> result = new HashMap<>(4);
        Map<String, String> ridAndPidMap = getRidAndPidMap(packagePart);
        Map<String, String> ridAndPathMap = getRidAndPathMap(packagePart);
        ridAndPidMap.forEach((key, value) -> {
            String path = ridAndPathMap.get(value);
            Optional<XSSFPictureData> first = allPictures.stream().filter(pictureData -> pictureData.getPackagePart().getPartName().getName().equals(path)).findFirst();
            result.put(key,first.orElse(null));
        });
        return result;

    }

这一步是来最终映射id 和图片得关系 为什么

List<XSSFPictureData> allPictures = workbook.getAllPictures();

这个能获取图片呢是因为无论是悬浮图片还是嵌入图片他最终都是读取到得是

这个路径

只是说找不到映射关系 再详细得可以去看下源码

最后测试:

复制代码
    public static void main(String[] args) throws Exception {
        File file = new File("C:\\Users\\18151\\Desktop\\test.xlsx");
        XSSFWorkbook sheets = new XSSFWorkbook(file);
        XSSFSheet sheetAt = sheets.getSheetAt(0);
        String id=sheetAt.getRow(1).getCell(1).getStringCellValue();
        Map<String, XSSFPictureData> pictureMap = WpsImageUtil.getPictureMap(sheets);
        System.out.println(pictureMap);
        System.out.println(pictureMap.get(StringExtractor.extractID(id)));
    }

读取文件,获取到cellValue得到得是

=DISPIMG("ID_C13878DEBED44D23AED14F38392FD788",1) 根据工具类拿到id ,然后再根据映射关系获取到得pictureData 这个直接getData()就是文件流该上传完成业务还是干嘛得都可以

完整得代码详见

java 利用poi读取wps嵌入式图片,自测-CSDN博客

相关推荐
专注VB编程开发20年3 天前
WPS 2024 Windows版UI用QT5和自研DirectUI-vba,jsa
qt·vba·wps·jsa·directui
扬帆破浪5 天前
麒麟系统安装察元 WPS AI 文档助手:免费、开源、离线部署说明
人工智能·开源·wps
扬帆破浪5 天前
免费开源的WPS AI 插件,离线安装、多系统与内网模型
人工智能·开源·wps
Evonso5 天前
Excel按照日期隔行颜色规则
wps
hashiqimiya6 天前
wps修改默认的字体号让以后的默认都是4号字体并修改间距
wps
骆驼爱记录7 天前
3步轻松去除WPS段落左侧符号
自动化·word·wps·新人首发
骆驼爱记录7 天前
表格居中无效的5大原因及解决方案
自动化·word·wps·新人首发
热爱生活的五柒9 天前
wps如何配置zotero,目前word中能看到zotero插件,但是wps中看不到
wps·zotero
weifont11 天前
太烧token了,我用Ai写了一个vscode的插件wps-editor(已开源)
人工智能·vscode·wps
骆驼爱记录13 天前
Word目录:标题加粗页码不加粗技巧
自动化·word·excel·wps·新人首发