为什么在 XSSFRow 中使用 copyRowFrom(...) 时会出现 IllegalArgumentException?
Why am I getting IllegalArgumentException while using copyRowFrom(...) in XSSFRow?
我正在尝试使用 copyRowFrom(...);
将电子表格的第一行复制到新 XSSFSheet 的第一行,但有些地方不正常。
您可以在此处找到 XSSFRow class 和方法:
https://github.com/apache/poi/blob/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java#L581
我从 FormulaShifter.java 得到 IllegalArgumentException("amountToMove must not be zero")
:
https://github.com/apache/poi/blob/trunk/src/java/org/apache/poi/ss/formula/FormulaShifter.java#L80
问题似乎出在 XSSFRow 的第 623 行,其中使用参数 rowDifference = 0
调用了 FormulaShifter.createForRowCopy(...)
,因为源行为 0,目标行为 0:
https://github.com/apache/poi/blob/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java#L623
我不知道,也许这是一个错误,但是当到达 FormulaShifter.java 中的第 80 行时,参数 rowDifference 对应的 amountToMove 为 0,因此它抛出 IllegalArgumentException。
我是不是遗漏了什么或者这是 XSSFRow 中 copyRowFrom(...);
方法的错误?
你是对的。这是 XSSFRow
中的 a bug,因为它会调用 FormulaShifter.createForRowCopy
,即使因为目标行号与源行号相同而没有要移动的内容也是如此。您可以将此作为错误提交给 apache poi
.
但是需要创建一个可以在那里提供的测试用例。我已经为你做到了。该代码还提供了一种解决方法。这是首先复制到行号与源行号不同的错误目标行。然后它将错误的第一个目标行复制到真正需要的目标行。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelCopyRowFrom {
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
XSSFSheet srcSheet = workbook.getSheetAt(0);
XSSFRow srcRow = srcSheet.getRow(0);
XSSFSheet destSheet = workbook.createSheet();
//XSSFRow destRow = destSheet.createRow(0); //this fails because destination row number is the same as source row number
XSSFRow destRow = destSheet.createRow(1); //this works
destRow.copyRowFrom(srcRow, new CellCopyPolicy());
//workaround copy wrong first destination row to really needed destination row
XSSFRow destRowNeeded = destSheet.createRow(0);
destRowNeeded.copyRowFrom(destRow, new CellCopyPolicy());
//the remove wrong first destination row
destSheet.removeRow(destRow);
FileOutputStream outputStream = new FileOutputStream("SAMPLENEW.xlsx");
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
}
//fix amountToMove must not be zero:srcRows index base destStartRow+1,avoid the same
int indexAdd1 = 1;
for (Row row : failRowList) {
row.setRowNum(indexAdd1);
indexAdd1++;
}
failSheet.copyRows(failRowList,0, CellCopyPolicyFactory.newOnlyValue());
我正在尝试使用 copyRowFrom(...);
将电子表格的第一行复制到新 XSSFSheet 的第一行,但有些地方不正常。
您可以在此处找到 XSSFRow class 和方法:
https://github.com/apache/poi/blob/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java#L581
我从 FormulaShifter.java 得到 IllegalArgumentException("amountToMove must not be zero")
:
https://github.com/apache/poi/blob/trunk/src/java/org/apache/poi/ss/formula/FormulaShifter.java#L80
问题似乎出在 XSSFRow 的第 623 行,其中使用参数 rowDifference = 0
调用了 FormulaShifter.createForRowCopy(...)
,因为源行为 0,目标行为 0:
https://github.com/apache/poi/blob/trunk/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java#L623
我不知道,也许这是一个错误,但是当到达 FormulaShifter.java 中的第 80 行时,参数 rowDifference 对应的 amountToMove 为 0,因此它抛出 IllegalArgumentException。
我是不是遗漏了什么或者这是 XSSFRow 中 copyRowFrom(...);
方法的错误?
你是对的。这是 XSSFRow
中的 a bug,因为它会调用 FormulaShifter.createForRowCopy
,即使因为目标行号与源行号相同而没有要移动的内容也是如此。您可以将此作为错误提交给 apache poi
.
但是需要创建一个可以在那里提供的测试用例。我已经为你做到了。该代码还提供了一种解决方法。这是首先复制到行号与源行号不同的错误目标行。然后它将错误的第一个目标行复制到真正需要的目标行。
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class ExcelCopyRowFrom {
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("SAMPLE.xlsx"));
XSSFSheet srcSheet = workbook.getSheetAt(0);
XSSFRow srcRow = srcSheet.getRow(0);
XSSFSheet destSheet = workbook.createSheet();
//XSSFRow destRow = destSheet.createRow(0); //this fails because destination row number is the same as source row number
XSSFRow destRow = destSheet.createRow(1); //this works
destRow.copyRowFrom(srcRow, new CellCopyPolicy());
//workaround copy wrong first destination row to really needed destination row
XSSFRow destRowNeeded = destSheet.createRow(0);
destRowNeeded.copyRowFrom(destRow, new CellCopyPolicy());
//the remove wrong first destination row
destSheet.removeRow(destRow);
FileOutputStream outputStream = new FileOutputStream("SAMPLENEW.xlsx");
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
}
//fix amountToMove must not be zero:srcRows index base destStartRow+1,avoid the same
int indexAdd1 = 1;
for (Row row : failRowList) {
row.setRowNum(indexAdd1);
indexAdd1++;
}
failSheet.copyRows(failRowList,0, CellCopyPolicyFactory.newOnlyValue());