猿问

在 Apache POI 中嵌入 Excel 中的对象时,如何保持预览图像的原始大小?

从这个关于使用 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用于嵌入对象时,如何将预览图像的大小调整为其原始大小?


守候你守候我
浏览 866回答 1
1回答

PIPIONE

的XSSFClientAnchor类提供一个构造,允许以供应左上角单元(作为一个CTPoint2D对象)和对象的大小(以的形式CTPositiveSize2D)。但是,此构造函数是受保护的。解决方法是将此类扩展为接受左上角单元格坐标以及宽度和高度(以 EMU 为单位)的类:class SizedClientAnchor extends XSSFClientAnchor{&nbsp; &nbsp; private SizedClientAnchor(XSSFSheet sheet, int columnIndex, int rowIndex, int w, int h)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; super((XSSFSheet) cell.getSheet(), createCTMarker(columnIndex, rowIndex), getSize2D(w, h));&nbsp; &nbsp; }&nbsp; &nbsp; private static CTMarker createCTMarker(int columnIndex, int rowIndex)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; CTMarker ret = CTMarker.Factory.newInstance();&nbsp; &nbsp; &nbsp; &nbsp; ret.setCol(columnIndex);&nbsp; &nbsp; &nbsp; &nbsp; ret.setColOff(0);&nbsp; &nbsp; &nbsp; &nbsp; ret.setRow(rowIndex);&nbsp; &nbsp; &nbsp; &nbsp; ret.setRowOff(0);&nbsp; &nbsp; &nbsp; &nbsp; return ret;&nbsp; &nbsp; }&nbsp; &nbsp; private static CTPositiveSize2D getSize2D(int w, int h)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; CTPositiveSize2D ret = CTPositiveSize2D.Factory.newInstance();&nbsp; &nbsp; &nbsp; &nbsp; ret.setCx(w);&nbsp; &nbsp; &nbsp; &nbsp; ret.setCy(h);&nbsp; &nbsp; &nbsp; &nbsp; return ret;&nbsp; &nbsp; }}原始代码变成如下所示:ClientAnchor anchor = new SizedClientAnchor(sh,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; columnIndex,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rowIndex,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgDim.width * Units.EMU_PER_PIXEL,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgDim.height * Units.EMU_PER_PIXEL);但是请注意,如果图像经过的列的字体与“标准”字体(Calibri 或 Arial 11pt)不同,则生成的图像的宽度将不正确。尺寸代码calcCell()在XSSFClientAnchor. 这使用Units.columnWidthToEMU(),而后者又使用Units.charactersToEMU(). 这使用DEFAULT_CHARACTER_WIDTH,记录为仅适用于默认字体(Calibri 或 Arial)。解决此问题的方法将涉及重新实现Units.charactersToEMU()和XSSFClientAnchor.calcCell()应用于适用单元格的适用字体。
随时随地看视频慕课网APP

相关分类

Java
我要回答