来自this answer的有关使用Apache POI将对象嵌入Excel电子表格的信息:
Workbook wb1 = new XSSFWorkbook();
Sheet sh = wb1.createSheet();
int picIdx = wb1.addPicture(getSamplePng(), Workbook.PICTURE_TYPE_PNG);
byte samplePPTX[] = getSamplePPT(true);
int oleIdx = wb1.addOlePackage(samplePPTX, "dummy.pptx", "dummy.pptx", "dummy.pptx");
Drawing<?> pat = sh.createDrawingPatriarch();
ClientAnchor anchor = pat.createAnchor(0, 0, 0, 0, 1, 1, 3, 6);
pat.createObjectData(anchor, oleIdx, picIdx);
这将使用getSamplePng()
中的图像作为预览图像创建嵌入的对象。该图像在行= 1,列= 1处锚定到单元格,并延伸到行= 6,列=3。除非图像宽高比完全匹配,否则会导致图像失真。
Picture
接口提供了resize
方法,但是似乎没有办法从Picture
获取ObjectData
实例。
如果图像尺寸在其锚定的单元格尺寸之内,则可以进行以下操作:
ClientAnchor anchor = drawing.createAnchor(0,
0,
imgDim.width * Units.EMU_PER_PIXEL,
imgDim.height * Units.EMU_PER_PIXEL,
columnIndex,
rowIndex,
columnIndex,
rowIndex);
如果图像大于单元格尺寸,则此方法不起作用;图像最终伸展到细胞的边界。
我也尝试过setAnchorType(AnchorType.MOVE_DONT_RESIZE)
,但似乎没有任何作用。
使用createObjectData
嵌入对象时如何将预览图像的大小调整为原始大小?
答案 0 :(得分:0)
XSSFClientAnchor
类提供了一个构造函数,该构造函数允许提供左上角的单元格(作为CTPoint2D
对象)和对象大小(以CTPositiveSize2D
的形式)。但是,此构造方法受保护。
解决方法是将该类扩展为一个接受左上角单元坐标以及宽度和高度(以EMU单位为单位)的类:
class SizedClientAnchor extends XSSFClientAnchor
{
private SizedClientAnchor(XSSFSheet sheet, int columnIndex, int rowIndex, int w, int h)
{
super((XSSFSheet) cell.getSheet(), createCTMarker(columnIndex, rowIndex), getSize2D(w, h));
}
private static CTMarker createCTMarker(int columnIndex, int rowIndex)
{
CTMarker ret = CTMarker.Factory.newInstance();
ret.setCol(columnIndex);
ret.setColOff(0);
ret.setRow(rowIndex);
ret.setRowOff(0);
return ret;
}
private static CTPositiveSize2D getSize2D(int w, int h)
{
CTPositiveSize2D ret = CTPositiveSize2D.Factory.newInstance();
ret.setCx(w);
ret.setCy(h);
return ret;
}
}
原始代码如下所示:
ClientAnchor anchor = new SizedClientAnchor(sh,
columnIndex,
rowIndex,
imgDim.width * Units.EMU_PER_PIXEL,
imgDim.height * Units.EMU_PER_PIXEL);
但是请注意,如果图像所经过的列的字体与“标准”字体(Calibri或Arial 11pt)不同,则结果图像的宽度将不正确。
上浆码位于calcCell()
中的XSSFClientAnchor
中。这使用了Units.columnWidthToEMU()
,而后者又使用了Units.charactersToEMU()
。它使用DEFAULT_CHARACTER_WIDTH
,据记录它仅适用于默认字体(Calibri或Arial)。
此问题的解决方法将涉及重新实现Units.charactersToEMU()
和XSSFClientAnchor.calcCell()
以应用于适用单元格的适用字体。