Reputation: 2338
I am working with the POI API to copy many Excel Workbooks into 1 large Excel Workbook. For one of my requirements there are images that are placed and sized specifically in the document. I am using the combination of the below code to transfer all of the images necessary. They will only be pictures and ALL of the pictures are found.
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; // only important class you need to know about.
private static void transferShape (XSSFSheet sheet, XSSFSheet newSheet) {
XSSFDrawing drawing = sheet.createDrawingPatriarch();
for(XSSFShape shape : drawing.getShapes()) {
if(shape instanceof XSSFPicture) {
XSSFPicture picture = (XSSFPicture) shape;
transferPicture(picture, newSheet);
}
}
}
private static void transferPicture(XSSFPicture picture, XSSFSheet newSheet) {
XSSFPictureData xssfPictureData = picture.getPictureData();
XSSFClientAnchor anchor = picture.getPreferredSize();
int col1 = anchor.getCol1();
int col2 = anchor.getCol2();
int row1 = anchor.getRow1();
int row2 = anchor.getRow2();
int x1 = anchor.getDx1();
int x2 = anchor.getDx2();
int y1 = anchor.getDy1();
int y2 = anchor.getDy2();
XSSFWorkbook newWb = newSheet.getWorkbook();
XSSFCreationHelper newHelper = newWb.getCreationHelper();
XSSFDrawing newDrawing = newSheet.createDrawingPatriarch();
XSSFClientAnchor newAnchor = newHelper.createClientAnchor();
newAnchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
// Row / Column placement.
newAnchor.setCol1(col1);
newAnchor.setCol2(col2);
newAnchor.setRow1(row1);
newAnchor.setRow2(row2);
// Fine touch adjustment along the XY coordinate.
newAnchor.setDx1(x1);
newAnchor.setDx2(x2);
newAnchor.setDy1(y1);
newAnchor.setDy2(y2);
double imageX = 0;
double imageY = 0;
if(anchor.getSize() != null) {
newAnchor.setSize(anchor.getSize());
} else {
int width = 0;
int height = 0;
for(int col = col1; col <= col2; col++) {
width += Math.round(Units.columnWidthToEMU(newSheet.getColumnWidth(col)));
}
width -= x1 - x2;
for(int row = row1; row <= row2; row++) {
height += Math.round(Units.TwipsToEMU(newSheet.getRow(row).getHeight()));
}
height -= y1 - y2;
CTPositiveSize2D ps2D = CTPositiveSize2D.Factory.newInstance();
ps2D.setCx((long) 0);
ps2D.setCy((long) 0);
newAnchor.setSize(ps2D);
}
int newPictureIndex = newWb.addPicture(xssfPictureData.getData(), xssfPictureData.getPictureType());
XSSFPicture newPicture = newDrawing.createPicture(newAnchor, newPictureIndex);
newPicture.resize();
}
However, the main issue is that the images are not sizing correctly any more. Something happened that broke that functionality. I had to add the following else to work on a new solution.
else {
int width = 0;
int height = 0;
for(int col = col1; col <= col2; col++) {
width += Math.round(Units.columnWidthToEMU(newSheet.getColumnWidth(col)));
}
width -= x1 - x2;
for(int row = row1; row <= row2; row++) {
height += Math.round(Units.TwipsToEMU(newSheet.getRow(row).getHeight()));
}
height -= y1 - y2;
CTPositiveSize2D ps2D = CTPositiveSize2D.Factory.newInstance();
ps2D.setCx((long) 0);
ps2D.setCy((long) 0);
newAnchor.setSize(ps2D);
}
Yet... even setting Cx and Cy to 0 nothing is being resized still. I am unsure what is going on.
newAnchor.setSize(anchor.getSize())
used to work all by itself. Not sure what changed for it to return null.
Upvotes: 1
Views: 1449
Reputation: 2338
This was a case of too much code from the API! Basically the size of the image is defined by its location and distance pushed by the dx
and dy
variables.
The below functions are the final product and works very well.
private static void transferShape (XSSFSheet sheet, XSSFSheet newSheet) {
XSSFDrawing drawing = sheet.createDrawingPatriarch();
for(XSSFShape shape : drawing.getShapes()) {
if(shape instanceof XSSFPicture) {
transferPicture(shape, newSheet);
}
}
}
private static void transferPicture(XSSFShape shape, XSSFSheet newSheet) {
XSSFPicture picture = (XSSFPicture) shape;
XSSFPictureData xssfPictureData = picture.getPictureData();
XSSFClientAnchor anchor = (XSSFClientAnchor) shape.getAnchor();
int col1 = anchor.getCol1();
int col2 = anchor.getCol2();
int row1 = anchor.getRow1();
int row2 = anchor.getRow2();
int x1 = anchor.getDx1();
int x2 = anchor.getDx2();
int y1 = anchor.getDy1();
int y2 = anchor.getDy2();
XSSFWorkbook newWb = newSheet.getWorkbook();
XSSFCreationHelper newHelper = newWb.getCreationHelper();
XSSFDrawing newDrawing = newSheet.createDrawingPatriarch();
XSSFClientAnchor newAnchor = newHelper.createClientAnchor();
// Row / Column placement.
newAnchor.setCol1(col1);
newAnchor.setCol2(col2);
newAnchor.setRow1(row1);
newAnchor.setRow2(row2);
// Fine touch adjustment along the XY coordinate.
newAnchor.setDx1(x1);
newAnchor.setDx2(x2);
newAnchor.setDy1(y1);
newAnchor.setDy2(y2);
int newPictureIndex = newWb.addPicture(xssfPictureData.getData(), xssfPictureData.getPictureType());
XSSFPicture newPicture = newDrawing.createPicture(newAnchor, newPictureIndex);
}
Hoping this helps someone. This was a really weird problem that I haven't yet found.
Upvotes: 3