sql >> Database >  >> RDS >> Database

Een Excel-document maken vanuit een Java-programma met behulp van Apache POI

De Apache POI is een populaire open source-bibliotheek die wordt gebruikt voor het lezen, schrijven en manipuleren van MS Office- en Open Office-bestanden met behulp van Java-code. De bibliotheek is een van de vele open source-producten die worden onderhouden door Apache Software Foundation (ASF) heeft bijgedragen aan de Java-gemeenschap. De bibliotheek bevat klassen en methoden om bestandsindelingen te decoderen op basis van Open Office XML-standaarden en Microsoft OLE2. Hoewel de bibliotheek in staat is om Word-, Excel-spreadsheet- en PowerPoint-bestanden te manipuleren, richt dit artikel zich voornamelijk op spreadsheetdocumenten, alleen om het kort te houden.

Leer JAVA en start vandaag nog uw gratis proefperiode!

De Apache POI-bibliotheek

Intrigerend genoeg staat de POI in de naam Apache POI voor "Poor Obfuscation Implementation" en het doel van de bibliotheek is om Java API's te bieden voor het manipuleren van verschillende bestandsindelingen op basis van de Office Open XML-standaarden (OOXML) en het OLE 2 Compound Document-formaat van Microsoft (OLE2). Kortom, hierdoor kan men MS Excel-, MS Word- en MS PowerPoint-bestanden lezen en schrijven met behulp van Java-code. De meeste Microsoft Office-bestanden, zoals XLS-, DOC-, PPT- en MFC-serialisatie-API-gebaseerde bestandsindelingen, zijn gebaseerd op de OLE2-standaard. De OLE is in feite een gepatenteerde techniek ontwikkeld door Microsoft en biedt de indeling voor het koppelen van objecten en het insluiten van objecten in containerdocumenten. Het eerste formaat wordt het OLE1.0-formaat genoemd, waarbij het gekoppelde object en de ingesloten objectgegevens zijn ingedeeld als een reeks bytes in het containerdocument. De tweede versie, het OLE2.0-formaat, maakt gebruik van OLE Compound File Technology (MS-CFB) waarbij het gekoppelde object of de ingebedde objectgegevens in deze opslag zijn opgeslagen in de vorm van OLE Compound File Stream-objecten. Raadpleeg de OLE1.0- en OLE2.0-indelingen voor meer informatie hierover. De Apache POI-bibliotheek biedt bibliotheek-API's voor het OLE2-bestandssysteem genaamd POIFS en OLE2 Document Properties genaamd HPSF.

Apache POI-componenten

De Apache POI-bibliotheek biedt klassen en methoden om te werken met OLE2 samengestelde documenten van MS Office. Hier is een kort overzicht van de meest gebruikte:

  • POIFS voor OLE2-documenten:de POIFS staat voor Poor Obfuscation Implementation File System . Dit is het basis POI-element dat in de bibliotheek is geïmplementeerd om OLE2 Samengesteld document te porten. Het ondersteunt lees- en schrijffunctionaliteit voor het niet-XML binaire Microsoft Office-formaat. Alle API's van de POI-bibliotheek zijn hierop gebouwd.
  • HSSF en XSSF:de HSSF staat voor Horrible Spread Sheet Format . Het is een Java-implementatiepoort voor het Excel 97-bestandsformaat of voor .xls-bestanden. XSSF staat voor XML Spread Sheet Format en het is een poort voor het OOXML-bestandsformaat of .xlsx-bestandsformaat.
  • HWPF en XWPF:de HWPF staat voor Horrible Word Processor Format . Het is een beperkte alleen-lezen-poort voor het oudere Word 6- of Word 95-bestandsformaat. De XWPF staat voor XML Word Processor Format . Het is een Java-implementatiepoort voor het Word 2007 .docx-bestandsformaat. Beide implementaties ondersteunen beperkte functionaliteit.
  • HSLF en XSLF:de HSLF staat voor Horrible Slide Layout Format . De XSLF staat voor XML Slide Layout Format . Beide bieden de mogelijkheid om PowerPoint-presentaties te lezen, schrijven, maken en wijzigen, terwijl HSLF het PowerPoint 97-formaat ondersteunt en XSLF latere versies ondersteunt.
  • HPSF :De HPSF staat voor Horrible Property Set Format . Het wordt met name gebruikt om met documenteigenschappen te werken, zoals het instellen van de titel, categorie, auteur, wijzigingsdatum enzovoort van een document
  • HDGF en XDGF:de HDGF staat voor Horrible Diagram Format . Deze component bevat klassen om te werken met de binaire bestandsindeling van Visio. Het biedt low-level, alleen-lezen API's voor toegang tot Visio-documenten en VSD-bestanden. De XDGF staat voor XML Diagram Format . Het is voor de Visio XML-bestandsindeling of VSDX-bestanden.
  • HPBF :De HPBF staat voor Horrible Publisher Format . Het is een beperkte Java-poort om met het MS Publisher-bestandsformaat te werken.

