0
votes

Pourquoi ne puis-je pas empêcher Apache POI de modifier le fichier source?

Je ouvre un fichier Excel (la source) en Java à l'aide d'un classeur Apache POI, modifiant les données dans un certain ensemble de cellules, enregistrant le classeur dans un fichier distinct, puis la clôture du classeur (car la documentation étage pour fermer la Le classeur, même s'il est en lecture seule).

POI modifie chaque fois les données du fichier Excel source à chaque fois. J'ai essayé quelques méthodes différentes pour éviter cela conformément aux recommandations de la documentation du POI, mais ces méthodes échouent. p>

Voici deux tentatives qui devraient fonctionner en théorie, mais ne le font pas. p>

tentative 1 - Définissez le fichier source pour en lire uniquement strong> p> xxx pré>

A FileNotFoundException code> pour "Accès est refusé" est lancé à workbookfactory.create (fichier) code>: p> xxx PRE>

Le fichier source existe et il est valablement en lecture seule. P>

Tentative 2 - Utilisez le constructeur d'API POI qui permet de définir uniquement explicitement fort> p> xxx pré>

an INVALIDOPERATIONEXCEPTION CODE> est lancée pendant l'appel d'écriture: p>

Caused by: org.apache.poi.openxml4j.exceptions.InvalidOperationException: 
Operation not allowed, document open in read only mode!
at org.apache.poi.openxml4j.opc.OPCPackage.throwExceptionIfReadOnly(OPCPackage.java:551)
at org.apache.poi.openxml4j.opc.OPCPackage.removePart(OPCPackage.java:955)
at org.apache.poi.openxml4j.opc.PackagePart.getOutputStream(PackagePart.java:531)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.commit(XSSFWorkbook.java:1770)
at org.apache.poi.ooxml.POIXMLDocumentPart.onSave(POIXMLDocumentPart.java:463)
at org.apache.poi.ooxml.POIXMLDocument.write(POIXMLDocument.java:236)
at com.stackoverflow.MyClass(MyClass.java:90)


5 commentaires

Vous devez ouvrir un deuxième classeur et écrire à celui-là un compagnon, j'ai fait quelque chose comme ça il y a quelques mois, je vérifierai


Que veux-tu dire par là; Créez un deuxième classeur en utilisant toutes les données de l'original comme source, puis manipulez le deuxième classeur? Pouvez-vous fournir un échantillon de code? Je verrai si je peux trouver quelque chose en ligne à ce sujet.


L'utilisation du fichier pour créer xssfworkbook a ces inconvénients. C'est un problème connu. Voir Stackoverflow.com/questions/55929312/... et stackoverflow.com/questions/46146161/... et Stackoverflow.com/Questtions/45708114/... . Utilisez FileInputStream au lieu de fichier pour créer le xssfworkbook .


@Joshdm Oui, créez une seconde zone de travail qui est celle qui va appeler .write (), l'autre est juste pour lire frère, consultez ma réponse attentivement j'ai commenté


@Axelrichter - J'ai été informé que le processus FileInputStream a été tenté et il a modifié l'original; Cependant, lorsque nous l'avons récupéré, enveloppé dans une bufferedInputStream, il réussit et sera notre code.


4 Réponses :


2
votes

Vous devez avoir deux classeurs, l'un où vous obtenez le Datafrom (lu) et un autre que vous écrivez à.

Look Man, c'est comme ça que j'ai fait il y a quelques mois, veuillez noter que j'utilise. ) Sur le deuxième cahier de travail (HSSFWorkBookNew), pas celui que vous utilisez pour lire les données, lisez-le soigneusement. Ce code est juste pour obtenir une première feuille d'un Excel XLS et la copier dans un nouveau fichier. P>

// this method generates a new excelFile based on the excelFile he receives

public void generarXLS(File excelFile, File excelNewFile) {
        InputStream excelStream = null;
        OutputStream excelNewOutputStream = null;
        try {
            excelStream = new FileInputStream(excelFile);
            excelNewOutputStream = new FileOutputStream(excelNewFile);
            // Representation of highest level of excel sheet.
            HSSFWorkbook hssfWorkbook = new HSSFWorkbook(excelStream);
            HSSFWorkbook hssfWorkbookNew = new HSSFWorkbook();

            // Chose the sheet that we pass as parameter.
            HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(0);

            // Create new sheet we are gonna use.
            HSSFSheet hssfSheetNew = hssfWorkbookNew.createSheet("Copy-Copia");

            // Create new sheet where we will copy the data

            // Object that allow us to read a row from the sheet and extract the data from the cells
            HSSFRow hssfRow;
            HSSFRow hssfRowNew; // for hssfSheetNew
            // Initialize the object that reads value of cell
            HSSFCell cellNew;
            // Get number of rows of the sheet
            int rows = hssfSheet.getLastRowNum();
            String cellValue;

            // Style of the cell border, color background and pattern (fill pattern) used.
            CellStyle style = hssfWorkbookNew.createCellStyle();
            // Definition of the font of the cell.

            // Iterate trhough all rows to get the cells and copy them to the new sheet
            for (Row row : hssfSheet) {
                hssfRowNew = hssfSheetNew.createRow(row.getRowNum());

                if (row.getRowNum() > 999999) {
                    break;
                }

                for (Cell cell : row) {

                    cellValue = (cell.getCellType() == CellType.STRING) ? cell.getStringCellValue()
                            : (cell.getCellType() == CellType.NUMERIC) ? "" + cell.getNumericCellValue()
                                    : (cell.getCellType() == CellType.BOOLEAN) ? "" + cell.getBooleanCellValue()
                                            : (cell.getCellType() == CellType.BLANK) ? ""
                                                    : (cell.getCellType() == CellType.FORMULA) ? "FORMULA"
                                                            : (cell.getCellType() == CellType.ERROR) ? "ERROR" : "";

                    cellNew = hssfRowNew.createCell(cell.getColumnIndex(), CellType.STRING);
                    cellNew.setCellValue(cellValue);

                }
            }
            // NOTICE how I write to the new workbook
            hssfWorkbookNew.write(excelNewOutputStream);
            hssfWorkbook.close();
            hssfWorkbookNew.close();
            excelNewOutputStream.close();

            JOptionPane.showMessageDialog(null, Constantes.MSG_EXITO, "Informacion", 1);

        } catch (FileNotFoundException fileNotFoundException) {
            JOptionPane.showMessageDialog(null, "file not found", "Error", 0);

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Error processing the file", "Error", 0);

        } finally {
            try {
                excelStream.close();
            } catch (IOException ex) {
                System.out.println("Error processing the file after closing it): " + ex);
            }
        }
    }


2 commentaires

Notez que j'utilise un HSSFWorkBook pour la lecture et une autre pour écrire, vous devez faire comme ça


J'ai fait quelque chose de similaire, mais beaucoup plus court: byteArrayOutPutStream OS = nouveau byearrayOutPutStream (4096); workbook.write (OS); workbook.close (); workbook = workbookfactory.create (nouveau byearrayInputStream (OS.TobyTeArray ())); Cependant, nous utiliserons l'appel de BufferedInputStream créé dans un autre commentaire pour résoudre ce problème.



2
votes

J'ai eu le même problème et j'ai résolu-le en utilisant un fichierInputStream code> au lieu d'un fichier code>.

Workbook workbook = WorkbookFactory.create(new FileInputStream(file));


0 commentaires

1
votes

Je devais gérer XSSF et HSSF; C'est comme ça que c'était accompli: xxx


0 commentaires

0
votes

Peut-être que vous pourriez aussi utiliser simplement la signature Créer

workbook workbook = workbookfactory.create (nouveau fichier ("// serveur / chemin / fichier / fichier.ext"), null, true);

Demander à POI d'ouvrir la feuille de calcul Lecture seulement?


0 commentaires