So erhalten Sie eine Liste mit Excel-Blattnamen in Java (POI vs SAX)

Einführung

Wenn Sie programmgesteuert mit Excel-Dateien arbeiten, ist es häufig wünschenswert, eine Liste der Blattnamen als ersten Schritt bei der Analyse des Blattinhalts zu erhalten. Ich bin auch auf eine solche Situation gestoßen, als ich das in [Vorheriger Beitrag] eingeführte Excel-Dateivergleichstool "Square Diff" (https://qiita.com/nmby/items/ca7227a1048528b1bf31) erstellt habe.

In diesem Artikel zeige ich Ihnen drei Möglichkeiten, um eine Liste der Blattnamen in einer Excel-Arbeitsmappe in Java abzurufen:

Verwendung der Apache POI-Benutzermodell-API

Was ist Apache POI?

Apache POI ist eine Java-Bibliothek (und ihr Projekt), die Dateien im Microsoft Office-Format lesen und schreiben kann und von der Apache Software Foundation unter der Apache License 2.0 veröffentlicht wird. Sie können es verwenden, indem Sie die Bibliothek zum Erstellungspfad hinzufügen. (Die Methode wird am Ende dieses Artikels vorgestellt.)

POI bietet die Usermodel-API und die Eventmodel-API, die später eingeführt werden. Die Usermodel-API ist Ihre erste Wahl, wenn Sie mit Excel in Java arbeiten.

Implementierungsbeispiel [^ 1]

[^ 1]: In dem in diesem Artikel vorgestellten Codebeispiel wird die Verarbeitung, die nicht mit der Hauptzeile zusammenhängt, wie z. B. die Eingabeprüfung, aufgrund der Papierbreite weggelassen.

Implementierungsbeispiel 1: SheetListerWithPOIUsermodelAPI.java


package mypackage;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

public class SheetListerWithPOIUsermodelAPI {
    
    /**
     *Gibt eine Liste der Blattnamen zurück, die in der angegebenen Excel-Datei enthalten sind.
     * 
     * @Parameterdatei Excel-Datei
     * @return Liste der Blattnamen
     */
    public static List<String> getSheetNames(File file) throws Exception {
        
        try (Workbook book = WorkbookFactory.create(file)) {
            
            return IntStream.range(0, book.getNumberOfSheets())
                    .mapToObj(book::getSheetAt)
                    .map(Sheet::getSheetName)
                    .collect(Collectors.toList());
        }
    }
    
    public static void main(String[] args) throws Exception {
        List<String> sheetNames = getSheetNames(
                new File("C:\\Users\\user01\\Desktop\\Verkaufsliste für Spielautomaten.xls"));
        
        sheetNames.forEach(System.out::println);
    }
}

Ausführungsergebnis


Verkaufsliste_2016
Graph_2016
Verkaufsliste_2017
Graph_2017
Verkaufsliste_2018
Graph_2018

Kommentar

Die Usermodel-API von POI muss zuerst die gesamte Excel-Datei lesen und analysieren. Dies ist der Teil von "Workbook book = WorkbookFactory.create (file)". Danach wird die Liste der Blattnamen unter Verwendung von "Arbeitsmappe # getNumberOfSheets ()", "Arbeitsmappe # getSheetAt (int)", "Blatt # getSheetName ()" usw. abgerufen. [^ 2]

Das obige Codebeispiel funktioniert mit Dateien im XLS-Format, Sie können jedoch auch mit Dateien im XLSX- / XLSM-Format arbeiten.

[^ 2]: Die Apache POI API-Dokumentation finden Sie hier: http://poi.apache.org/apidocs/index.html

Vorteile

Eine transparente Verarbeitung ist möglich

Für die transparente Verarbeitung stehen verschiedene APIs zur Verfügung, ohne das Dateiformat (XLS-Format oder XLSX / XLSM-Format) zu kennen.

Objektorientierte, leicht verständliche Modellierung

Bücher, Blätter, Zeilen, Zellen usw. werden in dem objektorientierten Stil modelliert, den Java-Programmierer gewohnt sind, und können intuitiv verstanden und gehandhabt werden.

Nachteile

Benötigt viel Speicher und Verarbeitungszeit

Da die Usermodel-API zuerst die gesamte Excel-Arbeitsmappe laden und analysieren muss, benötigen Sie den Speicherplatz und die Verarbeitungszeit abhängig vom Inhalt der gesamten Excel-Datei, auch wenn Sie nur den Blattnamen abrufen möchten. Dies kann ein praktischer Engpass sein.

Ich kann den juckenden Ort nicht erreichen

Die aktuelle Usermodel-API ist bei weitem nicht voll funktionsfähig.

Im obigen Codebeispiel wird beispielsweise der Name des Diagrammblatts zusätzlich zum Arbeitsblatt ausgegeben. Dies ist schwierig, wenn Sie nur auf den Arbeitsblattnamen eingrenzen möchten. Es wäre schön, eine API wie "Sheet # isChartSheet" zu haben, aber das tut es nicht.

Die Schnittstelle / Klasse für die Behandlung von Excel-Tabellen hat die folgende hierarchische Struktur.

Blatt: Eine Schnittstelle zum transparenten Umgang mit allen Arten von Blättern
  ├─ XSSFSheet : .xlsx/.XLSM-Formatblatt
  │    └─ XSSFChartSheet : .xlsx/.Diagrammblatt im XLSM-Format
  │
  └─ HSSFSheet : .XLS-Formatblatt

Wenn die zu verarbeitende Excel-Datei im XLSX / XLSM-Format vorliegt, können Sie das Diagrammblatt ausschließen, indem Sie den Quellcode wie folgt ändern.

Implementierungsbeispiel 1-Kai


(Weggelassen)
    
    return IntStream.range(0, book.getNumberOfSheets())
            .mapToObj(book::getSheetAt)
            .filter(s -> !(s instanceof XSSFChartSheet))  //Füge das hinzu
            .map(Sheet::getSheetName)
            .collect(Collectors.toList());
    
(Weggelassen)

Es gibt jedoch keine Möglichkeit, Diagrammblätter im XLS-Format auszuschließen [^ 3]. Wenn Sie versuchen, mit POI etwas Aufwändiges zu tun, werden Sie süchtig danach, nacheinander auf solche Probleme zu stoßen.

Wenn diese Mängel kein Problem darstellen, ist die POI-Benutzermodell-API möglicherweise Ihre erste Wahl. In anderen Fällen müssen Sie auf andere Methoden zurückgreifen.

[^ 3]: Vielleicht weiß ich es einfach nicht. Wenn Sie das wissen, hinterlassen Sie bitte einen Kommentar.

Verwendung der Apache POI-Ereignismodell-API

Was ist die Eventmodel-API von POI?

Die Eventmodel-API ist eine Funktion zum schnellen Lesen von Excel-Dateien und mit wenig Speicher. Das Schreiben in Dateien wird nicht unterstützt.

Die Eventmodel-API liest die Excel-Datei von Anfang bis Ende in eine Richtung und benachrichtigt die Anwendung über den Inhalt der Datei in Form eines Ereignisses. Die Anwendung führt eine eigene Verarbeitung entsprechend dem Inhalt des Ereignisses durch.

"Square Diff" verwendet diese Methode, um die Blattnamenliste aus einer Excel-Arbeitsmappe im XLS-Format zu lesen. Hier ist ein Implementierungsbeispiel für die Arbeit mit einer Excel-Arbeitsmappe im XLS-Format.

Implementierungsbeispiel

Abrufen des Arbeitsblattnamens und des Diagrammblattnamens

Implementierungsbeispiel 2-a:HSSFSheetListerWithPOIEventAPI.java


package mypackage;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class HSSFSheetListerWithPOIEventAPI {
    
    private static class HSSFSheetListingListener implements HSSFListener {
        
        private final List<String> sheetNames = new ArrayList<>();
        
        @Override
        public void processRecord(Record record) {
            if (record.getSid() == BoundSheetRecord.sid) {
                BoundSheetRecord bSheetRecord = (BoundSheetRecord) record;
                sheetNames.add(bSheetRecord.getSheetname());
            }
        }
    }
    
    /**
     *Gibt eine Liste der Blattnamen zurück, die in der angegebenen Excel-Datei enthalten sind.
     * 
     * @Parameterdatei Excel-Datei
     * @return Liste der Blattnamen
     */
    public static List<String> getSheetNames(File file) throws Exception {
        
        try (FileInputStream fis = new FileInputStream(file);
                POIFSFileSystem poifs = new POIFSFileSystem(fis)) {
            
            HSSFRequest req = new HSSFRequest();
            HSSFSheetListingListener listener = new HSSFSheetListingListener();
            req.addListenerForAllRecords(listener);
            HSSFEventFactory factory = new HSSFEventFactory();
            factory.abortableProcessWorkbookEvents(req, poifs);
            
            return listener.sheetNames;
        }
    }
    
    public static void main(String[] args) throws Exception {
        List<String> sheetNames = getSheetNames(
                new File("C:\\Users\\user01\\Desktop\\Verkaufsliste für Spielautomaten.xls"));
        
        sheetNames.forEach(System.out::println);
    }
}

Ausführungsergebnis


Verkaufsliste_2016
Graph_2016
Verkaufsliste_2017
Graph_2017
Verkaufsliste_2018
Graph_2018

Um nur den Arbeitsblattnamen zu erhalten

Implementierungsbeispiel 2-b:HSSFSheetListerWithPOIEventAPI.java


package mypackage;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
import org.apache.poi.hssf.eventusermodel.HSSFListener;
import org.apache.poi.hssf.eventusermodel.HSSFRequest;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class HSSFSheetListerWithPOIEventAPI {
    
    private static class HSSFSheetListingListener implements HSSFListener {
        
        private final Queue<String> queue = new ArrayDeque<>();
        private final List<String> sheetNames = new ArrayList<>();
        
        @Override
        public void processRecord(Record record) {
            switch (record.getSid()) {
            case BoundSheetRecord.sid:
                BoundSheetRecord bSheetRecord = (BoundSheetRecord) record;
                queue.add(bSheetRecord.getSheetname());
                break;
            
            case BOFRecord.sid:
                BOFRecord bofRecord = (BOFRecord) record;
                
                switch (bofRecord.getType()) {
                case BOFRecord.TYPE_WORKSHEET:
                    sheetNames.add(queue.remove());
                    break;
                
                case BOFRecord.TYPE_CHART:
                    queue.remove();
                    break;
                }
                
                break;
            }
        }
    }
    
    //Danach Implementierungsbeispiel 2-Gleich wie ein
    
    /**
     *Gibt eine Liste der Blattnamen zurück, die in der angegebenen Excel-Datei enthalten sind.
     * 
     * @Parameterdatei Excel-Datei
     * @return Liste der Blattnamen
     */
    public static List<String> getSheetNames(File file) throws Exception {
        
        try (FileInputStream fis = new FileInputStream(file);
                POIFSFileSystem poifs = new POIFSFileSystem(fis)) {
            
            HSSFRequest req = new HSSFRequest();
            HSSFSheetListingListener listener = new HSSFSheetListingListener();
            req.addListenerForAllRecords(listener);
            HSSFEventFactory factory = new HSSFEventFactory();
            factory.abortableProcessWorkbookEvents(req, poifs);
            
            return listener.sheetNames;
        }
    }
    
    public static void main(String[] args) throws Exception {
        List<String> sheetNames = getSheetNames(
                new File("C:\\Users\\user01\\Desktop\\Verkaufsliste für Spielautomaten.xls"));
        
        sheetNames.forEach(System.out::println);
    }
}

Ausführungsergebnis


Verkaufsliste_2016
Verkaufsliste_2017
Verkaufsliste_2018

Kommentar

Wie bereits erwähnt, empfängt die Eventmodel-API von POI den Inhalt der Datei als Ereignis. Sie müssen die HSSFListener-Schnittstelle implementieren und die processRecord (Record) -Methode überschreiben, um Ereignisse zu empfangen.

Die Methode "processRecord (Record)" wird bei jedem Lesen der Datei aufgerufen, sodass die Anwendung entsprechend dem Inhalt des Ereignisses (insbesondere dem Inhalt des als Argument übergebenen Objekts "Record") verarbeitet. In Implementierungsbeispiel 2-a lautet das Ereignis "record.getSid () == BoundSheetRecord.sid" und in Implementierungsbeispiel 2-b "record.getSid () == BoundSheetRecord.sid" oder "record.getSid () == Verarbeitung eines Ereignisses mit dem Namen BOFRecord.sid`.

Zu verstehen, welche Ereignisse in welcher Reihenfolge auftreten, kann eine entmutigende Aufgabe sein. Ich kann die API-Dokumentation für die Datensatzschnittstelle (http://poi.apache.org/apidocs/org/apache/poi/hssf/record/Record.html) und ihre Unterschnittstellen und Unterklassen sowie den folgenden Code anzeigen: Ich vertiefte allmählich mein Verständnis, während ich die tatsächlichen Veranstaltungsinhalte verglich.

Den tatsächlichen Ereignisinhalt ausgeben und prüfen


(Weggelassen)
    
    @Override
    public void processRecord(Record record) {
        System.out.println(record);
    }
    
(Weggelassen)

Beachten Sie, dass nur Excel-Arbeitsmappen im XLS-Format von den Implementierungsbeispielen 2-a und 2-b verarbeitet werden können. Es können keine Excel-Arbeitsmappen im XLSX- / XLSM-Format verarbeitet werden.

Vorteile

Funktioniert schnell mit wenig Speicher

Da die eventmodel-API eine Methode zum Lesen vom Anfang bis zum Ende einer Datei mit einem Stream ist, arbeitet sie mit wenig Speicher schneller als die usermodel-API, bei der der gesamte Dateiinhalt analysiert und im Speicher gehalten wird. ..

Feinverarbeitung ist möglich

Da der Dateiinhalt fast direkt gelesen werden kann, ist es möglich, eine Verarbeitung zu realisieren, die von der Usermodel-API nicht realisiert werden kann.

Nachteile

Erfordert ein Verständnis der internen Struktur der Datei

Für die Verarbeitung mit der Eventmodel-API ist es wichtig, die interne Struktur der Excel-Datei zu verstehen, z. B. welche Art von Ereignissen in welcher Reihenfolge auftreten.

Es gibt ein Nachschlagewerk. "Microsoft Excel 97 Developers Kit". Ausländische Bücher vergriffen. Zum Zeitpunkt des Schreibens dieses Artikels waren gebrauchte Bücher aufgelistet = 1530997082 & sr = 8-1 & keywords = 1572314982).

Die API-Dokumentation für die Implementierungsklasse "Record" enthält Verweise auf dieses Buch. In der API-Dokumentation für die Klasse "BoundSheetRecord" finden Sie beispielsweise "REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit". (ISBN: 1-57231-498-2) ". Wenn Sie eine vollwertige Anwendung erstellen, müssen Sie mit einem Nachschlagewerk in einer Hand arbeiten.

Ich fuhr mit der Implementierung fort, während ich die API-Dokumentation und den tatsächlichen Datensatzinhalt überprüfte. In beiden Fällen werden Sie zu einer Trial-and-Error-Implementierung gezwungen.

Ein wahlfreier Zugriff auf Dateiinhalte ist nicht möglich

Da die eventmodel-API die Datei von Anfang bis Ende nur in einer geraden Linie liest, können Sie den Inhalt der Datei selbst verwalten und aufzeichnen, wenn es erforderlich ist, den Inhalt an der Vorderseite der Datei anhand des Inhalts an der Rückseite der Datei zu bewerten. wird gebraucht.

Verwendung von SAX

Was ist SAX?

SAX steht für Simple API for XML und wird als Standard-API in Java8 im Paket org.xml.sax bereitgestellt. Ähnlich wie die Eventmodel-API von POI liest sie die XML-Datei von Anfang bis Ende in eine Richtung und benachrichtigt die Anwendung über den Inhalt der XML-Datei als Ereignis.

Bekanntlich ist die Excel-Datei im XLSX / XLSM-Format eine ZIP-Datei, die aus mehreren XML-Dateien besteht. Sie können also SAX verwenden, um den Inhalt einer Excel-Arbeitsmappe zu lesen.

"Square Diff" verwendet diese Methode, um die Blattnamenliste aus einer Excel-Arbeitsmappe im XLSX- / XLSM-Format zu lesen.

Implementierungsbeispiel

Abrufen des Arbeitsblattnamens und des Diagrammblattnamens

Implementierungsbeispiel 3-a:XSSFSheetListerWithSAX.java


package mypackage;

import java.io.File;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class XSSFSheetListerWithSAX {
    
    /**
     *Als Zip-Datei.xlsx/.Lesen Sie den folgenden Eintrag aus der xlsm-Datei
     *Extrahieren Sie die Liste der Blattnamen.
     * 
     * *.xlsx
     *   +- xl
     *     +- workbook.xml
     */
    private static class Handler1 extends DefaultHandler {
        
        private final List<String> names = new ArrayList<>();
        
        @Override
        public void startElement(
                String uri,
                String localName,
                String qName,
                Attributes attributes) {
            
            if ("sheet".equals(qName)) {
                names.add(attributes.getValue("name"));
            }
        }
    }
    
    /**
     *Gibt eine Liste der Blattnamen zurück, die in der angegebenen Excel-Datei enthalten sind.
     * 
     * @Parameterdatei Excel-Datei
     * @return Liste der Blattnamen
     */
    public static List<String> getSheetNames(File file) throws Exception {
        try (FileSystem fs = FileSystems.newFileSystem(file.toPath(), null)) {
            Handler1 handler1 = new Handler1();
            
            try (InputStream is = Files.newInputStream(
                    fs.getPath("xl/workbook.xml"))) {
                
                InputSource source = new InputSource(is);
                XMLReader parser = XMLReaderFactory.createXMLReader();
                parser.setContentHandler(handler1);
                parser.parse(source);
            }
            
            return handler1.names;
        }
    }
    
    public static void main(String[] args) throws Exception {
        List<String> sheetNames = getSheetNames(
                new File("C:\\Users\\user01\\Desktop\\Verkaufsliste für Spielautomaten.xlsx"));
        
        sheetNames.forEach(System.out::println);
    }
}

Ausführungsergebnis


Verkaufsliste_2016
Graph_2016
Verkaufsliste_2017
Graph_2017
Verkaufsliste_2018
Graph_2018

Um nur den Arbeitsblattnamen zu erhalten

Implementierungsbeispiel 3-b:XSSFSheetListerWithSAX.java


package mypackage;

import java.io.File;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

public class XSSFSheetListerWithSAX {
    
    /**
     *Als Zip-Datei.xlsx/.Lesen Sie den folgenden Eintrag aus der xlsm-Datei
     *Extrahieren Sie die Liste der Blattnamen und die Karte der Blattnamen und Blatt-IDs (relId).
     * 
     * *.xlsx
     *   +- xl
     *     +- workbook.xml
     */
    private static class Handler1 extends DefaultHandler {
        
        private final List<String> names = new ArrayList<>();
        private final Map<String, String> nameToId = new HashMap<>();
        
        @Override
        public void startElement(
                String uri,
                String localName,
                String qName,
                Attributes attributes) {
            
            if ("sheet".equals(qName)) {
                names.add(attributes.getValue("name"));
                nameToId.put(
                        attributes.getValue("name"),
                        attributes.getValue("r:id"));
            }
        }
    }
    
    /**
     *Als Zip-Datei.xlsx/.Lesen Sie den folgenden Eintrag aus der xlsm-Datei
     *Extrahieren Sie die Karte aus Blatt-ID (relId) und Eingabepfad.
     * 
     * *.xlsx
     *   +- xl
     *     +- _rels
     *       +- workbook.xml.rels
     */
    private static class Handler2 extends DefaultHandler {
        
        private final Map<String, String> idToSource = new HashMap<>();
        
        @Override
        public void startElement(
                String uri,
                String localName,
                String qName,
                Attributes attributes) {
            
            if ("Relationship".equals(qName)) {
                idToSource.put(
                        attributes.getValue("Id"),
                        attributes.getValue("Target"));
            }
        }
    }
    
    /**
     *Gibt eine Liste der Blattnamen zurück, die in der angegebenen Excel-Datei enthalten sind.
     * 
     * @Parameterdatei Excel-Datei
     * @return Liste der Blattnamen
     */
    public static List<String> getSheetNames(File file) throws Exception {
        try (FileSystem fs = FileSystems.newFileSystem(file.toPath(), null)) {
            
            Handler1 handler1 = new Handler1();
            try (InputStream is = Files.newInputStream(
                    fs.getPath("xl/workbook.xml"))) {
                
                InputSource source = new InputSource(is);
                XMLReader parser = XMLReaderFactory.createXMLReader();
                parser.setContentHandler(handler1);
                parser.parse(source);
            }
            
            Handler2 handler2 = new Handler2();
            try (InputStream is = Files.newInputStream(
                    fs.getPath("xl/_rels/workbook.xml.rels"))) {
                
                InputSource source = new InputSource(is);
                XMLReader parser = XMLReaderFactory.createXMLReader();
                parser.setContentHandler(handler2);
                parser.parse(source);
            }
            
            return handler1.names.stream()
                    .filter(name -> {
                        String id = handler1.nameToId.get(name);
                        String source = handler2.idToSource.get(id);
                        return source.startsWith("worksheets/");
                    })
                    .collect(Collectors.toList());
        }
    }
    
    public static void main(String[] args) throws Exception {
        List<String> sheetNames = getSheetNames(
                new File("C:\\Users\\user01\\Desktop\\Verkaufsliste für Spielautomaten.xlsx"));
        
        sheetNames.forEach(System.out::println);
    }
}

Ausführungsergebnis


Verkaufsliste_2016
Verkaufsliste_2017
Verkaufsliste_2018

Kommentar

Um den Inhalt der XML-Datei als Ereignis zu erhalten, ist es zweckmäßig, "org.xml.sax.helpers.DefaultHandler" zu erben. Überschreiben Sie von den verschiedenen Rückrufmethoden, die von der DefaultHandler-Klasse bereitgestellt werden, die Rückrufmethode, die dem von Ihrer Anwendung geforderten Ereignis entspricht.

Im obigen Codebeispiel wird die Methode "startElement (String, String, String, Attributes)" verwendet, die jedes Mal aufgerufen wird, wenn das Start-Tag einer XML-Datei angezeigt wird.

In Implementierungsbeispiel 3-a wird der Eintrag "xl / workbook.xml" hinzugefügt, wenn die Excel-Datei als Zip-Datei entpackt wird, und in Implementierungsbeispiel 3-b wird der Eintrag "xl / _rels / workbook.xml.rels" hinzugefügt. Liest.

Die Erklärung, wie man sie analysiert, wird langwierig sein, deshalb werde ich sie weglassen. Durch Extrahieren der Excel-Datei im XLSX- / XLSM-Format mit dem ZIP-Dekomprimierungswerkzeug können Sie den Inhalt der XML-Dateien, aus denen die Excel-Datei besteht, problemlos überprüfen. Bitte lesen Sie das obige Codebeispiel, während Sie Ihre Excel-Datei überprüfen.

Vorteile

Funktioniert schnell mit wenig Speicher

Ähnlich wie die Eventmodel-API von POI läuft sie schnell und spart Speicher. Darüber hinaus können nur die erforderlichen XML-Dateien gelesen werden, aus denen eine Excel-Datei besteht, wodurch sie noch schneller wird.

Feinverarbeitung ist möglich

Da der Dateiinhalt direkt gelesen werden kann, ist es möglich, eine Verarbeitung zu realisieren, die mit der Usermodel-API von POI nicht erreicht werden kann.

Benötigt keine externe Bibliothek

org.xml.sax und seine Unterpakete werden in Java8 als Standard-APIs bereitgestellt. Sie müssen sich nicht auf externe Bibliotheken verlassen.

Nachteile

Erfordert ein Verständnis der internen Struktur der Datei

Wie bei der Eventmodel-API von POI ist ein Verständnis der internen Struktur von Excel-Dateien unerlässlich. Die Struktur von Excel-Arbeitsmappen im XLSX- / XLSM-Format wird jedoch als Office Open XML bezeichnet und ist als ISO / IEC 29500 standardisiert. Daher ist es relativ einfach, Spezifikationsinformationen zu erhalten. Da der Inhalt mit dem ZIP-Dekomprimierungswerkzeug leicht überprüft werden kann, ist die Handhabung einfacher als die Handhabung einer Excel-Arbeitsmappe im XLS-Format mit der Eventmodel-API von POI.

Ein wahlfreier Zugriff auf Dateiinhalte ist nicht möglich

Wie die Eventmodel-API von POI liest SAX die XML-Datei nur von Anfang bis Ende in einer geraden Linie. Wenn Sie also den Inhalt am Anfang der Datei anhand des Inhalts am Ende der Datei bewerten müssen, Es ist notwendig, den Dateiinhalt mit zu verwalten und aufzuzeichnen.

abschließend

In diesem Artikel haben wir die folgenden drei Methoden zum Abrufen einer Liste von Blattnamen vorgestellt, die in einer Excel-Datei in Java enthalten sind.

Jede Methode hat Vor- und Nachteile, und wir Programmierer müssen sie je nach Zweck richtig einsetzen.

Ich selbst habe alle drei oben genannten Methoden zum ersten Mal in Frage gestellt, als ich vor der Notwendigkeit stand, "square Diff" zu erstellen. Insbesondere empfand ich die Verwendung der Eventmodel-API und von SAX als eine hohe Hürde, aber überraschenderweise ist es nicht so schwierig, wenn Sie es einmal gestartet haben, und es fühlt sich praktisch an, wenn Sie sich daran gewöhnt haben. Wenn Sie den anfänglichen Widerstand überwinden und sich der Herausforderung stellen, kann sich der Bereich der Montageleistung erweitern.

"Square Diff" verwendet auch mehrere Methoden, um Excel-Dateien zu aktualisieren. Ich möchte dies noch einmal in das Manuskript einführen.

APPENDIX

Verwendung der Apache POI-Bibliothek zusätzlich zum Erstellungspfad

Sie können diese Funktionalität nutzen, indem Sie einige der von Apache POI bereitgestellten JAR-Dateien zu Ihrem Erstellungspfad hinzufügen. So fügen Sie Ihrem Erstellungspfad in Eclipse eine manuell heruntergeladene JAR-Datei hinzu. (Bitte drücken Sie andere Möglichkeiten, um Maven usw. zu verwenden.)

1. Laden Sie die Bibliothek herunter (Zip-Datei)

Von der Download-Seite der Apache POI Site zur Zip-Datei (poi-bin-3.17 zum Zeitpunkt des Schreibens dieses Artikels) -20170915.zip) kann heruntergeladen werden.