De acroniemen klinken grappig omdat deze bestandssystemen gesloten zouden zijn en Microsoft deed zijn best om de code te verdoezelen, zodat ze niet alleen moeilijk te begrijpen zijn, maar ook moeilijk te reverse-engineeren. Maar de ontwikkelaars van Apache hebben het met gemak gehackt en met succes reverse-engineered. Misschien, als blijk van blijdschap of totale veroordeling van het gesloten systeem, noemden ze ze schertsend als zodanig.

Werken met HSSF- en XSSF-bestanden

De HSSF- en XSSF-componenten van de Apache-bibliotheek bieden drie modellen voor toegang tot een spreadsheetdocument volgens de HSSF- en XSSF-documentatie. Dit zijn:

  • Lage structuren voor speciale behoeften
  • De eventmodel-API's voor alleen-lezen toegang tot Excel-documenten
  • De gebruikersmodel-API's voor het maken, lezen en wijzigen van Excel-bestanden

De beperkte eventmodel-API's mogen alleen worden gebruikt voor het lezen van spreadsheetgegevens. Deze API's bevinden zich in het org.apache.poi.hssf.eventusermodel pakket en org.apache.poi.xssf.eventusermodel pakket, waarbij de eerste wordt gebruikt om gegevens te lezen van de .xls bestandsformaat en de tweede wordt gebruikt om gegevens te lezen van de .xlsx bestandsformaat.

Het gebruikersmodel is veel flexibeler en gebruiksvriendelijker; het kan een Excel-spreadsheetdocument lezen, schrijven, maken en wijzigen. Maar het heeft een veel grotere geheugenvoetafdruk dan het low-level eventmodel.

Bovendien heeft het openen en manipuleren van het nieuwere op OOXML gebaseerde bestandsformaat met XSSF een veel grotere geheugenvoetafdruk dan de oude door HSSF ondersteunde binaire bestanden.

Vanaf POI 3.5 is het HSSF- en XSSF-model in het SS-model gestoken, eerder aangepast om voor beide modellen te werken. Het is meer een aanpassing van de naam dan een echte verandering. In zekere zin kunnen we zeggen dat SS=HSSF+XSSF.

Databasetabelgegevens migreren naar een Excel-spreadsheet

Hier zullen we een eenvoudig hulpprogramma maken om sommige databasegegevens naar een Excel-blad te migreren. Dit kan ook worden aangepast om met andere manieren te werken, zoals het migreren van Excel-gegevens naar een databasetabel. Dit wordt overgelaten als een oefening voor de lezer. Het programma is eenvoudig en spreekt voor zich. Bezoek de Apache POI-documentatie voor gedetailleerde informatie over klassen of methoden. Om het volgende voorbeeld te proberen, hebben we het volgende gebruikt:

  • JDK 8
  • MS Excel 2007
  • Intellij IDEA IDE
  • Apache POI 3.17
  • Apache Derby 10.14

Bezoek de juiste documenten en helpbestanden voor het opzetten van het project. Hier is de inhoud van het Maven pom.xml-bestand dat we hebben gebruikt.

