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

如何向XSSFGroupShape添加多个图像

商运锋
2023-03-14

正在尝试向XSSFGroupShape添加多个图像。我尝试了以下方法(为了简单起见修改了):

    import lombok.Getter;
    import lombok.Setter;
    import lombok.experimental.Accessors;

    private void addImagesToGroupShape(Sheet sheet, List<XSSFGroupImage> groupImages) throws Exception{
        // XSSFGroupShape dimension
        int dx1 = 180975;
        int dy1 = 409575;
        int dx2 = 219075;
        int dy2 = 638175;
        int row1 = 9;
        int col1 = 8;
        int row2 = 38;
        int col2 = 19;
        XSSFDrawing drawing = (XSSFDrawing) sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor = drawing.createAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2);
        XSSFShapeGroup shapeGroup = drawing.createGroup(anchor);
        
        // XSSFGroupImage is a custom class
        // Included below
        for (XSSFGroupImage groupImage : groupImages) {
            byte[] imageData = Base64.getDecoder().decode(groupImage.data().getBytes());
            
            int picType = 1;
            switch (groupImage.extension()) {
            case "jpeg":
                picType = Workbook.PICTURE_TYPE_JPEG;
                break;
            case "png":
                picType = Workbook.PICTURE_TYPE_PNG;
                break;
            case "emf":
                picType = Workbook.PICTURE_TYPE_EMF;
                break;
            default:
                var msg = "Extension not supported";
                throw new Exception(msg);
            }

            int pictureIndex = sheet.getWorkbook().addPicture(imageData, picType);
           
            // shapeGroup.createPicture(anchor, pictureIndex);

            CTPicture ctPic = shapeGroup.getCTGroupShape().insertNewPic(pictureIndex);

            CTTransform2D ct2D = ctPic.addNewSpPr().addNewXfrm();
            ct2D.addNewOff();
            ct2D.addNewExt();

            ct2D.getOff().setX(groupImage.offsetX());
            ct2D.getOff().setY(groupImage.offsetY());
            ct2D.getExt().setCx(Long.parseLong(groupImage.extentsCx()));
            ct2D.getExt().setCy(Long.parseLong(groupImage.extentsCy()));

            XSSFChildAnchor childAnchor = new XSSFChildAnchor(Integer.parseInt(groupImage.offsetX()),
                    Integer.parseInt(groupImage.offsetY()), Integer.parseInt(groupImage.extentsCx()),
                    Integer.parseInt(groupImage.extentsCy()));

            // shapeGroup.getCTGroupShape().addNewPic();
            // shapeGroup.createPicture(childAnchor, picIndex);

            // ctPic.addNewBlipFill().addNewBlip().setEmbed("");
        }
    }

    @Accessors(fluent = true)
    public class XSSFGroupImage {
        @Getter
        @Setter
        private String data;
        @Getter
        @Setter
        private String extension;
        @Getter
        @Setter
        private String offsetX;
        @Getter
        @Setter
        private String offsetY;
        @Getter
        @Setter
        private String extentsCx;
        @Getter
        @Setter
        private String extentsCy;
    }

我还尝试使用int pictureIndex=Sheet.GetWorkbook().AddPicture(imageData,picType)将图像添加到工作簿中,并使用该索引使用ShapeGroup.GetCTGroupShape().InsertNewPic(pictureIndex)设置CTPicture。但是,通过这样做,将不会设置指向该图像的relationid,从而不会显示任何图像。

所需输出的图像


共有1个答案

程俊健
2023-03-14

XSSFShapeGroup直到现在才完成(Apache 5.0.02021年5月)。

但如果图片应该在该组中,则必须首先使用workbook.addpicture在工作簿级别创建这些图片。没有办法绕过。

有了图片ID,就可以使用XSSFShapeGroup.createPicture将图片放入组中。在那里,XSSFClientAnchor直到现在都没用,可以简单地new XSSFClientAnchor()。然而,为XSSFClientAnchor设置的其他内容将不起作用,无论是图片大小还是组中的位置。因此,在xssfpicture picture=ShapeGroup.CreatePicture(new XSSFClientAnchor(),pictureIdx1);之后,picture将位于位置0,0,大小为0,0。

可以使用xssfpicture.resize设置大小。如果这是不可能的,那么它必须以EMU为单位进行计算,并使用低级别的OOXML类进行设置。例如沿着…的路线

...
XSSFPicture picture = shapeGroup.createPicture(new XSSFClientAnchor(), pictureIdx1);
picture.getCTPicture().getSpPr().getXfrm().getExt().setCx(widthInEMU);
picture.getCTPicture().getSpPr().getXfrm().getExt().setCy(heightInEMU);
...

必须使用低级OOXML类设置该位置。对于位置X和Y也以emu为测量单位。例如:

...
picture.getCTPicture().getSpPr().getXfrm().getOff().setX(xInEMU);
picture.getCTPicture().getSpPr().getXfrm().getOff().setY(yInEMU);
...

