Java 无法使用Apache POI写入和保存XLSM文件

Java 无法使用Apache POI写入和保存XLSM文件,java,apache-poi,xssf,eofexception,xlsm,Java,Apache Poi,Xssf,Eofexception,Xlsm,我有一个现有的XLSM文件,我试图在其中使用apachepoi编写数据 String File = GlobalVariables.XLSM; try { Workbook workbook; workbook = new XSSFWorkbook(OPCPackage.open(GlobalVariables.XLSM)); Sheet sheet = workbook.getSheetAt(0); Row row = sheet.createRow(reco

我有一个现有的
XLSM
文件,我试图在其中使用
apachepoi
编写数据

String File = GlobalVariables.XLSM;

try {
    Workbook workbook;
    workbook = new XSSFWorkbook(OPCPackage.open(GlobalVariables.XLSM));
    Sheet sheet = workbook.getSheetAt(0);
    Row row = sheet.createRow(recordcount+5);
    Cell cell;

    cell = row.createCell(GlobalVariables.testID);
    cell.setCellValue(recordcount);

    FileOutputStream out = new FileOutputStream(new File(File));
    workbook.write(out);
    out.close();
    System.out.println("Data was written in XLSM");

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (InvalidFormatException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
我收到错误消息:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>error066080_01.xml</logFileName>
    <summary>Error in file (C:\_privat\completeReport.xlsm)</summary>
    <removedRecords>
        <removedRecord>/xl/worksheets/sheet1.xml</removedRecord>
        <removedRecord>/xl/calcChain.xml</removedRecord>
    </removedRecords>
</recoveryLog>
org.apache.poi.ooxml.POIXMLException:java.io.eofeException:意外 ZLIB输入流结束

该问题与
gzip流
gzip输出流
无关

更新2019.06.04。

我修改了代码,但仍然出现错误:

try {
    FileInputStream file = new FileInputStream(GlobalVariables.XLSM);
    XSSFWorkbook workbook = new XSSFWorkbook(file);
    XSSFSheet sheet = workbook.getSheetAt(0);
    XSSFRow row = sheet.createRow(recordcount+4);
    Cell cell;

    cell = row.createCell(GlobalVariables.testID);
    cell.setCellValue(recordcount+1);

    file.close();

    FileOutputStream out = new FileOutputStream(new File(GlobalVariables.XLSM));
    workbook.write(out);
    out.flush();
    out.close();
    workbook.close();
    System.out.println("Data was written");

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}
错误消息:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
    <logFileName>error066080_01.xml</logFileName>
    <summary>Error in file (C:\_privat\completeReport.xlsm)</summary>
    <removedRecords>
        <removedRecord>/xl/worksheets/sheet1.xml</removedRecord>
        <removedRecord>/xl/calcChain.xml</removedRecord>
    </removedRecords>
</recoveryLog>

error066080_01.xml
文件(C:\\u privat\completeReport.xlsm)中出错
/xl/worksheets/sheet1.xml
/xl/calcChain.xml

几乎每次打开由代码创建的工作簿时,都会遇到错误,原因是某些资源未正确关闭。不幸的是,我经历过很多次;-)

在我的情况下,我可以通过以下行动顺序(订单事项)解决问题:

  • 编写工作簿:
    工作簿。写出
  • 强制
    FileOutputStream
    清空所有使用的缓冲区:
    out.flush()
  • 关闭
    FileOutputStream
    out.close()
  • 关闭工作簿:
    workbook.close()
  • 以下是我如何将缺少的操作添加到您的代码中:

    试试看{
    工作手册;
    工作簿=新XSSF工作簿(OPCPackage.open(GlobalVariables.XLSM));
    工作表=工作簿。getSheetAt(0);
    Row Row=sheet.createRow(记录计数+5);
    细胞;
    cell=row.createCell(GlobalVariables.testID);
    cell.setCellValue(记录计数);
    FileOutputStream out=新FileOutputStream(新文件(文件));
    //1.编写工作簿
    练习册。写(出);
    //2.强制FileOutputStream在关闭之前写出所有内容
    out.flush();
    //3.然后关闭FileOutputStream
    out.close();
    //4.最后关闭工作簿
    workbook.close();
    System.out.println(“数据是用XLSM编写的”);
    }catch(filenotfounde异常){
    e、 printStackTrace();
    }捕获(无效格式){
    e、 printStackTrace();
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    
    请注意,刷新
    FileOutputStream
    可能并不总是必要的,但是在一些关于apachepoi的最佳实践教程中提到了它,所以我决定在我的代码中使用它

    这对我有用,我希望它也能对你有用

    编辑(OP在下面的评论中询问了我的示例代码)
    这是一个独立的示例,用于读取和扩展
    XSSFWorkbook
    。这一切都只是在
    main
    方法中,但至少有注释;-)
    您必须更改工作簿的路径,在本例中,它基本上是一个
    字符串
    ,然后变成
    java.nio.path

    public class PoiMain {
    
        public static void main(String[] args) {
            /*
             * Setup:
             * An existing xlsx file with a first sheet containing 6 columns and 1 row.
             * The row has 6 filled cells with the values
             * cell 1 (index 0): There
             * cell 2 (index 1): is
             * cell 3 (index 2): a
             * cell 4 (index 3): house
             * cell 5 (index 4): in
             * cell 6 (index 5): New Orleans
             * 
             * Task:
             * Write the words "they", "call", "it", "the", "rising", "sun"
             * in the cells below.
             */
    
            // define the (correct) path to the workbook
            String pathToFile = "Y:\\our\\path\\to\\the\\Test-Workbook.xlsx"; // you can use an xlsm here, too
            // create a Path object
            Path filePath = Paths.get(pathToFile);
            // declare a workbook
            XSSFWorkbook workbook;
    
            try {
                /*
                 * READING from the .xlsx file:
                 */
    
                FileInputStream in = new FileInputStream(filePath.toFile());
                workbook = XSSFWorkbookFactory.createWorkbook(in);
                XSSFSheet sheet = workbook.getSheetAt(0);
    
                // read all the cells of the first row and print their content
                for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
                    XSSFRow row = sheet.getRow(i);
                    for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
                        XSSFCell cell = row.getCell(j);
                        System.out.println(cell.getStringCellValue());
                    }
                }
    
                /*
                 * WRITING to the .xlsx file already read
                 */
    
                // create some meaningful words to be added to some cells in the workbook
                List<String> wordsToBeWritten = Arrays.asList("they", "call", "it", "the", "rising", "sun");
    
                FileOutputStream out = new FileOutputStream(filePath.toAbsolutePath().toString());
                sheet = workbook.getSheetAt(0);
                XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
                // create new cells and write the words into them
                for (int i = 0; i < wordsToBeWritten.size(); i++) {
                    XSSFCell cell = row.createCell(i);
                    cell.setCellValue(wordsToBeWritten.get(i));
                }
                // close the FileInputStream
                in.close();
                // write the workbook using the FileOutputStream
                workbook.write(out);
                // force the FileOutputStream to write everything until it is empty
                out.flush();
                // close the FileOutputStream
                out.close();
                // close the workbook.
                workbook.close();
            } catch (FileNotFoundException e) {
                System.err.println(
                        "The file \"" + filePath.toAbsolutePath().toString() + "\" could not be found.");
                e.printStackTrace();
            } catch (IOException e) {
                System.err.println("Error while reading the file \"" + filePath.toAbsolutePath().toString() + "\"");
                e.printStackTrace();
            } catch (InvalidFormatException e) {
                System.out.println(
                        "The file \"" + filePath.toAbsolutePath().toString() + "\" has an invalid format(ting)");
                e.printStackTrace();
            } catch (EmptyFileException e) {
                System.err.println("The supplied file \"" + filePath.toAbsolutePath().toString() + "\" is empty.");
                e.printStackTrace();
            }
    }
    
    公共类PoiMain{
    公共静态void main(字符串[]args){
    /*
    *设置:
    *一个现有的xlsx文件,第一页包含6列和1行。
    *该行有6个填充了值的单元格
    *单元格1(索引0):有
    *单元2(索引1):是
    *第3单元(索引2):a
    *第4单元(索引3):房屋
    *第5单元(索引4):在
    *第6单元(指数5):新奥尔良
    * 
    *任务:
    *写下“他们”,“呼叫”,“它”,“太阳”,“升起”,“太阳”
    *在下面的单元格中。
    */
    //定义工作簿的(正确)路径
    String pathToFile=“Y:\\our\\path\\to\\the\\Test Workbook.xlsx”;//您也可以在此处使用xlsm
    //创建路径对象
    Path filePath=Path.get(pathToFile);
    //声明工作簿
    XSSF工作手册;
    试一试{
    /*
    *正在从.xlsx文件中读取:
    */
    FileInputStream in=newfileinputstream(filePath.toFile());
    工作簿=XSSFWorkbookFactory.createWorkbook(在中);
    XSSFSheet sheet=workbook.getSheetAt(0);
    //读取第一行的所有单元格并打印其内容
    对于(int i=0;i