2. Entpacken Sie die Zip-Datei

Entpacken Sie die Zip-Datei an einer beliebigen Stelle auf Ihrem lokalen PC. Ich denke, es wird wie folgt dekomprimiert.

poi-3.17
  ├─ docs
│ └ Viele HTML-Dateien
  │
  ├─ lib
  │   ├─ commons-codec-1.10.jar
  │   ├─ commons-collections4-4.1.jar
  │   ├─ commons-logging-1.2.jar
  │   ├─ junit-4.12.jar
  │   └─ log4j-1.2.17.jar
  │
  ├─ ooxml-lib
  │   ├─ curvesapi-1.04.jar
  │   └─ xmlbeans-2.6.0.jar
  │
  ├─ LICENSE
  ├─ NOTICE
  ├─ poi-3.17.jar
  ├─ poi-examples-3.17.jar
  ├─ poi-excelant-3.17.jar
  ├─ poi-ooxml-3.17.jar
  ├─ poi-ooxml-schemas-3.17.jar
  └─ poi-scratchpad-3.17.jar

3. Erstellen Sie eine Benutzerbibliothek

A) Wählen Sie in den Eclipse-Einstellungen [Java]> [Build Path]> [User Library]> [New ...].

B) Geben Sie einen beliebigen Namen ein, z. B. "poi-3.17", und drücken Sie OK.

