2013-04-19 9 views
6

utilizzando il seguente codice, le variazioni di valore delle cellule apportate al mio foglio di calcolo di Excel non sono salvati:Perché il metodo close() di Apache POI OPCPackage close() non salva/scrive il contenuto per aprire il file scrivibile?

OPCPackage pkg = OPCPackage.open(inputFile); 
XSSFWorkbook wb = new XSSFWorkbook(pkg); 

ModifyWorkbook(); 

pkg.close(); 

La seguente è una soluzione che ho scritto, ma non capisco il motivo per cui è necessario.

OPCPackage pkg = OPCPackage.open(inputFile); 
XSSFWorkbook wb = new XSSFWorkbook(pkg); 

ModifyWorkbook(); 

File tmp = File.createTempFile("tempSpreadsheet", ".xlsx"); 
FileOutputStream newExcelFile = new FileOutputStream(tmp); 
wb.write(newExcelFile); 
newExcelFile.close(); 
tmp.deleteOnExit(); 
pkg.close(); 

Le javadocs e guide sull'argomento indicano che il metodo .close() deve salvare e chiudere. Controlla i valori delle celle modificate, prima della chiusura, indica che le modifiche sono state apportate, ma il metodo pkg.close() da solo non è sufficiente per scrivere quelle modifiche al file quando è chiuso.

risposta

2

Una chiamata a OPCPackage.close() chiuderà la struttura di file OOXML sottostante. Quello che non farà è causare XSSF (o uno qualsiasi dei formati X ?? F) per scrivere le loro modifiche. Quindi, scriverai un file non modificato ....

Se stai facendo modifiche di basso livello, puoi aprire OPCPackage, apportare modifiche, quindi chiamare close per scriverle. Se stai facendo cose di alto livello, apri OPCPackage, lavora con il codice UserModel per apportare modifiche, quindi chiedi al usermodel di scrivere le sue modifiche. È questo ultimo passaggio che è importante.

Il codice attuale è un po 'come:

File f = new File("test.txt"); 
Sting s = readFileCompletely(f); 
s = s.replaceAll("foo", "bar"); 
f.close(); 
// Why hasn't the file contents changed? 

la lettura del file e modificare gli oggetti di alto livello non è sufficiente, è necessario anche per raccontare gli oggetti di alto livello per scrivere le modifiche. (Gli oggetti di alto livello le cose di cache in memoria per motivi di prestazioni)

1

Calling close su un (XSSF) Workbook chiamerà OPCP.close che javadoc stati:

Calling myWorkbook.close() dovrebbe scrivere le modifiche su file è stato aperto da.

Tuttavia, la versione corrente (3.15) sembra avere problemi a farlo. La ragione in sé è sconosciuta a me, ma ho scoperto che chiamando lo myWorkbook.write() si impegnano non solo le modifiche al flusso di output, ma anche all'istanza corrente dopo aver chiamato close.

Una soluzione ragionevole potrebbe quindi essere:

try (OutputStream bos = ByteStreams.nullOutputStream()){ 
    workbook.write(bos); 
    workbook.close(); 
} catch (IOException e) { 
    log.error("Could not write Output File", e); 
} 

Ecco fatto con Guavas ByteStreams. Sentiti libero di usare le implementazioni del flusso di output nullo other.