Apache POI er et populært open source-bibliotek, der bruges til at læse, skrive og manipulere MS Office- og Open Office-filer ved hjælp af Java-kode. Biblioteket er et af de mange open source-produkter, der vedligeholdes af Apache Software Foundation (ASF) bidrog til Java-fællesskabet. Biblioteket indeholder klasser og metoder til at afkode filformater baseret på Open Office XML-standarder og Microsoft OLE2. Selvom biblioteket er i stand til at manipulere Word-, Excel-regnearks- og PowerPoint-filer, fokuserer denne artikel hovedsageligt på regnearksdokumenter, kun for at gøre det kort.
Lær JAVA og start din gratis prøveperiode i dag!
Apache POI-biblioteket
Spændende nok, i navnet Apache POI, står POI for "Dårlig obfuscation Implementation", og målet med biblioteket er at levere Java API'er til at manipulere forskellige filformater baseret på Office Open XML-standarderne (OOXML) og Microsofts OLE 2 Compound Document-format (OLE2). Kort sagt gør dette dig i stand til at læse og skrive MS Excel-, MS Word- og MS PowerPoint-filer ved at bruge Java-kode. De fleste Microsoft Office-filer – såsom XLS, DOC, PPT og MFC serialisering API-baserede filformater – er baseret på OLE2-standarden. OLE er grundlæggende en proprietær teknik udviklet af Microsoft og leverer formatet til at linke objekter og indlejre objekter i containerdokumenter. Det første format kaldes OLE1.0-format, hvor det sammenkædede objekt og de indlejrede objektdata er lagt ud som en sekvens af bytes i containerdokumentet. Den anden version, OLE2.0-formatet, udnytter OLE Compound File Technology (MS-CFB), hvor det sammenkædede objekt eller indlejrede objektdata er indeholdt i dette lager i form af OLE Compound File Stream-objekter. Se OLE1.0- og OLE2.0-formater for flere detaljer om dette. Apache POI-biblioteket leverer biblioteks-API'er til OLE2-filsystemet kaldet POIFS og OLE2-dokumentegenskaber kaldet HPSF.
Apache POI-komponenter
Apache POI-biblioteket giver klasser og metoder til at arbejde med OLE2-sammensatte dokumenter fra MS Office. Her er en kort oversigt over de mest brugte:
- POIFS for OLE2-dokumenter:POIFS står for Poor Obfuscation Implementation File System . Dette er det grundlæggende POI-element, der er implementeret i biblioteket til at portere OLE2 Compound Document. Det understøtter læse- og skrivefunktionalitet til det ikke-XML-binære Microsoft Office-format. Alle API'er i POI-biblioteket er bygget på dette.
- HSSF og XSSF:HSSF står for Horrible Spread Sheet Format . Det er en Java-implementeringsport til Excel 97-filformatet eller til .xls-filer. XSSF står for XML Spread Sheet Format og det er en port til OOXML-filformatet eller .xlsx-filformatet.
- HWPF og XWPF:HWPF står for Horrible Word Processor Format . Det er en begrænset skrivebeskyttet port til det ældre Word 6- eller Word 95-filformat. XWPF står for XML Word Processor Format . Det er en Java-implementeringsport til Word 2007 .docx-filformatet. Begge implementeringer understøtter begrænset funktionalitet.
- HSLF og XSLF:HSLF står for Horrible Slide Layout Format . XSLF står for XML Slide Layout Format . Begge disse giver mulighed for at læse, skrive, oprette og ændre PowerPoint-præsentationer, hvorimod HSLF understøtter PowerPoint 97-formatet, og XSLF understøtter senere versioner.
- HPSF :HPSF står for Horrible Property Set Format . Det bruges især til at arbejde med dokumentegenskaber såsom indstilling af titel, kategori, forfatter, dato for ændring og så videre for et dokument
- HDGF og XDGF:HDGF står for Horrible Diagram Format . Denne komponent indeholder klasser til at arbejde med Visio binære filformat. Det giver lav-niveau, skrivebeskyttede API'er for at få adgang til Visio-dokumenter og VSD-filer. XDGF står for XML Diagram Format . Det er til Visio XML-filformatet eller VSDX-filer.
- HPBF :HPBF står for Horrible Publisher Format . Det er en begrænset Java-port til at arbejde med MS Publisher-filformatet.
Akronymerne lyder humoristiske, fordi disse filsystemer skulle være lukket, og Microsoft gjorde deres bedste for at sløre koden, så de ikke kun er svære at forstå, men også svære at omdanne. Men udviklerne hos Apache hackede det med lethed og reverse-manipulerede det med succes. Måske, som et tegn på glæde eller fuldstændig fordømmelse af det lukkede system, kaldte de dem spøgefuldt som sådan.
Arbejde med HSSF- og XSSF-filer
HSSF- og XSSF-komponenterne i Apache-biblioteket giver tre modeller til at få adgang til et regnearksdokument i henhold til HSSF- og XSSF-dokumentationen. De er:
- Lavniveaustrukturer til særlige behov
- Hændelsesmodel-API'erne til skrivebeskyttet adgang til Excel-dokumenter
- Brugermodel-API'erne til oprettelse, læsning og ændring af Excel-filer
De begrænsede hændelsesmodel-API'er kan kun bruges til at læse regnearksdata. Disse API'er er placeret i org.apache.poi.hssf.eventusermodel pakke og org.apache.poi.xssf.eventusermodel pakke, hvor den første bruges til at læse data fra .xls filformat, og det andet bruges til at læse data fra .xlsx filformat.
Brugermodellen er meget mere fleksibel og nemmere at bruge; den kan læse, skrive, oprette og ændre et Excel-regnearksdokument. Men den har et meget højere hukommelsesfodaftryk end begivenhedsmodellen på lavt niveau.
Også adgang til og manipulation af det nyere OOXML-baserede filformat med XSSF har et meget højere hukommelsesfodaftryk end de gamle HSSF-understøttede binære filer.
Fra POI 3.5 og fremefter er HSSF- og XSSF-modellen blevet slået ind i SS-modellen, snarere tilpasset til at fungere for begge modeller. Det er mere en tweak af navn end en reel ændring. På en måde kan vi sige, at SS=HSSF+XSSF.
Migrering af databasetabeldata til et Excel-regneark
Her opretter vi et simpelt hjælpeprogram til at migrere nogle databasedata til et Excel-ark. Dette kan også justeres til at fungere med andre måder, såsom migrering af Excel-data til en databasetabel. Dette efterlades som en øvelse for læseren. Programmet er enkelt og selvforklarende. Besøg Apache POI-dokumentation for detaljerede oplysninger om klasser eller metoder. For at prøve følgende eksempel er det, vi har brugt, som følger:
- JDK 8
- MS Excel 2007
- Intellij IDEA IDE
- Apache POI 3.17
- Apache Derby 10.14
Besøg de relevante dokumenter og hjælpefiler til opsætning af projektet. Her er indholdet til Maven pom.xml-filen, vi har brugt.
<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>
Fortegnelse 1: pom.xml
Der oprettes en databasetabel med nogle dummy-poster, før hjælpeprogrammet køres. Her er koden for den fil.
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(); } }
Fortegnelse 2: DummyDatabase.java.
Dette er hjælpeprogrammet, vi taler om. Koden blev skrevet i stor hast og strukturen ikke særlig elegant. Det virker dog. Omstrukturer eller tweak det, som du finder det passende.
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()); } }
Fortegnelse 3: SSFile.java
Dette er kontrolpanelet, hvorfra hjælpeprogrammet startes.
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")); } }
Fortegnelse 4 :App.java
Før du kører...
Sørg for, at test1.xls eller test1.xlsx filer findes ikke i d://temp bibliotek før programmet køres, fordi programmet hverken overskriver eller kontrollerer filen med samme navn i den mappe, hvor filen skal oprettes. Sørg for dette hver gang programmet køres; ellers giver koden en grim fejlmeddelelse. Du kan dog justere koden for at sætte en vis kontrol.
Konklusion
Der er et andet alternativ til at arbejde med regneark, som Apache POI-dokumentationen foreslår via Cocoon serializer, selvom den stadig bruger HSSF indirekte. Cocoon kan serialisere enhver XML-datakilde ved at anvende typografiarket og udpege serializeren. HSSF- og XSSF-modellen er ret kraftfuld og giver en række klasser og metoder til at håndtere forskellige aspekter af et Excel-dokument. Denne artikel forsøgte at give et indblik i, hvad vi kan gøre med Apache POI. Vi skal ofte skrive et hjælpeprogram for at bygge bro mellem et åbent og lukket system. Apache POI kan helt sikkert tjene vores formål som en af sin slags.
Referencer
- Apache POI – Java API til Microsoft Documents
- POI-HSSF og POI-XSSF – Java API for at få adgang til filer i Microsoft Excel-format