java POI Excel工作表:在保持比例的同时重新绘制图片
你好,我创build一个使用POI的Excel shhet,并在一个点上添加一个JPG文件的图像:
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,我无法计算单元格比例或者BC我无法获得宽度和高度在同样的单位…任何build议?
POI中有一个Units类,提供像素和点之间的转换。
这里有一些其他的方法可能会有所帮助。
(使用下面的方法来设置单位的宽度和高度,如果你使用更多的像素,只需忽略cmToPx()
,而不是使用像素。
1.Centimeters像素
public static int cmToPx(double cm) { return (int) Math.round(cm * 96 / 2.54D); }
96
是我的显示器的DPI(从dpilove检查你的)
和1英寸= 2.54厘米
2.Centimers到RowHeight
public static int cmToH(double cm) { return (int) (Units.pixelToPoints(cmToPx(cm)) * 20); //POI's Units }
该公式来自HSSFRow#getHeightInPoints
将高度设置为“缇”或1/20的点。
设置行高时使用cmToH()
,如sheet.setDefaultRowHeight()
3.Centimeters到ColumnWidth
public static int cmToW(double cm) { return (int) Math.round(((cmToPx(cm) - 5.0D) / 8 * 7 + 5) / 7 * 256); }
使用(px - 5.0D) / 8
将像素转换为excel宽度的点(当在excel中拖动列的宽度时,像素和点将在光标周围显示)
该公式来自HSSFSheet#setColumnWidth
设置宽度( 以字符宽度的1/256为单位 )
Excel使用以下公式(OOXML规范的第3.3.1.12节):
// 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像素(96 dpi)。 如果将列宽设置为八个字符宽度,例如setColumnWidth(columnIndex,8 * 256),则可见字符的实际值(Excel中显示的值)从以下公式导出:
Truncate([numChars * 7 + 5] / 7 * 256) / 256 = 8;
设置列宽( 字符宽度 cmToW()
时使用cmToW()
,如sheet.setColumnWidth()
下面我设置XSSFClientAnchor来调整图片的大小,以保持它的比例。
// set padding between picture and gridlines so gridlines would not covered by the picture private static final double paddingSize = 10; private static final int padding = Units.toEMU(paddingSize); 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); } public static int[] calCoordinate(boolean fixTop, double cellX, double cellY, int imgX, int imgY) { int x = imgX; double ratio = ((double) imgX) / imgY; x = (int) Math.round(Units.toEMU(cellY - 2 * paddingSize) * ratio); x = (Units.toEMU(cellX) - x) / 2; if (x < padding) { return calCoordinate(false, cellY, cellX, imgY, imgX); } return calDirection(fixTop, x); } public static int[] calDirection(boolean fixTop, int x) { if (fixTop) { return new int[] { x, padding, -x, -padding }; } else { return new int[] { padding, x, -padding, -x }; } } ... // set XSSFClientAnchor here BufferedImage img = ImageIO.read(new File(path)); 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], col1, row1, col2, row2); ...