Невозможно записать и сохранить файл XLSM с помощью Apache POI. - PullRequest
1 голос
/ 03 июня 2019

У меня есть существующий файл XLSM, в который я пытаюсь записать данные с использованием Apache POI.

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();
}

Я получил сообщение об ошибке:

org.apache.poi.ooxml.POIXMLException: java.io.EOFException: неожиданно конец входного потока ZLIB

Проблема не связана с GZIPinStream и GZIPOutputStream.

ОБНОВЛЕНИЕ 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>

1 Ответ

1 голос
/ 04 июня 2019

Практически каждый раз, когда вы сталкиваетесь с ошибкой при открытии книги, созданной вами по коду, причиной является не правильно закрытый ресурс.К сожалению, я испытывал это много раз; -)

В моих случаях я мог решить проблему с помощью следующей последовательности действий (порядок имеет значение):

  1. написать рабочую книгу: workbook.write(out);
  2. заставляет FileOutputStream очистить все использованные буферы: out.flush();
  3. закрыть FileOutputStream: out.close();
  4. закрыть рабочую книгу: workbook.close();

Вот как я бы добавил недостающие действия в ваш код:

    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));
        // 1. write the workbook
        workbook.write(out);
        // 2. force the FileOutputStream to write everything out before closing it
        out.flush();
        // 3. then close the FileOutputStream
        out.close();
        // 4. finally close the workbook
        workbook.close();
        System.out.println("Data was written in XLSM");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (InvalidFormatException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

Обратите внимание, что очистка FileOutputStream не всегда может быть необходимой,но это было упомянуто в нескольких лучших уроках, касающихся apache-poi, поэтому я решил использовать его в своем коде.

Это работает для меня, я надеюсь, что оно подойдет и вам.

РЕДАКТИРОВАТЬ (ОП попросил мой пример кода в комментарии ниже)
Это независимый пример для чтения и расширения XSSFWorkbook.Это все только в методе main, но, по крайней мере, прокомментировано; -)
Вы должны изменить путь к книге, который в данном примере обычно равен String и впоследствии становится 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();
        }
}
...