POITwoCellAnchors
用于添加图片...因此,带有一些讨厌的反射,您可以添加带有OneCellAnchor
在示例中,drawing.createAnchor(10, 10, 110, 110, 2, 2, 0, 0)
用于将图像从单元格(2,2)的左上角定位为 10x10,并将图片缩放到 100x100 像素,即 110-10。
(使用 Libre Office 4.0、Excel Viewer 2010 测试)
import java.io.*;
import java.lang.reflect.*;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*;
public class Automation {
public static void main(String[] args) throws Exception {
XSSFWorkbook book = new XSSFWorkbook();
XSSFSheet sheet = book.createSheet("Test Sheet");
InputStream is = new FileInputStream("src/test/resources/smiley.jpg");
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = book.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(10, 10, 110, 110, 2, 2, 0, 0);
createPicture(anchor, pictureIdx, drawing);
XSSFRow row = sheet.createRow(12);
for (int i = 2; i < 11; i++) {
XSSFCell cell = row.createCell(i);
cell.setCellValue("oval (although anchor's type is set to MOVE_DONT_RESIZE ). ... But the one way to ");
}
sheet.autoSizeColumn(2);
book.write(new FileOutputStream(new File("auto.xlsx")));
}
public static XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex, XSSFDrawing drawing)
throws Exception
{
Method m = XSSFDrawing.class.getDeclaredMethod("addPictureReference", int.class);
m.setAccessible(true);
PackageRelationship rel = (PackageRelationship)m.invoke(drawing, (Integer)pictureIndex);
long shapeId = 1000+drawing.getCTDrawing().sizeOfOneCellAnchorArray();
CTOneCellAnchor ctAnchor = createOneCellAnchor(drawing, anchor);
CTPicture ctShape = ctAnchor.addNewPic();
m = XSSFPicture.class.getDeclaredMethod("prototype");
m.setAccessible(true);
CTPicture ctp = (CTPicture)m.invoke(null);
ctShape.set(ctp);
ctShape.getNvPicPr().getCNvPr().setId(shapeId);
Constructor<XSSFPicture> picCon = XSSFPicture.class
.getDeclaredConstructor(XSSFDrawing.class, CTPicture.class);
picCon.setAccessible(true);
XSSFPicture shape = picCon.newInstance(drawing, ctShape);
Field f = XSSFShape.class.getDeclaredField("anchor");
f.setAccessible(true);
f.set(shape, anchor);
m = XSSFPicture.class.getDeclaredMethod("setPictureReference", PackageRelationship.class);
m.setAccessible(true);
m.invoke(shape, rel);
return shape;
}
public static CTOneCellAnchor createOneCellAnchor(XSSFDrawing drawing, XSSFClientAnchor anchor) {
final int pixel2emu = 12700;
CTOneCellAnchor ctAnchor = drawing.getCTDrawing().addNewOneCellAnchor();
long cx = (anchor.getTo().getRowOff()-anchor.getFrom().getRowOff())*pixel2emu;
long cy = (anchor.getTo().getColOff()-anchor.getFrom().getColOff())*pixel2emu;
CTPositiveSize2D size = CTPositiveSize2D.Factory.newInstance();
size.setCx(cx);
size.setCy(cy);
ctAnchor.setExt(size);
ctAnchor.setFrom(anchor.getFrom());
CTMarker m = ctAnchor.getFrom();
m.setColOff(m.getColOff()*pixel2emu);
m.setRowOff(m.getRowOff()*pixel2emu);
ctAnchor.addNewClientData();
try {
Method mt = XSSFClientAnchor.class.getDeclaredMethod("setFrom", CTMarker.class);
mt.setAccessible(true);
mt.invoke(anchor, ctAnchor.getFrom());
} catch (Exception e) {
throw new RuntimeException("handle me", e);
}
return ctAnchor;
}
}