Wie man Excel-Dateien mit dem IntelliJ IDEA Plugin in Java liest

How to read Excel files in Java with real efficiency using SCell

Table of Contents

Es gibt viele Möglichkeiten, xlsx-Dateien zu bearbeiten. Im Grunde können Sie Java verwenden, um ohne Einschränkungen Excel-Dateien zu lesen. Mit den richtigen Java-Tools können Sie problemlos alles Mögliche erstellen. Um dies zu beweisen, erstellen wir ein Plugin für IntelliJ, welches xlsx-Dateien anzeigt.

Um diese Aufgabe zu erfüllen:

  1. Erstellen wir das „Grundgerüst“ des Plugins mit dem IntelliJ DevKit.
  2. Integrieren und verwenden wir ein geeignetes Java-Tool, um die Excel-Datei zu lesen und anzuzeigen.

 

Erstellen des Grundgerüsts für das IntelliJ-Plugin zum Lesen von Excel-
Dateien mit Java

Der erste Schritt besteht darin, ein neues Gradle-Projekt zu erstellen und die „IntelliJ DevKit“-Bibliothek zu aktivieren. Das „IntelliJ DevKit“ ermöglicht es Ihnen, die Standardfunktionen von IntelliJ zu erweitern und zu modifizieren. In unserem Fall haben wir uns entschieden, die erstellte Excel-/xlsx-Datei im „Tool-Fenster“ anzuzeigen, indem wir sie im Projektbaum doppelklicken.

Using Java to read Excel files - done the right way

Verwendung von Java zum Lesen von Excel-Dateien – auf die richtige Weise

 

Um einen Doppelklick zu verarbeiten, erstellen wir die IntelliJ-Klasse „AnAction“ und binden die xlsx-Dateierweiterung daran.

public class FilePopupAction extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        final Project project = e.getData(CommonDataKeys.PROJECT);
        final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if (project == null || virtualFile == null) {
            return;
        }
 
        SCellService scellService = project.getService(SCellService.class);
        scellService.load(virtualFile);
    }
 
    @Override
    public void update(@NotNull AnActionEvent e) {
        e.getPresentation().setEnabledAndVisible(available(e));
    }
 
    private static boolean available(AnActionEvent e) {
        VirtualFile data = e.getData(CommonDataKeys.VIRTUAL_FILE);
        if (data == null) {
            return false;
        }
        String extension = data.getExtension();
        return Arrays.asList(XlsxFileType.SUPPORTED_EXTENSIONS).contains(extension);
    }
}

Diese Klasse stellt Ihnen die Methode „actionPerformed“ zur Verfügung, die aufgerufen wird, wenn eine der IntelliJ-Aktionen ausgelöst wird. Um den Ort festzulegen, an dem Sie diese Methode aufrufen möchten, modifizieren Sie die Datei „yourProject\src\main\resources\META-INF\plugin.xml“:

<idea-plugin>
    <depends>com.intellij.modules.platform</depends>
    <depends>com.intellij.javafx</depends>
    <depends>com.intellij.java</depends>
 
    <extensions defaultExtensionNs="com.intellij">
       <projectService serviceImplementation="com.intechcore.scell.ideaplugin.platform.SCellService"/>
        <fileType
                name="Spreadsheet file"
                implementationClass="com.intechcore.scell.ideaplugin.platform.XlsxFileType"
                fieldName="INSTANCE"
                extensions="xlsx"/>
 
     <toolWindow id="XLSXReader" anchor="bottom" icon="/icons/scellIcon16x16.svg"                   factoryClass="com.intechcore.scell.ideaplugin.toolwindow.SpreadsheetToolWindowFactory"/>
    </extensions>
 
    <actions>
        <action id="XLSXReader" class="com.intechcore.scell.ideaplugin.FilePopupAction" text="Open with XLSXReader"
                description="The tool you can read the xlsx files in IDEA.">
            <add-to-group group-id="ProjectViewPopupMenu" anchor="first"/>
        </action>
    </actions>
</idea-plugin>

