How to get SVG picture data from excel that has been automatically converted to PNG

Viewed 98

Excel automatically converts SVG to PNG and saves both the copies.

When we use apache poi v5.0.0to fetch the picture data,

XSSFPicture picture = (XSSFPicture) shape;
System.out.println(picture.getPictureData().suggestFileExtension()); // output: png

we get the PNG format of the picture.

If we want to get the original SVG picture data, we can make use of the following method(Traversal taken from here):

private void traverseShapeContainer(ShapeContainer<XSSFShape> container) {
        for (XSSFShape shape : container) {
            if (shape instanceof XSSFConnector) {
                
            } else if (shape instanceof XSSFGraphicFrame) {

            } else if (shape instanceof XSSFPicture) {
                XSSFPicture picture = (XSSFPicture) shape;
                System.out.println(picture.getPictureData().suggestFileExtension());
                if (picture.getPictureData().suggestFileExtension().equals("png")) {
                    XSSFPictureData svgPictureData = getSVGPicture(picture);
                    if (Objects.nonNull(svgPictureData)) {
                        byte[] svgData = svgPictureData.getData();
                    }
                }
            } else if (shape instanceof XSSFShapeGroup) { // we have a shape group
                XSSFShapeGroup shapeGroup = (XSSFShapeGroup) shape;
                System.out.println(shapeGroup);
                traverseShapeContainer(shapeGroup);
            } else if (shape instanceof XSSFSimpleShape) {
            
            }
        }
    }

    private XSSFPictureData getSVGPicture(XSSFPicture picture) {
        CTOfficeArtExtensionList extLst = picture.getCTPicture().getBlipFill().getBlip().getExtLst();
        if (Objects.nonNull(extLst)) {
            List<CTOfficeArtExtension> extList = extLst.getExtList();
            for (var ext : extList) {
                var extNodes = ext.getDomNode().getChildNodes();
                for (int i = 0; i < extNodes.getLength(); i++) {
                    var extNode = extNodes.item(i);
                    if (extNode.getNodeName().equals("asvg:svgBlip")) {
                        var attr = extNode.getAttributes().getNamedItem("r:embed");
                        if (Objects.nonNull(attr)) {
                            String relationId = attr.getNodeValue();
                            // accesses the drawings.xml.rels to get the data corresponding to the relationId
                            XSSFPictureData svgPictureData = (XSSFPictureData) picture.getDrawing()
                                    .getRelationById(relationId);
                            System.out.println(svgPictureData.suggestFileExtension()); // output: svg
                            return svgPictureData;
                        }
                    }
                }
            }
        }
        return null;
    }

This definitely solves the problem, however is there a better approach to geting the SVG picture data?

0 Answers
Related