Ответ 1
Это скорее всего ошибка.
https://issues.apache.org/bugzilla/show_bug.cgi?id=49940
Я предлагаю вам подписаться на этот билет, чтобы получить уведомление о текущих улучшениях/альтернативах.
Если я найду обходное решение, я дам вам знать.
Я получаю следующее исключение при попытке записать файл .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);
}
}
Это скорее всего ошибка.
https://issues.apache.org/bugzilla/show_bug.cgi?id=49940
Я предлагаю вам подписаться на этот билет, чтобы получить уведомление о текущих улучшениях/альтернативах.
Если я найду обходное решение, я дам вам знать.
У меня была такая же проблема сегодня. Я заметил, что многие люди задавали один и тот же вопрос на разных форумах, но я нигде не видел ответа. Итак, вот что я придумал. Это далеко не идеальный (я могу думать, по крайней мере, о двух сценариях, где это может быть плохой идеей), и может не соответствовать каждой потребности, но он работает!
После каждой операции сохранения внутри класса, которым является объект рабочей книги, я перезагружаю книгу из файла, который я только что сохранил.
Используя приведенный выше пример кода, я бы изменил метод следующим образом:
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"));
}
Я тестировал это в своем коде, и он решил проблему хорошо. Просто убедитесь, что вы прочитали его обратно из того же файла, который вы сохранили, а не более ранней или другой версии.
Решение, которое я нашел для этого, и я искал какое-то время, должен убедиться, что вы не открываете свой 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
.
Это происходит только тогда, когда мы пытаемся писать несколько раз в тот же файл, что и для файла .xlsx. Я пришел по той же проблеме и решил ее решить.
Он работал
Я тоже столкнулся с такой же проблемой при использовании apache poi 3.10. Но после добавления последних файлов apache poi jar он работал у меня. Попробуйте обновить банки до последней версии.
У меня была такая же проблема. Позже я попробовал другой метод и решил.
В этом случае мы можем переместить код:
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 используется только один раз. Также данные могут быть изменены несколько раз.
Кажется, что это действительно ошибка в 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);