Mit dem folgenden Abschnitt abonniert man die bereitgestellte Klasse „FilePopupAction“ für einen Doppelklick auf eine beliebige Datei im Projektbaum und erstellt die neue Projektansicht-Popup-Option durch Klicken auf die rechte Maustaste:

<action id="XLSXReader" class="com.intechcore.scell.ideaplugin.FilePopupAction" text="Open with XLSXReader" 
                description="The tool you can read the xlsx files in IDEA."> 
            <add-to-group group-id="ProjectViewPopupMenu" anchor="first"/> 
        </action>

 

Konzentrieren wir uns nun auf die „update“-Methode.
Unsere Aktion sollte nur ausgelöst werden, wenn auf die xlsx-Datei geklickt wird. Dies kann durch Implementierung der „update“-Methode erreicht werden. Der Inhalt dieser Methode überprüft, ob die Datei die xlsx-Erweiterung hat. Abhängig vom Ergebnis wird IntelliJ die „actionPerformed“-Methode aufrufen, welche die erhaltene Datei an unsere Serviceklasse weitergibt und sie ausführt.
Die Klasse „XlsxFileType“ beschreibt die gewünschte Datei:

public class XlsxFileType implements INativeFileType {
    public static final INativeFileType INSTANCE = new XlsxFileType();
    public static final Icon SCELL_FILE_ICON = IconLoader.getIcon("/icons/scellIcon16x16.svg", XlsxFileType.class);
    public static final String[] SUPPORTED_EXTENSIONS = new String[] { "xlsx" };
 
    @Override
    public boolean openFileInAssociatedApplication(Project project, @NotNull VirtualFile file) {
        IdeFrame lastFocusedFrame = IdeFocusManager.getGlobalInstance().getLastFocusedFrame();
        if (lastFocusedFrame == null) {
            return false;
        }
 
        SCellService scellService = project.getService(SCellService.class);
        scellService.load(file);
        return false;
    }
 
    @Override
    public boolean useNativeIcon() {
        return false;
    }
 
    @Override
    public @NonNls @NotNull String getName() {
        return "Spreadsheet file";
    }
 
    @Override
    public @NlsContexts.Label @NotNull String getDescription() {
        return "Excel";
    }
 
    @Override
    public @NlsSafe @NotNull String getDefaultExtension() {
        return "xlsx";
    }
 
    @Override
    public Icon getIcon() {
        return SCELL_FILE_ICON;
    }
 
    @Override
    public boolean isBinary() {
        return true;
    }
}

Um diesen Dateityp für unser Plugin zu reservieren, müssen wir Folgendes zur plugin.xml hinzufügen:

<extensions defaultExtensionNs="com.intellij">
    <fileType
            name="Spreadsheet file"
            implementationClass="com.intechcore.scell.ideaplugin.platform.XlsxFileType"
            fieldName="INSTANCE"
            extensions="xlsx"/>
 
</extensions>

Es ist auch praktisch, ein Startfenster in der Symbolleiste zu erstellen. Das Fenster wird Sie auffordern, eine Datei auszuwählen, falls keine Datei ausgewählt wurde, als das Fenster geöffnet wurde.

Using Java to create Excel files easily with SCell

Die folgende Klasse wird das tun, was wir brauchen:

public class SpreadsheetToolWindowFactory implements ToolWindowFactory, DumbAware {
    @Override
    public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
        if (ApplicationManager.getApplication().isUnitTestMode()) {
            return;
        }
 
        JBPanelWithEmptyText myMessagePanel = new JBPanelWithEmptyText().withEmptyText("Double click the xlsx-file inside the filetree to open it here");
        ContentFactory contentFactory = ContentFactory.getInstance();
        Content content = contentFactory.createContent(myMessagePanel, "Usage", false);
        toolWindow.getContentManager().addContent(content);
 
        SCellService scellService = project.getService(SCellService.class);
        scellService.initToolWindow((ToolWindowEx)toolWindow);
    }
}

