Apache POI Excel - 如何配置列进行扩展?

138

我正在使用Apache POI API生成Excel电子表格来输出一些数据。

我面临的问题是,当电子表格创建并打开时,列没有展开,因此一些长文本(如日期格式的文本)不能在第一眼看到。

我可以在Excel中双击列边框以展开或拖动边框调整列宽,但可能有20多个列,我不想每次手动这样做 :(

我发现(尽管可能是错误的方法)groupRow()setColumnGroupCollapsed()可能能够完成这个技巧,但没有成功。可能我使用的方法不对。

代码示例片段:

        Workbook wb = new HSSFWorkbook();
        CreationHelper createHelper = wb.getCreationHelper();
        //create sheet
        Sheet sheet = wb.createSheet("masatoSheet");

        //not really working yet.... :(
        //set group for expand/collapse
        //sheet.groupRow(0, 10); //just random fromRow toRow argument values...
        //sheet.setColumnGroupCollapsed(0, true);

        //create row
        Row row = sheet.createRow((short)0);
        //put a cell in the row and store long text data
        row.createCell(0).setCellValue("Loooooooong text not to show up first");

在创建此电子表格时,“Looooooong text not to show up first”字符串位于单元格中,但由于列未展开,因此仅显示“Loooooooo”。

我该如何配置,以便在打开电子表格时,列已经展开了?


https://dev59.com/Z2Ij5IYBdhLWcg3wflQy - gavenkoa
你似乎正在寻找一种使用POI来完成这个任务的方法。但是在Excel中,要简单地完成此操作,请选择整个工作表,然后双击A-B列标题边界。如果您需要对多个工作表执行此操作,则编码解决方案可能更适合您。 - avg
请查看我在其他帖子中的回答:https://dev59.com/ymMk5IYBdhLWcg3wxAry#73571342 - Jakub Słowikowski
12个回答

217

14
我想指出autoSizeColumn不会很好地缩放,如果有很多行,它会非常慢。我不得不使用一些技巧,并执行类似于此问题中建议的操作。 - lbstr
14
关于autoSizeColumn的警告,它需要Java字体可用。 这不是服务器上使用的无头Java JRE的一部分,会抛出NullPointerException。 - Stephen Dillon
@StephenDillon 你有没有办法修复字体配置的空指针问题? - Vishal
我们发现最好的方法是在列中循环每一行,找到最长的字符长度,然后乘以x并添加缓冲区。 X使用试错法来看看适合什么,但它应该是一个字符的平均宽度。没有字体,我不认为你能真正做到完全正确,但我们非常接近。否则,您可以添加一个Excel宏,在用户首次打开时解决所有问题,这是最佳方法,但需要启用宏。 - Stephen Dillon
1
正如其他人在评论中指出的那样,autoSizeColumn确实可以工作,但它会使速度变得非常慢。我在我的项目中使用它时,10行数据的差异大约为3秒,想象一下如果有数百或数千行数据的情况。 - user9802118
它能运行,但速度太慢了。请查看我的答案:https://dev59.com/ymMk5IYBdhLWcg3wxAry#73571342 - Jakub Słowikowski

55

如果您想要自动调整工作簿中的所有列大小,这里有一个可能会有用的方法:

public void autoSizeColumns(Workbook workbook) {
    int numberOfSheets = workbook.getNumberOfSheets();
    for (int i = 0; i < numberOfSheets; i++) {
        Sheet sheet = workbook.getSheetAt(i);
        if (sheet.getPhysicalNumberOfRows() > 0) {
            Row row = sheet.getRow(sheet.getFirstRowNum());
            Iterator<Cell> cellIterator = row.cellIterator();
            while (cellIterator.hasNext()) {
                Cell cell = cellIterator.next();
                int columnIndex = cell.getColumnIndex();
                sheet.autoSizeColumn(columnIndex);
            }
        }
    }
}

我在 row.cellIterator() 处遇到了 NullPointerException。这是因为其中一个单元格没有值吗? - rakeeee
你尝试过创建一个更通用的解决方案吗?因为当前的解决方案似乎无法很好地处理合并区域。我的意思是,如果你在某个地方使用了sheet.addMergedRegion(new CellRangeAddress(...)),这种方法就不会很好地工作。 - ka3ak

55

提示:为使自动调整大小生效,应在将数据填充到Excel中之后调用sheet.autoSizeColumn(columnNumber)方法。

在填充数据之前调用此方法将不会产生任何效果。


1
有时候在使用autosizecolumn时,Android POI会崩溃。 - Roman Soviak
这里提供的答案与Java有关,而评论中提供的链接与Android有关。该答案在所有Java情况下仍然有效(除了没有java字体可用的无头Java JRE)。 - Unni Kris
谢谢,我计算了func,并以以下方式使用setColumnWidth:(5 until row.lastCellNum).forEach { colNum -> val columnWidth = (row.getCell(colNum).toString().length * 0.44 + 2.24) * 768 reportSheet.setColumnWidth(colNum, columnWidth.toInt()) } - Roman Soviak
@user7856586,你能否为我详细解释一下这个方法? - Mehroz Mustafa

11

你可以尝试像这样做:

HSSFSheet summarySheet = wb.createSheet();
summarySheet.setColumnWidth(short column, short width);

这里的参数是:表格中列号和其宽度。 但是,宽度的单位非常小,你可以尝试使用4000作为示例。


好的,谢谢!我认为对于我的目的,在列字符串可能动态生成的情况下,自适应大小的方法是适合的。 - Meow

9

如果您知道您的列数(例如,它等于一个集合列表),则可以使用此一行代码来调整一个工作表的所有列(如果您至少使用Java 8):

IntStream.range(0, columnCount).forEach(sheet::autoSizeColumn)

虽然这是几年前的语言,但当你在处理时,使用方法引用可以让代码更简短:IntStream.range(0, columnCount).forEach(sheet::autoSizeColumn) - BAERUS
@BAERUS 谢谢!我已经调整了它,使用了您建议的更短的变量。 - snap

8

关于Excel POI:

sheetName.autoSizeColumn(cellnum); 

它能工作,但速度非常慢。更好的方法是计算列宽并使用setColumnWidth()。 - Jakub Słowikowski

7
以下是示例代码。
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("your sheet name");
HSSFRow row = sheet.createRow(0);

cell = row.createCell(0);
cell.setCellValue("A BIG NAME WITH AUTO SIZE FEATURE ENABLED");

//这是至关重要的

sheet.autoSizeColumn(0);

//参数必须是单元格号码

cell = row.createCell(1);
cell.setCellValue("a big name without auto size feature enabled");

检查输出并开心地使用它 :)


2
sheet.setColumnWidth(columnIndex, width)是另一个你想要查看的方法。 - Mateen

4
你可以在循环之后添加这段代码。
for (int i = 0; i<53;i++) {
    sheet.autoSizeColumn(i);
}

3

我使用以下简单的解决方案:

这是您的工作簿和工作表:

XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("YOUR Workshhet");

然后添加带有列和行的数据到您的表格中。完成向表格添加数据后,请编写以下代码以自动调整列宽:autoSizeColumn

for (int columnIndex = 0; columnIndex < 15; columnIndex++) {
                    sheet.autoSizeColumn(columnIndex);
                }

在这里,您需要添加表格中列的数量,而不是15。

希望有人能帮助到您。


0

如果您想要扩展单元格的大小,可以使用setColumnWidth()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接