web-dev-qa-db-fra.com

Exception lors de l'écriture plusieurs fois sur le document xlsx avec Apache Poi 3.7

Je reçois l'exception suivante lors de la tentative d'écriture d'un fichier .xlsx à l'aide d'un POI Apache: org.Apache.xmlbeans.impl.values.XmlValueDisconnectedException

Il semble que le problème utilise la méthode write () une seconde fois. Lorsque vous travaillez avec un HSSFWorkbook de ce problème ne se pose pas.

Voici le code:

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);
}
}
18
Mihail

C'est probablement un bug.

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

Je vous suggère de vous abonner à ce ticket pour être averti des améliorations/alternatives en cours.

Si je trouve une solution de contournement, je vous le ferai savoir.

9
Ernani Joppert

J'ai eu le même problème aujourd'hui. J'ai remarqué que beaucoup de gens posaient la même question sur de nombreux forums différents, mais je n'ai vu aucune réponse nulle part. Alors, voici ce que je suis venu avec. C'est loin d'être idéal (je peux penser à au moins deux scénarios où cela pourrait être une mauvaise idée), et peut ne pas répondre à tous les besoins, mais cela fonctionne!

Après chaque opération de sauvegarde à l'intérieur de la classe dont l'objet de classeur est une propriété, je recharge le classeur à partir du fichier dans lequel je viens de l'enregistrer.

En utilisant votre exemple de code ci-dessus, je modifierais la méthode comme suit:

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

J'ai testé cela dans mon code et cela a bien résolu le problème. Assurez-vous simplement de le relire à partir du même fichier que celui dans lequel vous l'avez enregistré, et non d'une version antérieure ou différente.

11
Scott Offen

La solution que j'ai trouvée pour cela, et que je cherchais depuis un moment, est de s'assurer que vous n'ouvrez pas votre Workbook avec la File que vous utilisez pour ouvrir la FileOutputStream afin de sauvegarder la Workbook. Utilisez plutôt une FileInputStream pour ouvrir la Workbook.

Quelque chose comme ça fonctionnera parfaitement

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

N'oubliez pas de fermer tous les flux ouverts et la OPCPackage.

3
Jonathan Drapeau

Cela se produit uniquement lorsque nous essayons d’écrire plusieurs fois dans le même fichier qu’un fichier .xlsx. Je suis tombé sur le même problème et je l'ai résolu en ..

  1. Auparavant j'écrivais deux fois
  2. Maintenant retiré le premier appel en écriture
  3. Passé la même instance de classeur à la méthode et définition des valeurs dans la nouvelle cellule
  4. a finalement apporté quelques modifications supplémentaires au classeur en écrivant quelques colonnes et cellules
  5. Puis écrit en utilisant le flux de sortie du fichier.

Ça fonctionnait

0
Sriram Ramani

Moi aussi, j'ai rencontré le même problème avec Apache poi 3.10. Mais après l’ajout des derniers fichiers Apache poi jar, cela a fonctionné pour moi. S'il vous plaît essayez après la mise à jour des pots au plus tard.

0
Ashok Pandian

J'ai eu le même problème aussi. Plus tard, j'ai essayé une autre méthode et celle-ci a été résolue.
Dans ce cas, nous pouvons déplacer le code:

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

hors de la méthode (int i), puis dans la méthode principale, on peut utiliser:

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

Ensuite, le classeur.write n'est utilisé qu'une seule fois. Les données peuvent également être modifiées plusieurs fois.

0
Jing Wan