C) Wählen Sie die erstellte Benutzerbibliothek aus und klicken Sie auf [Externe JAR hinzufügen ...].

D) Geben Sie die JAR-Datei an, die in der Dekomprimierung von 2. oben enthalten ist. Geben Sie außerdem an, was im Ordner lib und im Ordner ooxml-lib enthalten ist.

Es enthält JAR-Dateien und Beispieldateien für den Betrieb von Word und PowerPoint sowie Excel. Wenn Sie nur Excel-Dateien bedienen, benötigen Sie diese JAR-Dateien nicht, aber fügen Sie sie alle ein. Sollte es nicht gut sein?

E) Klicken Sie auf [Übernehmen und schließen].

4. Fügen Sie die Benutzerbibliothek zum Erstellungspfad des Projekts hinzu

A) Wählen Sie das Projekt aus und wählen Sie im Kontextmenü Build Path> Add Library ....

B) Wählen Sie Benutzerbibliothek als Bibliothekstyp und geben Sie die zuvor erstellte Benutzerbibliothek als Ziel an.

das ist alles.

Recommended Posts

So erhalten Sie eine Liste mit Excel-Blattnamen in Java (POI vs SAX)
So benennen Sie Variablen in Java
So erhalten Sie den Namen einer Klasse / Methode, die in Java ausgeführt wird
So erhalten Sie das Datum mit Java
So erhalten Sie eine Klasse von Element in Java
So erhalten Sie den Klassennamen des Arguments von LoggerFactory.getLogger, wenn Sie SLF4J in Java verwenden
Wie man JAVA in 7 Tagen lernt
So erhalten Sie Parameter in Spark
[Java] Verwendung von List [ArrayList]
Wie verwende ich Klassen in Java?
So verketten Sie Zeichenfolgen mit Java
So ermitteln Sie die Länge einer Audiodatei mit Java
So implementieren Sie die Datumsberechnung in Java
So implementieren Sie den Kalman-Filter mit Java
Mehrsprachige Unterstützung für Java Verwendung des Gebietsschemas
So ändern Sie den App-Namen in Rails
So führen Sie eine Basiskonvertierung in Java durch
Ändern Sie die Liste <Optional <T >> in Java in Optional <Liste <T >>
[Java] So erhalten Sie das aktuelle Verzeichnis
So erzwingen Sie Codierungskonventionen in Java
Einbetten von Janus Graph in Java
[Architekturdesign] Wie führe ich SQL in einer Java-Anwendung aus? 2WaySql vs ORM
[Java] [ibatis] So erhalten Sie 1-zu-N-Beziehungsdatensätze mit List <Map <>>
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
So erstellen Sie Ihre eigene Anmerkung in Java und erhalten den Wert
graphql-ruby: So erhalten Sie den Namen der Abfrage oder Mutation im Controller Hinweis
So zeigen Sie eine Webseite in Java an
Wenn ich in Apache POI 3.15 das Ergebnis einer Formel erhalte, erhalte ich eine FormulaParseException (die Formel bezieht sich auf "Zellen mit Blattnamen, die" ・ "enthalten).
So verbergen Sie Nullfelder als Antwort in Java
Bibliothek "OSHI" zum Erfassen von Systeminformationen mit Java
[Java] So erhalten Sie Zufallszahlen ohne bestimmte Zahlen
Wie man Java SE8 Gold bekommt und studiert
So lösen Sie Ausdrucksprobleme in Java
[Java] So erhalten Sie die endgültige umgeleitete URL
Wie schreibe ich Java String # getBytes in Kotlin?
[Java] So erhalten Sie den Schlüssel und den Wert, die in Map gespeichert sind, durch iterative Verarbeitung
Speichern von Dateien mit der angegebenen Erweiterung unter dem in Java angegebenen Verzeichnis in der Liste
[Java] So erhalten Sie die URL der Übergangsquelle
Aufrufen von Funktionen in großen Mengen mit Java Reflection
So erstellen Sie eine Java-Umgebung in nur 3 Sekunden
[Java] So lassen Sie den privaten Konstruktor in Lombok weg
Beispielcode zum Konvertieren von List in List <String> in Java Stream
Wie kann ich IBM Mainframe-Dateien in Java eingeben / ausgeben?
java: Wie schreibe ich eine generische Typliste? [Hinweis]
[Java] So extrahieren Sie den Dateinamen aus dem Pfad
So erhalten Sie Informationen zu zugeordneten Tabellen in vielen-zu-vielen-Tabellen
Benennen Sie Java Excel Sheet um und legen Sie die Registerkartenfarben fest
[Java] So erhalten Sie den Maximalwert von HashMap
Quelle zum Abrufen der Umleitungsquell-URL in Java
So zeigen Sie eine Browser-Vorschau mit VS-Code an
Stand April 2018 So installieren Sie Java 8 auf einem Mac
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
So erstellen Sie eine Java-Entwicklungsumgebung mit VS Code
So verwalten Sie Java EE-Projekte in Eclipse