如何将多个图像添加到 XSSFGroupShape
How to add multiple images to XSSFGroupShape
正在尝试向 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;
}
Added images outside group and .
我了解没有 anchor
就无法附加图像这一事实。但是,我找不到在 XSSFGroupShape
中添加 XSSFChildAnchor
的方法,该方法允许设置 CTTransform2D
对象的属性。
我还尝试使用 int pictureIndex = sheet.getWorkbook().addPicture(imageData, picType)
将图像添加到 Workbook
,并使用该索引使用 shapeGroup.getCTGroupShape().insertNewPic(pictureIndex)
设置 CTPicture
。但是,通过这样做,将指向该图像的 relationId
未被设置,导致没有图像被显示。
Image of desired output
XSSFShapeGroup
直到现在(apache 5.0.0
2021 年 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.jpeg
和 image2.jpeg
的原始大小不应大于组框的锚点。
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();
}
}
正在尝试向 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;
}
Added images outside group and
我了解没有 anchor
就无法附加图像这一事实。但是,我找不到在 XSSFGroupShape
中添加 XSSFChildAnchor
的方法,该方法允许设置 CTTransform2D
对象的属性。
我还尝试使用 int pictureIndex = sheet.getWorkbook().addPicture(imageData, picType)
将图像添加到 Workbook
,并使用该索引使用 shapeGroup.getCTGroupShape().insertNewPic(pictureIndex)
设置 CTPicture
。但是,通过这样做,将指向该图像的 relationId
未被设置,导致没有图像被显示。
Image of desired output
XSSFShapeGroup
直到现在(apache 5.0.0
2021 年 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.jpeg
和 image2.jpeg
的原始大小不应大于组框的锚点。
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();
}
}