首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Apache POI Excel工作表:调整图片大小,同时保持其比例不变

Apache POI Excel工作表:调整图片大小,同时保持其比例不变
EN

Stack Overflow用户
提问于 2016-05-12 17:25:51
回答 2查看 7.6K关注 0票数 1

您好,我使用POI创建了excel工作表。我用下面的方法添加了图片(jpg-file):

代码语言:javascript
复制
Workbook wb = new HSSFWorkbook();
CreationHelper helper = wb.getCreationHelper();
//...
InputStream is = new FileInputStream("img.jpg");
byte[] bytes = IOUtils.toByteArray(is);
int picIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
anchor.setCol1(5);
anchor.setRow1(5);
Picture pict = drawing.createPicture(anchor, picIdx);
pict.resize();

现在,我希望图片适合该单元格,但我不想更改它的纵横比。我可以调整大小的比例是相对于单元格的,显然可以有不同的比例。我试着计算比例,但问题是,我不能得到或设置像素的行高,只能以pt为单位,我也不能计算单元比率,我不能得到相同单位的宽度和高度。有什么建议吗?

EN

回答 2

Stack Overflow用户

发布于 2016-10-19 16:49:31

POI中有一个Units类,它提供像素和点之间的转换。

这里有一些方法可能有助于设置单元格的宽度和高度。

1.到像素的厘米

代码语言:javascript
复制
public static int cmToPx(double cm) {
    return (int) Math.round(cm * 96 / 2.54D);
}

96是我的显示器的DPI值(从dpilove查看您的)

1英寸= 2.54厘米

2.到RowHeight的厘米距离

代码语言:javascript
复制
public static int cmToH(double cm) {
    return (int) (Units.pixelToPoints(cmToPx(cm)) * 20); //POI's Units
}

用法:sheet.setDefaultRowHeight(cmToH(1.0))

参考:HSSFRow#getHeightInPoints

将高度设置为"twips“或1/20的点。

3.到ColumnWidth的距离

代码语言:javascript
复制
public static int cmToW(double cm) {
    return (int) Math.round(((cmToPx(cm) - 5.0D) / 8 * 7 + 5) / 7 * 256);
}

用法:sheet.setColumnWidth(cmToW(1.0))

使用(px - 5.0D) / 8将像素转换为excel宽度中的点。(在excel中拖动列宽时,光标周围将显示像素和点)

参考:HSSFSheet#setColumnWidth

设置宽度(以字符宽度的1/256为单位的)

Excel使用以下公式( OOXML规范的第3.3.1.12节):

代码语言:javascript
复制
// Excel width, not character width
width = Truncate([{Number of Visible Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width} * 256) / 256

以Calibri字体为例,11磅字体大小的最大数字宽度为7像素(96dpi)。如果将列宽设置为8个字符宽度,例如setColumnWidth(columnIndex,8*256),则可见字符的实际值(在Excel中显示的值)将从以下公式中导出:

代码语言:javascript
复制
Truncate([numChars * 7 + 5] / 7 * 256) / 256 = 8;

使用XSSFClientAnchor调整图片大小以填充单元格并保持其比例:

代码语言:javascript
复制
// set padding between picture and gridlines so gridlines would not covered by the picture
private static final double PADDING_SIZE = 10;
private static final int PADDING = Units.toEMU(PADDING_SIZE);

/**
 * Draw Image inside specific cell
 *
 * @param wb workbook
 * @param sheet sheet
 * @param cellW cell width in pixels
 * @param cellH cell height in pixels
 * @param imgPath image path
 * @param col the column (0 based) of the first cell.
 * @param row the row (0 based) of the first cell.
 * @param colSize the column size of cell
 * @param rowSize the row size of cell
 */
public static void drawImageInCell(SXSSFWorkbook wb, SXSSFSheet sheet, int cellW, int cellH,
      String imgPath, int col, int row, int colSize, int rowSize) throws IOException {
    Path path = Paths.get(imgPath);
    BufferedImage img = ImageIO.read(path.toFile());
    int[] anchorArray = calCellAnchor(Units.pixelToPoints(cellW), Units.pixelToPoints(cellH),
       img.getWidth(), img.getHeight());
    XSSFClientAnchor anchor = new XSSFClientAnchor(anchorArray[0], anchorArray[1], anchorArray[2],
        anchorArray[3], (short) col, row, (short) (col + colSize), row + rowSize);
    int index = wb.addPicture(Files.readAllBytes(path), XSSFWorkbook.PICTURE_TYPE_JPEG);
    sheet.createDrawingPatriarch().createPicture(anchor, index);
}

/**
 * calculate POI cell anchor
 *
 * @param cellX cell width in excel points
 * @param cellY cell height in excel points
 * @param imgX image width
 * @param imgY image height
 */
public static int[] calCellAnchor(double cellX, double cellY, int imgX, int imgY) {
    // assume Y has fixed padding first
    return calCoordinate(true, cellX, cellY, imgX, imgY);
}

/**
 * calculate cell coordinate
 *
 * @param fixTop is Y has fixed padding
 */
private static int[] calCoordinate(boolean fixTop, double cellX, double cellY, int imgX, int imgY) {
    double ratio = ((double) imgX) / imgY;
    int x = (int) Math.round(Units.toEMU(cellY - 2 * PADDING_SIZE) * ratio);
    x = (Units.toEMU(cellX) - x) / 2;
    if (x < PADDING) {
        return calCoordinate(false, cellY, cellX, imgY, imgX);
    }
    return calDirection(fixTop, x);
}

/**
 * calculate X's direction
 *
 * @param fixTop is Y has fixed padding
 * @param x X's padding
 */
private static int[] calDirection(boolean fixTop, int x) {
    if (fixTop) {
        return new int[] { x, PADDING, -x, -PADDING };
    } else {
        return new int[] { PADDING, x, -PADDING, -x };
    }
}
票数 5
EN

Stack Overflow用户

发布于 2018-06-21 20:01:51

我使用Base64图像数据,我这样做,对我来说,它在给定的列/行添加,并适当地调整它的大小,我也不想适应它可以轴向和底部的任何单元格:

代码语言:javascript
复制
    byte[] imageBase64Data = base64DataString.getBytes();
    byte[] imageRawData = Base64.getDecoder().decode(imageBase64Data);

    int imgWidth = 1920; // only initial if not known
    int imgHeight = 1080; // only initial if not known

    try {
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imageRawData));
        imgWidth = img.getWidth();
        imgHeight = img.getHeight();
    } catch (IOException e) {
        e.printStackTrace();
    }

    int pictureIdx = workbook.addPicture(imageRawData, Workbook.PICTURE_TYPE_PNG);

    CreationHelper helper = workbook.getCreationHelper();
    Drawing drawing = sheet.createDrawingPatriarch();
    ClientAnchor anchor = helper.createClientAnchor();

    anchor.setCol1(desiredCol);
    anchor.setRow1(desiredRow);
    Picture picture = drawing.createPicture(anchor, pictureIdx);
    picture.resize(0.7 * imgWidth / XSSFShape.PIXEL_DPI, 5 * imgHeight / XSSFShape.PIXEL_DPI);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37182688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档