2016-05-12 268 views
0

您好,我已經使用POI創建了Excel工作表。我在接下來的方式添加的圖片(JPG文件):Apache POI Excel工作表:在保持比例的同時調整圖片大小

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我無法獲得寬度和高度同樣的單位...任何建議?

回答

2

在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.Centimet ERS爲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()當設置列的寬度(字符寬度 )如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); 
... 
相關問題