在使用autosizeColumn的Apache POI 3.9中,呈现在同一列上的图像越来越窄

我在excel表单中的图像下面有一个图像和一些文本。 当我将autoSizeColumn()应用到列的文本呈现图像也拉长。 我也将anchortype设置为2,但这不保护图像的大小。 我在这里发布一些示例代码。 任何帮助表示赞赏

public static void main(String[] args) { try{ XSSFWorkbook book = new XSSFWorkbook(); XSSFSheet sheet = book.createSheet("Test Sheet"); InputStream is = new FileInputStream("D:\\RPM_Eclipse_Workspaces\\B6.9\\00POI\\Chrysanthemum.jpg"); byte[] bytes = IOUtils.toByteArray(is); int pictureIdx = book.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); Drawing drawing = sheet.createDrawingPatriarch(); ClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, 2,2,10,10); //Image should not get Resized while doing Autosize anchor.setAnchorType(ClientAnchor.DONT_MOVE_AND_RESIZE); Picture pict = drawing.createPicture(anchor, pictureIdx); XSSFRow row = sheet.createRow(12); for(int i = 2 ; i < 11 ; i++){ XSSFCell cell = row.createCell(i); cell.setCellValue("oval (although anchor's type is set to MOVE_DONT_RESIZE ). ... But the one way to "); } sheet.autoSizeColumn(2); book.write(new FileOutputStream(new File("D:\\auto.xlsx"))); System.out.println("=== DONE ==="); }catch (Exception e){ } } 

POI使用TwoCellAnchors添加图片…所以有一些讨厌的reflection,你可以添加一个Picture OneCellAnchor

在这个例子中,使用drawing.createAnchor(10, 10, 110, 110, 2, 2, 0, 0)来定位单元格左上angular的图像10×10(2,2),并将图像缩放到100×100像素,即110-10。

(使用Libre Office 4.0,Excel Viewer 2010进行testing)

 import java.io.*; import java.lang.reflect.*; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.usermodel.*; import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.*; public class Automation { public static void main(String[] args) throws Exception { XSSFWorkbook book = new XSSFWorkbook(); XSSFSheet sheet = book.createSheet("Test Sheet"); InputStream is = new FileInputStream("src/test/resources/smiley.jpg"); byte[] bytes = IOUtils.toByteArray(is); int pictureIdx = book.addPicture(bytes, Workbook.PICTURE_TYPE_PNG); XSSFDrawing drawing = sheet.createDrawingPatriarch(); XSSFClientAnchor anchor = drawing.createAnchor(10, 10, 110, 110, 2, 2, 0, 0); createPicture(anchor, pictureIdx, drawing); XSSFRow row = sheet.createRow(12); for (int i = 2; i < 11; i++) { XSSFCell cell = row.createCell(i); cell.setCellValue("oval (although anchor's type is set to MOVE_DONT_RESIZE ). ... But the one way to "); } sheet.autoSizeColumn(2); book.write(new FileOutputStream(new File("auto.xlsx"))); } public static XSSFPicture createPicture(XSSFClientAnchor anchor, int pictureIndex, XSSFDrawing drawing) throws Exception { Method m = XSSFDrawing.class.getDeclaredMethod("addPictureReference", int.class); m.setAccessible(true); PackageRelationship rel = (PackageRelationship)m.invoke(drawing, (Integer)pictureIndex); long shapeId = 1000+drawing.getCTDrawing().sizeOfOneCellAnchorArray(); CTOneCellAnchor ctAnchor = createOneCellAnchor(drawing, anchor); CTPicture ctShape = ctAnchor.addNewPic(); m = XSSFPicture.class.getDeclaredMethod("prototype"); m.setAccessible(true); CTPicture ctp = (CTPicture)m.invoke(null); ctShape.set(ctp); ctShape.getNvPicPr().getCNvPr().setId(shapeId); Constructor<XSSFPicture> picCon = XSSFPicture.class .getDeclaredConstructor(XSSFDrawing.class, CTPicture.class); picCon.setAccessible(true); XSSFPicture shape = picCon.newInstance(drawing, ctShape); Field f = XSSFShape.class.getDeclaredField("anchor"); f.setAccessible(true); f.set(shape, anchor); m = XSSFPicture.class.getDeclaredMethod("setPictureReference", PackageRelationship.class); m.setAccessible(true); m.invoke(shape, rel); return shape; } public static CTOneCellAnchor createOneCellAnchor(XSSFDrawing drawing, XSSFClientAnchor anchor) { final int pixel2emu = 12700; CTOneCellAnchor ctAnchor = drawing.getCTDrawing().addNewOneCellAnchor(); long cx = (anchor.getTo().getRowOff()-anchor.getFrom().getRowOff())*pixel2emu; long cy = (anchor.getTo().getColOff()-anchor.getFrom().getColOff())*pixel2emu; CTPositiveSize2D size = CTPositiveSize2D.Factory.newInstance(); size.setCx(cx); size.setCy(cy); ctAnchor.setExt(size); ctAnchor.setFrom(anchor.getFrom()); CTMarker m = ctAnchor.getFrom(); m.setColOff(m.getColOff()*pixel2emu); m.setRowOff(m.getRowOff()*pixel2emu); ctAnchor.addNewClientData(); try { Method mt = XSSFClientAnchor.class.getDeclaredMethod("setFrom", CTMarker.class); mt.setAccessible(true); mt.invoke(anchor, ctAnchor.getFrom()); } catch (Exception e) { throw new RuntimeException("handle me", e); } return ctAnchor; } } 

在picture.resize()方法中,为了计算图像的原始高度,它使用row.getHeight值。 问题是,行高值! 根据单元格的内容,行高会自动增加,但是您无法通过row.getHeight()方法获取增加的高度值。 所以,你需要手动使用row.setHeigth(height)来设置行的高度。 那么你可以获得正常的图像大小和picture.resize()方法将正常工作。