使用apache poi 3.7多次写入xlsx文档时出现异常

时间:2011-11-24 07:47:26

标签: java excel apache-poi

尝试使用Apache POI编写.xlsx文件时出现以下异常:org.apache.xmlbeans.impl.values.XmlValueDisconnectedException

似乎问题是第二次使用write()方法。 使用HSSFWorkbook时,不会出现此问题。

以下是代码:

public class SomeClass{

XSSFWorkbook workbook;

public SomeClass() throws IOException{
    File excelFile = new File("workbook.xlsx");

    InputStream inp = new FileInputStream(excelFile);
    workbook = new XSSFWorkbook(inp);
    inp.close();
}

void method(int i) throws InvalidFormatException, IOException {

    XSSFSheet sheet = workbook.getSheetAt(0);
    XSSFRow row = sheet.getRow(i);
    if (row == null) {
        row = sheet.createRow(i);
    }
    XSSFCell cell = row.getCell(i);
    if (cell == null)
        cell = row.createCell(i);
    cell.setCellType(Cell.CELL_TYPE_STRING);
    cell.setCellValue("a test");

    // Write the output to a file
    FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
    workbook.write(fileOut);
    fileOut.close();

}

public static void main(String[] args) throws Exception {
    SomeClass sc = new SomeClass();

    sc.method(1);
    sc.method(2);
}
}

7 个答案:

答案 0 :(得分:11)

我今天遇到了同样的问题。我注意到很多人在很多不同的论坛上都提出同样的问题,但我没有在任何地方看到答案。所以,这就是我想出的。它远非理想(我可以想到至少有两种情况可能是一个坏主意),并且可能无法满足所有需求,但它有效!

在工作簿对象所属的类中的每个保存操作之后,我从刚刚保存到的文件中重新加载工作簿。

使用上面的代码示例,我会像这样修改方法:

void method(int i) throws InvalidFormatException, IOException {
    ...

    // Write the output to a file
    FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
    workbook.write(fileOut);
    fileOut.close();

    // Reload the workbook, workaround for bug 49940
    // https://issues.apache.org/bugzilla/show_bug.cgi?id=49940
    workbook = new XSSFWorkbook(new FileInputStream("workbook.xlsx"));
}

我在我的代码中对此进行了测试,并且很好地解决了这个问题。只需确保您从保存它的同一文件中读回来,而不是早期版本或不同版本。

答案 1 :(得分:10)

这很可能是一个错误。

https://issues.apache.org/bugzilla/show_bug.cgi?id=49940

我建议您订阅该机票,以获得有关当前改进/替代方案的通知。

如果我找到解决方法,我会通知您。

答案 2 :(得分:3)

我为此找到的解决方案,我一直在寻找一段时间,是为了确保您没有使用Workbook打开您的File FileOutputStream保存Workbook。而是使用FileInputStream打开Workbook

像这样的东西可以完美地运作

        File inputFile = new File("Your-Path");
        this.inputStream = new FileInputStream(inputFile);
        this.opc = OPCPackage.open(this.inputStream);
        this.workbook = WorkbookFactory.create(opc);

...

        this.outputStream = new FileOutputStream(inputFile);
        this.workbook.write(this,outputStream);

不要忘记关闭每个打开的流和OPCPackage

答案 3 :(得分:0)

仅当我们尝试多次写入.xlsx文件的同一文件时才会发生这种情况。我遇到了同样的问题并通过......解决了。

  1. 以前我写过两次
  2. 现已删除第一次写入呼叫
  3. 将相同的工作簿实例传递给方法并将值设置为新单元格
  4. 最后通过编写更多列和单元格对工作簿进行了一些更改
  5. 然后使用文件输出流编写。
  6. 它正在运作

答案 4 :(得分:0)

使用apache poi 3.10时我也遇到了同样的问题。 但是在添加最新的apache poi jar文件后,它对我有用。 请将罐子更新到最新版本后尝试。

答案 5 :(得分:0)

我也有同样的问题。后来,我尝试了另一种方法,它解决了 在这种情况下,我们可以移动代码:

FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
workbook.write(fileOut);
fileOut.close();

出方法(int i),然后在main方法中,我们可以使用:

 sc.method(1); 
 sc.method(2); 
 FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
 workbook.write(fileOut);
 fileOut.close();

然后,workbook.write仅用于一次。此外,数据可以多次修改。

答案 6 :(得分:-1)

这似乎确实是XSSFSheet.createRow(int index)中的一个错误。只要错误没有得到修复,使用此类作为解决方法应该可以解决问题:

import java.util.Iterator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

public class PoiHacks
{
    // Fix of XSSFSheet.createRow(int index)
    public static Row createRow(Sheet sheet, int index) {
        Row row = sheet.getRow(index);
        if(row==null) return sheet.createRow(index);

        Iterator it = row.iterator();
        while(it.hasNext()) {
            it.next();
            it.remove();
        }
        return row;
    }
}

使用:

PoiHacks.createRow(sheet, 0);