Исключение при записи в документ xlsx несколько раз с использованием apache poi 3.7 - PullRequest
19 голосов
/ 24 ноября 2011

Я получаю следующее исключение при попытке записать файл .xlsx с использованием Apache POI: 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 ]

11 голосов
/ 20 марта 2012

У меня была такая же проблема сегодня. Я заметил, что многие люди задают один и тот же вопрос на разных форумах, но я нигде не видел ответа. Итак, вот что я придумала. Это далеко от идеала (я могу придумать по крайней мере два сценария, в которых это может быть плохой идеей), и может не подходить для всех нужд, но это работает!

После каждой операции сохранения внутри класса, к которому относится объект рабочей книги, я перезагружаю книгу из файла, в котором только что сохранила его.

Используя ваш пример кода выше, я бы изменил метод следующим образом:

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

Я проверил это в своем коде, и это хорошо решило проблему. Просто убедитесь, что вы прочитали его обратно из того же файла, в котором вы его сохранили, а не из более ранней или другой версии.

10 голосов
/ 24 ноября 2011

Скорее всего, это ошибка.

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

Я предлагаю вам подписаться на этот билет, чтобы получать уведомления о текущих улучшениях / альтернативах.

Если я найду обходной путь, я сообщу вам.

3 голосов
/ 26 июня 2013

Решение, которое я нашел для этого, и которое я искал некоторое время, состоит в том, чтобы убедиться, что вы не открываете свой 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.

0 голосов
/ 12 апреля 2017

У меня тоже была такая же проблема.Позже я попробовал другой метод, и он решил.В этом случае мы можем переместить код:

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

вне метода (int i), а затем в основном методе мы можем использовать:

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

Тогда workbook.write используется только один раз.Также данные могут быть изменены несколько раз.

0 голосов
/ 21 января 2015

Я тоже столкнулся с той же проблемой при использовании apache poi 3.10. Но после добавления последних файлов apache poi jar это сработало для меня. Пожалуйста, попробуйте после обновления банок до последней версии.

0 голосов
/ 11 мая 2013

Кажется, это действительно ошибка в 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);
0 голосов
/ 09 января 2013

Это происходит только тогда, когда мы пытаемся записать более одного раза в один и тот же файл, что и для файла .xlsx.Я столкнулся с той же проблемой и получил ее решение ..

  1. Раньше я писал дважды
  2. Теперь удалил первый вызов записи
  3. Пропущен тот же экземпляр рабочей книгик методу и задайте значения для новой ячейки
  4. наконец-то сделал еще некоторые изменения в книге, написав еще несколько столбцов и ячеек
  5. Затем записал с использованием потока вывода файла.

Работало

...