如何使用Java POI从工作簿中删除所有公式
几年前这里也提出了同样的问题: 然而,当时没有收到对我有效的答复。 我有一个工作簿,有几个大的工作表,我想循环所有单元格,用字符串替换单元格内容。问题是,许多单元格都包含公式,我必须先去掉这些公式。无论是如何使用Java POI从工作簿中删除所有公式,java,apache-poi,array-formulas,Java,Apache Poi,Array Formulas,几年前这里也提出了同样的问题: 然而,当时没有收到对我有效的答复。 我有一个工作簿,有几个大的工作表,我想循环所有单元格,用字符串替换单元格内容。问题是,许多单元格都包含公式,我必须先去掉这些公式。无论是cell.setCellFormula(null)还是cell.setCellType(CellType.STRING)(或BLANK)都不令人满意,因为删除数组公式的底层过程需要很长时间,并且使整个作业太慢 以下操作正常,但会留下一个损坏的excel工作簿,只能在第一次使用修复步骤打开该工作
cell.setCellFormula(null)
还是cell.setCellType(CellType.STRING)
(或BLANK
)都不令人满意,因为删除数组公式的底层过程需要很长时间,并且使整个作业太慢
以下操作正常,但会留下一个损坏的excel工作簿,只能在第一次使用修复步骤打开该工作簿:
方法m=XSSFCell.class.getDeclaredMethod(“setBlank”)代码>
m.setAccessible(true)代码>
m.invoke(单元)代码>
有没有其他更快捷、更干净的方法可以简单地将某些单元格设置为空白,而不考虑任何公式?发生损坏工作簿的原因是,/xl/calcChain.xml
中存储了一个计算链。删除公式的常规慢速方法将更新此计算链。但是,正如您已经发现的,它们还试图仅用于删除单个公式,而不是全部公式。因此,在删除部分数组公式时,它们必须小心,这会使它们变慢
但是如果真的所有的公式都应该被删除,那么这种谨慎是没有必要的,然后就可以删除整个/xl/calcChain.xml
例如:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xssf.model.CalculationChain;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.POIXMLDocumentPart;
import java.lang.reflect.Method;
class ExcelRemoveFormulasAndCalcChain {
private static void removeCalcChain(XSSFWorkbook workbook) throws Exception {
CalculationChain calcchain = workbook.getCalculationChain();
Method removeRelation = POIXMLDocumentPart.class.getDeclaredMethod("removeRelation", POIXMLDocumentPart.class);
removeRelation.setAccessible(true);
removeRelation.invoke(workbook, calcchain);
}
public static void main(String[] args) throws Exception {
XSSFWorkbook workbook = (XSSFWorkbook)WorkbookFactory.create(new FileInputStream("Test.xlsx"));
for (Sheet sheet : workbook) {
for (Row row : sheet) {
for (Cell cell : row) {
XSSFCell xssfcell = (XSSFCell)cell;
if (xssfcell.getCTCell().isSetF() && xssfcell.getCTCell().getF().getT() != STCellFormulaType.DATA_TABLE) {
xssfcell.getCTCell().unsetF();
}
}
}
}
removeCalcChain(workbook);
workbook.write(new FileOutputStream("Test_1.xlsx"));
workbook.close();
}
}
这将删除所有公式,并让所有单元格返回仅包含值和样式的单元格。我想我能够找到如何删除某些单元格范围内的公式。
我注意到,如果我删除工作表,第一个链接到它的公式会很快被删除。
如果我交换删除公式和删除工作表,这需要很多时间。
所以,如果我们创建一个工作表,使用“链接到它”重写所有公式,然后删除工作表,则公式将被快速删除(将带有“链接到不存在的工作表”的公式设置为无效)。
15k+行需要几秒钟的时间。以下是实验:
File fReport = new File(".xlsx");
XSSFWorkbook book = new XSSFWorkbook(new FileInputStream(fReport));
XSSFSheet sheet = book.getSheet("");
XSSFSheet dummy = book.createSheet("dummy");
int lastRow = sheet.getLastRowNum();
for (int i = 8; i <= lastRow; i++) {
XSSFRow rowToClean = sheet.getRow(i);
XSSFCell cell = rowToClean.getCell(2);
System.out.println(i);
if (cell != null) {
cell.setCellFormula("'dummy'!A1");
}
}
book.removeSheetAt(book.getSheetIndex(dummy));
for (int i = 8; i <= lastRow; i++) {
XSSFRow rowToClean = sheet.getRow(i);
XSSFCell cell = rowToClean.getCell(2);
System.out.println(i);
if (cell != null) {
cell.removeFormula();
}
}
book.write(new FileOutputStream(fReport));
book.close();
File fReport=新文件(“.xlsx”);
XSSFWorkbook book=新XSSFWorkbook(新文件输入流(fReport));
XSSFSheet sheet=book.getSheet(“”);
XSSFSheet dummy=book.createSheet(“dummy”);
int lastRow=sheet.getLastRowNum();
对于(int i=8;i)setCellForumla(null)
或setCellType(CellType.STRING)需要多长时间
?通过将非公式单元格复制到新工作表并删除旧工作表/工作簿,是否可以更快地创建另一个工作表/工作簿?谢谢,这是丢失的链接。您还可以通过继承XSSFWorkbook来避免反射:公共类NoFormulaWorkbook扩展XSSFWorkbook{public NoFormulaWorkbook(文件文件)抛出IOException,InvalidFormatException{super(文件);removeRelation(getCalculationChain();}}
user8656003-已经有一段时间了,但是你想把@Axel Richter的答案标记为正确吗?@gordon613用户已经多年没有这样做了。很多用户只问一个问题,永远不会回来。不要担心接受标记,它们是完全可选的。