<project 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.mano.examples</groupId>
   <artifactId>apache-poi-demo</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>apache-poi-demo</name>
   <url>http://maven.apache.org</url>

   <properties>
      <project.build.sourceEncoding>
         UTF-8
      </project.build.sourceEncoding>
   </properties>

   <build>
      <plugins>
         <plugin>
            <artifactId>
               maven-compiler-plugin
            </artifactId>
            <version>3.7.0</version>
            <configuration>
               <source>1.8</source>
               <target>1.8</target>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>3.8.1</version>
         <scope>test</scope>
      </dependency>

      <!-- https://mvnrepository.com/artifact
         /org.apache.maven.plugins/maven-compiler-plugin -->
      <dependency>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.7.0</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/
         org.apache.poi/poi -->
      <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>poi</artifactId>
         <version>3.17</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/
         org.apache.poi/poi-ooxml -->
      <dependency>
         <groupId>org.apache.poi</groupId>
         <artifactId>poi-ooxml</artifactId>
         <version>3.17</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/
         org.apache.derby/derby -->
      <dependency>
         <groupId>org.apache.derby</groupId>
         <artifactId>derby</artifactId>
         <version>10.14.1.0</version>
         <scope>test</scope>
      </dependency>

      <!-- https://mvnrepository.com/artifact/
         org.apache.derby/derbyclient -->
      <dependency>
         <groupId>org.apache.derby</groupId>
         <artifactId>derbyclient</artifactId>
         <version>10.14.1.0</version>
      </dependency>

   </dependencies>
</project>

Vermelding 1: pom.xml

Voordat het hulpprogramma wordt uitgevoerd, wordt een databasetabel gemaakt met enkele dummy-records. Hier is de code van dat bestand.

package com.mano.examples;

import java.sql.*;


public class DummyDatabase {

