Подтвердить что ты не робот

Исключение при записи в документ xlsx несколько раз с помощью apache poi 3.7

Я получаю следующее исключение при попытке записать файл .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);
}
}
4b9b3361

Ответ 1

Это скорее всего ошибка.

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

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

Если я найду обходное решение, я дам вам знать.

Ответ 2

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

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

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

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

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

Ответ 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.

Ответ 4

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

  • Раньше я писал дважды
  • Теперь удалить первый вызов записи
  • Передал тот же экземпляр рабочей книги методу и установил значения в новую ячейку
  • наконец-то сделал несколько изменений в книге, написав несколько столбцов и ячеек
  • Затем написал, используя выходной поток файла.

Он работал

Ответ 5

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

Ответ 6

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

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 используется только один раз. Также данные могут быть изменены несколько раз.

Ответ 7

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