当前位置: 首页 > 知识库问答 >
问题:

如何在XSSFWorkBook中添加SVG映像

常鸿朗
2023-03-14
FileInputStream in = new FileInputStream("testWorkbook.xlsx");
XSSFWorkbook wb = (XSSFWorkbook)WorkbookFactory.create(in);
InputStream inputStream = new FileInputStream("/home/test/test1.svg");
//Get the contents of an InputStream as a byte[].
byte[] imageData = IOUtils.toByteArray(inputStream);
// XSSFWorkbook.PICTURE_TYPE_SVG is not supported yet.
int pictureIndex = wb.addPicture(imageData, XSSFWorkbook.PICTURE_TYPE_SVG); // Preferred support

有什么方法可以将SVG映像添加到XSSFWorkbook中吗?

共有1个答案

龙弘济
2023-03-14

SVG的支持是Microsoft Office 365的新功能。这就是为什么直到现在Apache poi还不完全支持它(2021年5月,Apache poi 5.0.0)。

要在Excel中实现这种支持,需要知道Excel如何插入SVG图像。为了向后兼容,它将图像转换为png。它将SVG图像和PNG图像都放入工作簿中。然后,它将png图像显示为绘图中的形状。该形状具有对SVG图像的附加引用,因此如果使用Excel 365,也可以获得SVG图像。

要在Apache POI中实现这种支持,需要以下内容:

