为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

守候你守候我 2021-05-31 10:17:39
从这个关于使用 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用于嵌入对象时,如何将预览图像的大小调整为其原始大小?
查看完整描述

1 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

的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()应用于适用单元格的适用字体。


查看完整回答
反对 回复 2021-06-02
  • 1 回答
  • 0 关注
  • 865 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信