具有合并单元格的Apache POI和自动行高度

我正在使用Apache POI,我遇到了一个奇怪的问题。 我可以自动调整行的大小,但只有当行中没有合并的单元格时才可以。 这是一个例子:

new FileOutputStream('test.xlsx').withStream { OutputStream os -> Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet(); CellStyle wrapStyle = workbook.createCellStyle(); wrapStyle.setWrapText(true); Row row = sheet.createRow(0); row.setRowStyle(wrapStyle); Cell cell = row.createCell(0); cell.setCellStyle(wrapStyle); cell.setCellValue("Very long text that needs to be wrapped") cell = row.createCell(1); cell.setCellStyle(wrapStyle); cell.setCellValue("Short text"); cell = row.createCell(2); cell.setCellStyle(wrapStyle); cell.setCellValue(""); // These two lines break row auto-height! // CellRangeAddress cellRangeAddress = new CellRangeAddress(0, 0, 1, 2); sheet.addMergedRegion(cellRangeAddress); workbook.write(os); } 

此代码生成以下文档: 在这里输入图像说明

但是,只要我注释掉合并两个单元格的行,输出如下所示: 在这里输入图像说明

这是一个错误? 有谁知道一个解决方法?

经过更多的研究,事实certificate,这是Excel本身的问题,而不是POI。 对于所有合并了单元格的行,Excel确实失去了自动将行适合内容的能力。 更多信息请参阅:

http://excel.tips.net/T003207_Automatic_Row_Height_For_Merged_Cells_with_Text_Wrap.html http://blog.contextures.com/archives/2012/06/07/autofit-merged-cell-row-height/

解决方法是基于预测行的最大单元格中的行数,然后手动调整行高度。 代码基于这个讨论:

http://mail-archives.apache.org/mod_mbox/poi-user/200906.mbox/%3C24216153.post@talk.nabble.com%3E

RowInfoNestedCellInfo是我的自定义数据结构,跟踪表单布局。 你应该能够用你的等价物和辅助函数replace它们。

 private void adjustRowHeights(Sheet sheet, List<RowInfo> rows, SortedSet<Integer> createdColumnNumbers) { SortedMap<Integer, Float> columnWidthsInPx = [] as TreeMap; createdColumnNumbers.each { columnWidthsInPx.put(it, sheet.getColumnWidthInPixels(it)); } rows.each { RowInfo rowInfo -> if ( rowInfo.hasMergedCells ) { Row excelRow = sheet.getRow(rowInfo.rowIndex); // Find the column with the longest text - that's the one that will determine // the row height // NestedCellInfo longestCell = rowInfo.getCellWithLongestContent(); String cellText = longestCell.getText(); if ( cellText != null && cellText.size() > 5 ) { int colIdx = rowInfo.cells.indexOf(longestCell); // Figure out available width in pixels, taking colspans into account // float columnWidthInPx = columnWidthsInPx[colIdx]; int numberOfMergedColumns = longestCell.colSpan; (numberOfMergedColumns - 1).times { columnWidthInPx += columnWidthsInPx[colIdx + it]; } // Setup the font we'll use for figuring out where the text will be wrapped // XSSFFont cellFont = longestCell.getCellFont(); int fontStyle = Font.PLAIN; if ( cellFont.getBold() ) fontStyle = Font.BOLD; if ( cellFont.getItalic() ) fontStyle = Font.ITALIC; java.awt.Font currFont = new java.awt.Font( cellFont.getFontName(), fontStyle, cellFont.getFontHeightInPoints()); AttributedString attrStr = new AttributedString(cellText); attrStr.addAttribute(TextAttribute.FONT, currFont); // Use LineBreakMeasurer to count number of lines needed for the text // FontRenderContext frc = new FontRenderContext(null, true, true); LineBreakMeasurer measurer = new LineBreakMeasurer(attrStr.getIterator(), frc); int nextPos = 0; int lineCnt = 0; while (measurer.getPosition() < cellText.length()) { nextPos = measurer.nextOffset( columnWidthInPx ); lineCnt++; measurer.setPosition(nextPos); } if ( lineCnt > 1 ) { excelRow.setHeight((short)(excelRow.getHeight() * lineCnt * /* fudge factor */ 0.7)); } } } } 

这个解决scheme远非完美,但它使我前进。