Das IntelliJ-Interface „ToolWindowFactory“ bietet Zugriff auf das Symbolleistenfenster für weitere Modifikationen über die Methode „createToolWindowContent“. Um dieses Fenster anzuzeigen, müssen wir es den Erweiterungen in der plugin.xml hinzufügen:

<toolWindow id="XLSXReader" anchor="bottom" icon="/icons/scellIcon16x16.svg" factoryClass="com.intechcore.scell.ideaplugin.toolwindow.SpreadsheetToolWindowFactory"/>

Von diesem Punkt an können wir mit dem zweiten Schritt unseres Plans fortfahren.

 

Integration der Java-Bibliothek zum Lesen und Bearbeiten von Excel-Dateien und zur Anzeige der xlsx-Datei in IntelliJ IDEA

SCell

SCell ist eine Java-Bibliothek, die für unsere Aufgabe geeignet ist, Excel-Dateien zu lesen und zu bearbeiten. Sie wurde entwickelt, um Excel-Tabellenkalkulationen in andere Anwendungen einzubetten. Sie kann xlsx-Dateien öffnen, bearbeiten und sogar speichern. Was noch wichtiger ist, sie kann Tabellenkalkulationen für uns rendern.

Lassen Sie uns damit beginnen, die SCell-dependencies in unser Projekt hinzuzufügen.

Fügen Sie zunächst Folgendes in die Datei „yourProject/build.gradle“ ein:

repositories {
  jcenter()
  maven {
    url "${SCELL_REPO_URL}"
    credentials {
      username "${SCELL_REPO_USER}"
      password "${SCELL_REPO_PASS}"
    }
  }
}

dependencies {
  implementation "com.intechcore.scomponents.scell:api-interfaces-core:${SCELL_API_VERSION}"
  runtimeOnly "com.intechcore.scomponents.scell:api-impl-core:${SCELL_API_VERSION}"
  implementation "com.intechcore.scomponents.scell:api-interfaces-ui:${SCELL_API_VERSION}"
  runtimeOnly "com.intechcore.scomponents.scell:api-impl-ui:${SCELL_API_VERSION}"
}

Then create the “yourProject/graddle.properties” file:
SCELL_API_VERSION = 1.3.5-java11-DEMO
SCELL_REPO_URL = https://nexus.intechcore.online/repository/maven-scomponents-demo
SCELL_REPO_USER = demo
SCELL_REPO_PASS = demo

Nach diesem Schritt ist SCell einsatzbereit.

Wir registrieren dafür einen Dienst, der die xlsx-Datei verarbeitet, damit andere IDE- Komponenten darauf zugreifen können. Um diesen Dienst zu registrieren, erstellen Sie ihn und fügen die folgenden Änderungen zu den Erweiterungen der plugin.xml hinzu:

<projectService serviceImplementation="com.intechcore.scell.ideaplugin.platform.SCellService"/>

Jetzt können wir die xlsx-Datei mit Hilfe von SCell laden. Dazu haben wir die „load“-Methode zum Service hinzugefügt, die in unserer Aktion aufgerufen wird:

public class SCellService {
 
    public static final String TOOL_WINDOW_ID = "XLSXReader";
 
    private final Project project;
 
    private CompletableFuture<IScellApiResolver> scellResolverFuture;
 
    private ToolWindowEx toolWindow;
    private ScellControl scellControl;
 
    public SCellService(Project project) {
        this.project = project;
    }
 
    public void initToolWindow(ToolWindowEx toolWindow) {
        if (this.toolWindow != null) {
            return;
        }
        this.toolWindow = toolWindow;
        toolWindow.setAutoHide(false);
        toolWindow.setToHideOnEmptyContent(true);
    }
 
    public ToolWindowEx getOrInitToolWindow() {
        ToolWindowEx localToolWindow = this.toolWindow;
        if (localToolWindow == null) {
            localToolWindow = (ToolWindowEx)ToolWindowManager.getInstance(this.project).getToolWindow(TOOL_WINDOW_ID);
            this.initToolWindow(localToolWindow);
        }
        return localToolWindow;
    }
 