   public static void createDummyDatabase()
         throws SQLException {
      Connection con=DriverManager.getConnection
         ("jdbc:derby:D:/temp/dummy;create=true");
      Statement stmt=con.createStatement();
      stmt.executeUpdate("drop table semester2");
      stmt.executeUpdate("CREATE TABLE semester2(STUDENT_ID int,
         CARCH INT, DCE INT, WEBTECH INT, JAVA INT, SAD_MIS INT,
         PRIMARY KEY(STUDENT_ID))");

      // Insert 2 rows
      stmt.executeUpdate("insert into semester2
         values (23567932,56,78,97,58,85)");
      stmt.executeUpdate("insert into semester2
         values (47250001,96,34,75,68,12)");
      stmt.executeUpdate("insert into semester2
         values (99568955,45,68,69,78,29)");
      stmt.executeUpdate("insert into semester2
         values (89376473,75,23,56,89,47)");
      stmt.executeUpdate("insert into semester2
         values (29917740,85,78,55,15,48)");
      stmt.executeUpdate("insert into semester2
         values (85776649,23,56,78,25,69)");
      stmt.executeUpdate("insert into semester2
         values (38846455,68,95,78,53,48)");
      stmt.executeUpdate("insert into semester2
         values (40028826,63,56,48,59,75)");
      stmt.executeUpdate("insert into semester2
         values (83947759,85,54,69,36,89)");
      stmt.executeUpdate("insert into semester2
         values (92884775,78,59,25,48,69)");
      stmt.executeUpdate("insert into semester2
         values (24947389,12,10,14,54,68)");
      stmt.executeUpdate("insert into semester2
         values (77399465,44,33,26,88,77)");

      // Query
      ResultSet rs = stmt.executeQuery
      ("SELECT * FROM semester2");

      // Print out query result
      while (rs.next()) {
         System.out.printf
               ("%dt%dt%dt%dt%dt%dn",
            rs.getLong("STUDENT_ID"),
            rs.getInt("CARCH"),
            rs.getInt("DCE"),
            rs.getInt("WEBTECH"),
            rs.getInt("JAVA"),
            rs.getInt("SAD_MIS"));
      }
      stmt.close();
      con.close();
   }
}

Vermelding 2: DummyDatabase.java.

Dit is het hulpprogramma waar we het over hebben. De code werd in grote haast geschreven en de structuur was niet erg elegant. Het werkt echter wel. Herstructureer of pas het naar eigen inzicht aan.

package com.mano.examples;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.*;

public class SSFile {

   private static String[] header={"STUDENT_ID",
      "CARCH", "DCE", "WEBTECH", "JAVA",
      "SAD_MIS", "TOTAL", "AVERAGE"};

   public static void databaseToExcel(File file)
         throws IOException, SQLException {
      Workbook workbook = null;
      if (file.getName().endsWith(".xls"))
         workbook = new HSSFWorkbook();
      else if (file.getName().endsWith(".xlsx"))
         workbook = new XSSFWorkbook();
      else {
         System.out.println("Invalid filename!");
         return;
      }
      Sheet sheet = workbook.createSheet();
      Connection con = DriverManager.getConnection
         ("jdbc:derby:D:/temp/dummy;create=true");
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM semester2");



      Row rr = sheet.createRow(0);
      for(int i=0;i<header.length;i++){
         createHeaderCell(rr, (short) i, header[i]);
      }

      int i = 1;
      while (rs.next()) {
         rr = sheet.createRow(i++);
         for(int j=0;j<header.length-2;j++){
            createDataCell(rr, (short) j,
               rs.getLong(header[j]));
         }
      }
      rr = sheet.getRow(1);
      Cell total = rr.createCell(6);
      total.setCellType(CellType.FORMULA);
      total.setCellFormula("SUM(B2:F2)");
      Cell avg = rr.createCell(7);
      avg.setCellType(CellType.FORMULA);
      avg.setCellFormula("AVERAGE(B2:F2)");

      FileOutputStream outFile = new
         FileOutputStream(file);
      workbook.write(outFile);
      outFile.flush();
      outFile.close();
      stmt.close();
      con.close();
   }

   private static void createHeaderCell(Row row,
         short col, String cellValue) {
      Cell c = row.createCell(col);
      c.setCellValue(cellValue);
   }

   private static void createDataCell(Row row,
         short col, Number cellValue) {
      Cell c = row.createCell(col);
      c.setCellType(CellType.NUMERIC);
      c.setCellValue(cellValue.doubleValue());
   }
}

Vermelding 3: SSFile.java

Dit is het configuratiescherm van waaruit het hulpprogramma wordt opgeroepen.

package com.mano.examples;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;

public class App
{
   public static void main( String[] args )
         throws IOException,SQLException{
      // DummyDatabase.createDummyDatabase();
      SSFile.databaseToExcel(new
         File("d://temp//test1.xls"));
   }
}

Vermelding 4 :App.java

Voordat je gaat rennen...

Zorg ervoor dat de test1.xls of test1.xlsx bestanden bestaan ​​niet in de d://temp directory voordat het programma wordt uitgevoerd, omdat het programma het bestand met dezelfde naam niet overschrijft of controleert in de directory waar het bestand zou moeten worden gemaakt. Zorg ervoor dat dit elke keer dat het programma wordt uitgevoerd; anders geeft de code een vervelende foutmelding. U kunt de code echter aanpassen om wat controle uit te oefenen.

Conclusie

Er is een ander alternatief voor het werken met spreadsheets, zoals de Apache POI-documentatie suggereert via de Cocoon-serializer, hoewel het nog steeds indirect HSSF gebruikt. Cocoon kan elke XML-gegevensbron serialiseren door de stylesheet toe te passen en de serializer aan te wijzen. Het HSSF- en XSSF-model is behoorlijk krachtig en biedt een aantal klassen en methoden om met verschillende aspecten van een Excel-document om te gaan. Dit artikel probeerde een glimp te geven van wat we kunnen doen met Apache POI. We moeten vaak een hulpprogramma schrijven om een ​​brug te slaan tussen een open en een gesloten systeem. Apache POI kan ons doel zeker dienen als uniek in zijn soort.

Referenties

  • Apache POI – de Java API voor Microsoft-documenten
  • POI-HSSF en POI-XSSF – Java API voor toegang tot bestanden in Microsoft Excel-indeling

  1. python-object opslaan in postgres-tabel met augurk

  2. Strings samenvoegen in SQLite

  3. Hoe te controleren welke sloten op een tafel worden vastgehouden?

  4. Hoe voeg ik meerdere rijen uit een array in met behulp van het CodeIgniter-framework?