如何使用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用户已经多年没有这样做了。很多用户只问一个问题,永远不会回来。不要担心接受标记,它们是完全可选的。