    public void load(VirtualFile virtualFile) {
        if (this.scellResolverFuture == null) {
            this.scellResolverFuture =
                    ScellApiEntryPoint.getApiResolverAsync(this.getClass().getClassLoader());
        }

        ToolWindowEx output = this.getOrInitToolWindow();

        if (this.scellControl == null) {
            this.scellControl = new ScellControl(this.scellResolverFuture);
        }
 
        output.getContentManager().removeAllContents(false);
        Content content = createContent(virtualFile.getName(), this.scellControl);
        output.getContentManager().addContent(content);
        this.scellControl.addNotify();
        this.scellControl.loadFile(virtualFile);
        output.show();
    }
 
    private static Content createContent(String fileName, JComponent component) {
        String tabName = ObjectUtils.notNull(fileName, "New File");
        return ContentFactory.getInstance().createContent(component, tabName, false);
    }
}

Das Erste, was Sie von SCell erhalten, ist der ScellApiEntryPoint, von dem aus Sie auf jede API-Komponente zugreifen können.
Wenn dies der erste Aufruf dieser Methode ist, wird die SCell-API initialisiert und an den ScellControl übergeben:

public class ScellControl extends JFXPanel implements Disposable {
    private final CompletableFuture<IScellApiResolver> scellResolverFuture;
    private CompletableFuture<IScellUiApi<Node>> uiApiFuture;
    private BorderPane root;
 
    public ScellControl(CompletableFuture<IScellApiResolver> scellResolverFuture) {
        this.scellResolverFuture = scellResolverFuture;
        this.setLayout(new BorderLayout());
        this.root = new BorderPane(new Label("Initializing ..."));
        Platform.runLater(() -> {
            Scene scene = new Scene(this.root);
            this.setScene(scene);
        });
    }
 