因此,让我们提供一个完整的示例。以下使用Apache poi 5.0.0工作(已测试)。请注意:图像文件image1.jpegimage2.jpeg的本机大小不应大于组帧的锚点。

java prettyprint-override">import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;

import java.io.FileInputStream;
import java.io.FileOutputStream;

class CreateExcelXSSFShapeGroup {

 public static void main(String[] args) throws Exception{

  Workbook workbook = new XSSFWorkbook();

  CreationHelper helper = workbook.getCreationHelper();

  //add picture data to this workbook.
  FileInputStream is = new FileInputStream("./image1.jpeg");
  byte[] bytes = IOUtils.toByteArray(is);
  int pictureIdx1 = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
  is.close();
  is = new FileInputStream("./image2.jpeg");
  bytes = IOUtils.toByteArray(is);
  int pictureIdx2 = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
  is.close();

  Sheet sheet = workbook.createSheet("Sheet1");

  Drawing drawing = sheet.createDrawingPatriarch();

  //From here on XSSF only.
  XSSFDrawing xssfdrawing = (XSSFDrawing)drawing;
  XSSFClientAnchor anchor = (XSSFClientAnchor)helper.createClientAnchor();

  int groupShapeStartsAtCol = 1;
  int groupShapeStartsAtRow = 1;
  anchor.setCol1(groupShapeStartsAtCol);
  anchor.setRow1(groupShapeStartsAtRow); 
  int groupWidthInCols = 8;
  anchor.setCol2(groupShapeStartsAtCol + groupWidthInCols);
  int groupHeightInRows = 20;
  anchor.setRow2(groupShapeStartsAtRow + groupHeightInRows);

  XSSFShapeGroup shapeGroup = xssfdrawing.createGroup(anchor); // group shape is now of size from anchor abowe

  XSSFPicture picture = shapeGroup.createPicture(new XSSFClientAnchor(), pictureIdx1);
  //picture.resize(); // picture is now at pos 0, 0 (top left) of group shape and of it's native size
  picture.getCTPicture().getSpPr().getXfrm().getExt().setCx(1234567);
  picture.getCTPicture().getSpPr().getXfrm().getExt().setCy(1234567); // picture is now at pos 0, 0 (top left) of group shape and of size 1234567 x 1234567 EMU
  
  picture = shapeGroup.createPicture(new XSSFClientAnchor(), pictureIdx2);
  picture.resize(); // picture is now at pos 0, 0 (top left) of group shape and of it's native size

  // picture shall be at position bottom right of group shape
  // so top left of picture must be at x = group width - picture width and y = group height - picture height
  int pictureWidthInPx = (int)Math.round(picture.getImageDimension().getWidth());
  int pictureHeightInPx = (int)Math.round(picture.getImageDimension().getHeight());
  int defaultColWidthInPx = Math.round(sheet.getColumnWidthInPixels(0));
  int defaultRowHeightInPx = Units.pointsToPixel(sheet.getDefaultRowHeightInPoints()); 
 
  int xInEMU = Units.pixelToEMU(groupWidthInCols * defaultColWidthInPx - pictureWidthInPx);
  picture.getCTPicture().getSpPr().getXfrm().getOff().setX(xInEMU);
  int yInEMU = Units.pixelToEMU(groupHeightInRows * defaultRowHeightInPx - pictureHeightInPx);
  picture.getCTPicture().getSpPr().getXfrm().getOff().setY(yInEMU);

  FileOutputStream out = new FileOutputStream("CreateExcelXSSFShapeGroup.xlsx");
  workbook.write(out);
  out.close();
  workbook.close();

 }
}
 类似资料:
  • 我想在我的pandas条形图中添加百分比值-以及计数。然而,我不能这样做。我的代码如下所示,到目前为止,我可以得到要显示的计数值。有人能帮我在每个条显示的计数值旁边/下面添加相对%值吗? 我的代码的输出如下所示。如何在显示的每个计数值旁边添加%值?

  • 问题内容: 我是ReactJS和JSX的新手,下面的代码有一些问题。 我试图将多个类添加到每个属性: 我的React组件是: 问题答案: 当确定(不)使用的类需要大量逻辑时,我使用类名。一个 过于简单的例子 : 就是说,如果您不想包含依赖项,那么下面会有更好的答案。

  • 问题内容: 我是ReactJS和JSX的新手,下面的代码有一些问题。 我试图将多个类添加到每个属性: 我的React组件是: 问题答案: 当确定(不)使用的类需要大量逻辑时,我使用类名。一个 过于简单的例子 : 就是说,如果您不想包含依赖项,那么下面会有更好的答案。

  • 注意:“else”语句只是出于测试目的,似乎表明if语句没有正常工作,因为当我测试时,它总是被触发。

  • 假设我有以下代码: 我怎样才能使它对打字和计算都更有效?

  • 问题内容: 问题答案: 您必须向JLabel提供一个实现(即)。您可以通过方法(如您的问题)中的方法或通过构造函数来执行此操作: 我建议你阅读的Javadoc ,和。另外,您可以查看“ 如何使用标签教程 ”以获取更多信息。