介绍
大家都知道POI! 它是可用Java创建Excel文档的最佳库。 它真的很好,可以轻松地完成很多事情。 但是最近我想做些不那么简单的事情。 我想将现有的xlsx文件用作模板,并在某些位置将一些数据插入其中。 在这篇文章中,我将说明为什么版本4.0.0并不那么容易。
可用工具
为了在现有Excel文档的中间插入一些内容,必须将从插入点到最后一行的所有行向下移动n行,其中n是要插入的行数。 还最好保持要移动的行的格式。
实际上,POI具有一些API可以帮助解决这些问题。 的
工作表界面有方法
Sheet.shiftRows(int,int,int)可以这样使用:
sheet.shiftRows(insertPosition,sheet.getLastRowNum(),n);
有更高级的方法
Sheet.shiftRows(int,int,int,boolean,boolean),但是对于XSSF,布尔参数没有什么区别,正如我在代码中可以找到的那样。 对于HSSF,这些参数可能很重要。
因此,该方法应该可以解决问题! 有什么问题?
问题
当我尝试使用这种方法时,遇到了一个可怕的问题:“我们发现了一些内容问题……”
实际上,这非常令人沮丧。 我很快发现行以某种方式被错误地移动了。 LibreOffice至少能够打开文件,但是格式和插入的内容均错误。
解
这需要2-3个小时的勤奋挖掘:-)。 事实证明,即使在最新的4.0.0版本(甚至很可能是4.0.1版本)中,POI也存在错误,无法正确移动行。 这是该错误的链接:
https://bz.apache.org/bugzilla/show_bug.cgi?id=57423
例如,该方法更新工作表xml中的行引用
<row r =” 139 “
但不会更新单元格引用
<cr =” A138 ” s =“ 1” /> –错误
在这种情况下,单元必须指向上一级行,如下所示:
<cr =” A139 ” s =“ 1” /> –对
(如果您解压缩xlsx文件,则可以查看工作表xml)
该错误显示了一种解决方法。 我创建了一个方法,该方法在一个方法中实现了移位和变通方法:
public static void xssfShiftRows(Sheet sh, int firstRow, int last Row, int shiftN) {int firstShiftedRow = firstRow + shiftN;int lastShiftedRow = lastRow + shiftN;sh.shiftRows(firstRow, lastRow, shiftN, true, true);/** This code is a workaround for the bug* https://bz.apache.org/bugzilla/show_bug.cgi?id=57423* In the sheet xml the row references are updated like this:* <row r="139"* but the cell references are incorrect* <c r="A138" s="1"/>** The number in the row 139 must match the number in the cell A139.* This code manually updates these links.*/for (int nRow = firstShiftedRow; nRow <= lastShiftedRow; nRow++) {final Row row = sh.getRow(nRow);if (row != null) {String msg = "Row[rownum=" + row.getRowNum()+ "] contains cell(s) included in a multi-cell array formula. "+ "You cannot change part of an array.";for (Cell c : row) {((XSSFCell) c).updateCellReferencesForShifting(msg);}}
}
}
翻译自: https://www.javacodegeeks.com/2019/03/insert-content-apache-poi.html