    public CompletableFuture<Void> loadFile(VirtualFile file) {
        if (this.uiApiFuture == null) {
            this.uiApiFuture = this.createScellUi(file);
            this.uiApiFuture.thenApplyAsync(IScellUiApi::getControl).whenCompleteAsync((node, ex) -> {
                if (ex != null) {
                    node = new Label("Failed to init: " + ex.getCause().getMessage());
                }
 
                this.root.setCenter(node);
            }, Platform::runLater);
 
            return this.uiApiFuture.thenAccept(unused -> { });
        }
 
        return this.uiApiFuture.thenAcceptAsync(uiApi -> {
            try {
                uiApi.getContentManager().load(file.getInputStream(), file.getPath());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }
 
    private CompletableFuture<IScellUiApi<Node>> createScellUi(VirtualFile file) {
        return this.scellResolverFuture.thenApplyAsync(resolver -> {
            IScellCoreApiFactory apiFactory = IScellCoreApiFactory.resolve(resolver);
 
            IScellUiApiBuilder<Node> uiBuilder = IScellUiFxApiBuilder.resolve(resolver);
 
            return uiBuilder.readOnly(true).create(CompletableFuture.supplyAsync(() -> {
                try {
                    return apiFactory.load(file.getInputStream(), () -> "", file.getPath());
                } catch (IOException e) {
                    return null;
                }
            }));
        });
    }
 
    @Override
    public void dispose() {
        Platform.runLater(() -> {
            if (this.root.getCenter() != null) {
                this.root.setCenter(null);
            }
        });
    }
}

Beachten Sie, dass SCell JavaFX verwendet, während IntelliJ Swing zum Rendern verwendet.

Swing kann die JavaFX-scene mit seiner eigenen Benutzeroberfläche hosten. Dazu vererben wir das „JFXPanel“ und übergeben die JavaFX-scene mit der Tabellenkalkulation an die
Methode „setScene“.

Die Methode „loadFile“ erstellt einen Knoten, der die geladene Tabellenkalkulation enthält, und übergibt ihn an die „Scene“.

Die Implementierung des „ISCellUiApiBuilder“-Interfaces erstellt den UI-Knoten und die Implementierung des „IScellCoreApiFactory“ lädt schließlich die Datei:

private CompletableFuture<IScellUiApi<Node>> createScellUi(VirtualFile file) {
       return this.scellResolverFuture.thenApplyAsync(resolver -> {
           IScellCoreApiFactory apiFactory = IScellCoreApiFactory.resolve(resolver);

           IScellUiApiBuilder<Node> uiBuilder = IScellUiFxApiBuilder.resolve(resolver);

           return uiBuilder.readOnly(true).create(CompletableFuture.supplyAsync(() -> {
               try {
                   return apiFactory.load(file.getInputStream(), () -> "", file.getPath());
               } catch (IOException e) {
                   return null;
               }
           }));
       });
   }

Die Methode „IScellCoreApiFactory.load(InputStream inputStream, Supplier&lt;String&gt;passwordSupplier, String title)“ kann passwortgeschützte Dateien laden. Da wir in unserem Beispiel eine normale xlsx-Datei laden, übergeben wir ein leeres Passwort (im Falle des Ladens von passwortgeschützten Dateien ist ein Menü zur Passwortabfrage erforderlich). Wir setzen die Tabellenkalkulation außerdem in den „read-ony“ (Nur-Lese-)Modus, indem wir den „ISCellUiApiBuilder“ verwenden, da unsere Aufgabe lediglich darin besteht, die xlsx-Datei zu lesen.

Diese beiden Instanzen können von der „CompletableFuture&lt;IScellApiResolver&gt; scellResolverFuture“ bezogen werden, die wir zuvor vom „ScellService“ übergeben hatten.

Nun lassen Sie uns zum „SCellService“ zurückkehren:

public void load(VirtualFile virtualFile) {
     if (this.scellResolverFuture == null) {
         this.scellResolverFuture =
                 ScellApiEntryPoint.getApiResolverAsync(this.getClass().getClassLoader());
     }
 
     ToolWindowEx output = this.getOrInitToolWindow();
 
     if (this.scellControl == null) {
         this.scellControl = new ScellControl(this.scellResolverFuture);
     }
 
     output.getContentManager().removeAllContents(false);
     Content content = createContent(virtualFile.getName(), this.scellControl);
     output.getContentManager().addContent(content);
     this.scellControl.addNotify();
     this.scellControl.loadFile(virtualFile);
     output.show();
 }

Please also check the short IntelliJ video: and subscribe to our YouTube channel. Nach der Initialisierung von „ScellControl“ erhalten wir das zuvor erstellte Tool-Fenster.

Dann erstellen wir den Inhalt für das Tool-Fenster aus „scellControl“ mithilfe der Methode „createContent“. Danach rufen wir „loadFile“ auf, das die Tabellenkalkulation für uns erstellt und diese im Tool-Fenster anzeigt, indem die Methode „output.show()“ aufgerufen wird.

Herzlichen Glückwunsch, die Arbeit ist erledigt, wir können die xlsx-Tabellenkalkulation in IntelliJ öffnen und anzeigen.

Bitte sehen Sie sich auch das kurze IntelliJ-Video an: Integration into IntelliJ IDEA – YouTube und abonnieren Sie unseren YouTube-Kanal.

 

Einladung: Erfahren Sie mehr über unsere Java-Komponenten zum Erstellen, Lesen und Bearbeiten von Excel-Dateien

Wenn Sie Java verwenden möchten, um Excel-Dateien zu lesen, und auch lernen möchten, wie Sie andere Funktionen von SCell nutzen können, wie das Bearbeiten oder Speichern von xlsx-Dateien oder wie Sie es in ein Maven-Projekt installieren, besuchen Sie unseren Artikel “Bearbeiten und Erstellen von Exceldateien in Java mit SCell” oder die offizielle Website oder die JavaDock Dokumentation (English only). Hier finden Sie mit Sicherheit hilfreiche Informationen.

Zögern Sie nicht, uns über unsere Kontaktseite zu erreichen.

Share:

More Posts

Nach oben scrollen