您好我使用POI创建了Excel工作表。我已经在下一个方面添加了图片(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 i can can&t获取相同单位的宽度和高度......有什么建议吗?
答案 0 :(得分:4)
POI中有一个Units类,它提供像素和点之间的转换 这里有一些方法可能有助于设置单元格的宽度和高度。
1.Centimeters to Pixels
public static int cmToPx(double cm) {
return (int) Math.round(cm * 96 / 2.54D);
}
96
是我的显示器的DPI(请从dpilove查看)
和1英寸= 2.54厘米
2.Centimeters to RowHeight
public static int cmToH(double cm) {
return (int) (Units.pixelToPoints(cmToPx(cm)) * 20); //POI's Units
}
用法:sheet.setDefaultRowHeight(cmToH(1.0))
参考:HSSFRow#getHeightInPoints
将高度设置为“缇”或1点20分。
3.Centimeters to ColumnWidth
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节):
// 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;
使用XSSFClientAnchor调整图片大小以填充单元格并保持其比例:
// 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 };
}
}
答案 1 :(得分:0)
我正在使用Base64图像数据,并且这样做是这样的,对我来说,它会在给定的col / row处添加并正确调整其大小,而且我也不想容纳它可以左右固定的单元格:< / p>
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);