java - Apache POI 和自动行高以及合并单元格

标签 java excel 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);
}

此代码生成以下文档: enter image description here

但是,一旦我注释掉合并两个单元格的行,输出将如下所示: enter image description here

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

最佳答案

经过更多研究,发现这是 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/%[email protected]%3E

下面的

RowInfoNestedCellInfo 是我的自定义数据结构,用于跟踪工作表布局。您应该能够将它们替换为您的等效函数和辅助函数。

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));
            }
        }
    }
}

这个解决方案远非完美,但它让我能够继续前进。

关于java - Apache POI 和自动行高以及合并单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37744922/

相关文章:

java - 使用 JSch Java 库 SftpProgressMonitor 或任何其他类/方法,如何监控 SFTP 文件传输的传输速度?

java - 开关盒中的变量范围

excel - Excel散点图背景颜色可以根据数据值自定义吗?

java - 如何使用 apache poi 读取 xlsx 类型的 Excel 文件的单元格内容?

coldfusion - SpreadsheetFormatRows 格式颜色 ColdFusion

java - 在运行时和编译时计算字符串

java - 集成离线排行榜的最简单方法 [LibGDX]

php - 如何将此数据列表压缩到一个字段中?

excel - 如何清除内存以防止excel vba中的 "out of memory error"?

java - Apache POI 读取 xlsx 输入流问题