>

  • SVGPNG的转换器。那里可以使用阿帕奇蜡染代码转换器。

    扩展的XSSFWorkbook,它提供单独的AddsVGPicture方法,或者在AddPicture方法中提供对SVG的支持。但是扩展xssf...类并不是那么简单,因为有些奇怪的决定将成员或方法设置为私有。

    xssfrelation.image_svg,在创建图片和形状时提供创建关系。但是XSSFRelation完全不可扩展。因此,需要扩展低层POIXMLRelation

    扩展的XSSFPictureData,为新的POIXMLRelation提供对所需图片构造函数的支持。

    下面的代码提供了所有这些。在需要的地方对其进行评论。

    import org.apache.poi.xssf.usermodel.*;
    import org.apache.poi.ss.usermodel.*;
    
    import java.io.InputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    
    class CreateExcelXSSFPictureSVG {
     
     // use org.apache.batik.transcoder to convert SVG to PNG 
     static byte[] svgToPng(InputStream svg) throws Exception {
      org.apache.batik.transcoder.image.PNGTranscoder t = new org.apache.batik.transcoder.image.PNGTranscoder();
      org.apache.batik.transcoder.TranscoderInput input = new org.apache.batik.transcoder.TranscoderInput(svg);
      
      java.io.ByteArrayOutputStream ostream = new java.io.ByteArrayOutputStream();
      org.apache.batik.transcoder.TranscoderOutput output = new org.apache.batik.transcoder.TranscoderOutput(ostream);
    
      t.transcode(input, output);
      ostream.flush();
      
      return ostream.toByteArray();  
     }
        
     public static void main(String[] args) throws Exception {
         
      String svgFilePath = "./Freesample.svg";
      
      MyXSSFWorkbook workbook = new MyXSSFWorkbook(); // see MyXSSFWorkbook.java
    
      // add SVG Image to workbook  
      FileInputStream is = new FileInputStream(svgFilePath);
      int svgPictureIdx = workbook.addSVGPicture(is);
      is.close();
      
      // add PNG image to workbook
      is = new FileInputStream(svgFilePath);
      int pngPictureIdx = workbook.addPicture(svgToPng(is), Workbook.PICTURE_TYPE_PNG);
      is.close();
    
      // create sheet and get drawing
      XSSFSheet sheet = workbook.createSheet("Sheet1");
      XSSFDrawing drawing = sheet.createDrawingPatriarch();
     
      // add SVG Image relation to drawing 
      XSSFPictureData pictureData = workbook.getAllPictures().get(svgPictureIdx);
      org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart rp = drawing.addRelation(null, XSSFRelation.IMAGES, pictureData);
      String svgRId = rp.getRelationship().getId();
    
      // create anchor for picture shape
      XSSFCreationHelper helper = workbook.getCreationHelper();
      XSSFClientAnchor anchor = helper.createClientAnchor();
      anchor.setCol1(1);
      anchor.setRow1(1); 
    
      // create PNG picture shape
      XSSFPicture pngPicture = drawing.createPicture(anchor, pngPictureIdx);
      pngPicture.resize();
      
      // set SVG extension to PNG picture shape
      org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension ext = pngPicture.getCTPicture().getBlipFill().getBlip().addNewExtLst().addNewExt();
      ext.setUri("{96DAC541-7B7A-43D3-8B79-37D633B846F1}");
      org.apache.xmlbeans.XmlCursor cursor = ext.newCursor();
      cursor.toNextToken();
      cursor.toNextToken();
      cursor.beginElement(new javax.xml.namespace.QName("http://schemas.microsoft.com/office/drawing/2016/SVG/main", "svgBlip", "asvg"));
      cursor.insertNamespace("asvg", "http://schemas.microsoft.com/office/drawing/2016/SVG/main");
      cursor.insertAttributeWithValue(new javax.xml.namespace.QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "embed", "r"), svgRId);
      cursor.dispose();
    
      FileOutputStream out = new FileOutputStream("CreateExcelXSSFPictureSVG.xlsx");
      workbook.write(out);
      out.close();
      workbook.close();
    
     }
    }
    

    使用的扩展类:

    myxssfworkbook.java

    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.apache.poi.xssf.usermodel.XSSFPictureData;
    import org.apache.poi.xssf.usermodel.XSSFFactory;
    import org.apache.poi.util.IOUtils;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.List;
    
    import java.lang.reflect.Field;
    
    public class MyXSSFWorkbook extends XSSFWorkbook {
    
     public int addSVGPicture(InputStream is) throws Exception {
      Field _xssfFactory = XSSFWorkbook.class.getDeclaredField("xssfFactory");
      _xssfFactory.setAccessible(true);
      XSSFFactory xssfFactory = (XSSFFactory)_xssfFactory.get(this);
      
      int imageNumber = getAllPictures().size() + 1;
      
      Field _pictures = XSSFWorkbook.class.getDeclaredField("pictures");
      _pictures.setAccessible(true);
      @SuppressWarnings("unchecked")
      List<XSSFPictureData> pictures = (List<XSSFPictureData>)_pictures.get(this);
    
      MyXSSFPictureData img = createRelationship(MyXSSFRelation.IMAGE_SVG, xssfFactory, imageNumber, true).getDocumentPart(); // see MyXSSFPictureData.java and MyXSSFRelation.java
      try (OutputStream out = img.getPackagePart().getOutputStream()) {
       IOUtils.copy(is, out);
      }
      pictures.add(img);
    
      return imageNumber - 1;
     }
    
    }
    
    import org.apache.poi.ooxml.POIXMLRelation;
    import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
    
    public final class MyXSSFRelation extends POIXMLRelation {
    
     public static final MyXSSFRelation IMAGE_SVG = new MyXSSFRelation(
      "image/svg",
      PackageRelationshipTypes.IMAGE_PART,
      "/xl/media/image#.svg",
      MyXSSFPictureData::new, MyXSSFPictureData::new // see MyXSSFPictureData.java
     );
    
     private MyXSSFRelation(String type, String rel, String defaultName,
                          NoArgConstructor noArgConstructor,
                          PackagePartConstructor packagePartConstructor) {
      super(type, rel, defaultName, noArgConstructor, packagePartConstructor, null);
     }
    
    }
    
    import org.apache.poi.openxml4j.opc.PackagePart;
    import org.apache.poi.xssf.usermodel.XSSFPictureData; 
    
    public class MyXSSFPictureData extends XSSFPictureData {
    
     protected MyXSSFPictureData() {
      super();
     }
     
     protected MyXSSFPictureData(PackagePart part) {
      super(part);
     }
    
    }
    

  •  类似资料:
    • 我有一个图标列表。我想把图标的颜色改为白色。默认情况下,我的图标是黑色的。伙计们有什么建议吗?

    • 问题内容: 我有一系列的svg矩形(使用D3.js),我想在鼠标悬停时显示一条消息,该消息应被用作背景的框包围。它们应彼此完全对齐,并与矩形(顶部和中心)完全对齐。做这个的最好方式是什么? 我尝试使用“ x”,“ y”,“ width”和“ height”属性添加svg文本,然后在svg rect之前添加。问题是文本的参考点在中间(因为我想使它居中对齐),但是对于矩形,它是左上角的坐标,而且我想在

    • 问题内容: 我在Ubuntu 14.04的Docker 1.13.1容器中运行ASP.NET Core 1.1 Web API。 当代码尝试从HTTPS服务器检索某些数据时,出现此证书身份验证错误: HTTPS服务器是内部的,具有由公司CA签名的证书,因此请注意,我可能需要注册内部CA。 到目前为止,我已找到有关该错误的所有信息,并且Docker谈到了使Docker本身运行,连接到存储库等。我的D

    • 问题内容: 我有一个包含图像的svg: 如何用字体真棒图标替换该行: 由于图像未显示,因此似乎无法正常工作。 问题答案: 是无效的SVG。您需要包括显示图标的实际字符。如果您查看fontawesome的样式表,您将看到… 但是那些是为CSS编码的unicode字符。在SVG中,您需要将example的语法更改为: 然后在样式表中添加:

    • 问题内容: 我需要将SVG图形添加​​到PDF文件中。 使用iText7是否有可能? 使用iText5: 我在以下页面中发现了这一点: PdfPTable和PdfTemplate 有一种创建类似于Template的方法: 如何创建Graphics2D? 问题答案: 巧合的是,我们今天发布了SVG实现。我们目前尚不支持全部功能集,我们仍将在第二季度及以后的时间里进行开发,但是您已经可以使用它了。该工

    • 我有一个灰色的选项,我必须完成才能完成一个项目。上面说