O POI do Apache é uma biblioteca de código aberto popular usada para ler, escrever e manipular arquivos do MS Office e Open Office usando código Java. A biblioteca é um dos muitos produtos de código aberto mantidos pela Apache Software Foundation (ASF) contribuiu para a comunidade Java. A biblioteca contém classes e métodos para decodificar formatos de arquivo com base nos padrões Open Office XML e Microsoft OLE2. Embora a biblioteca seja capaz de manipular arquivos do Word, planilhas do Excel e PowerPoint, este artigo se concentra principalmente em documentos de planilhas, apenas para torná-lo breve.
Aprenda JAVA e comece sua avaliação gratuita hoje mesmo!
A Biblioteca Apache POI
Curiosamente, no nome Apache POI, o POI significa “Poor Obfuscation Implementation” e o objetivo da biblioteca é fornecer APIs Java para manipular vários formatos de arquivo com base nos padrões Office Open XML (OOXML) e no formato OLE 2 Compound Document da Microsoft. (OLE2). Em suma, isso permite ler e escrever arquivos MS Excel, MS Word e MS PowerPoint usando código Java. A maioria dos arquivos do Microsoft Office — como XLS, DOC, PPT e formatos de arquivo baseados em API de serialização MFC — são baseados no padrão OLE2. O OLE, basicamente, é uma técnica proprietária desenvolvida pela Microsoft e fornece o formato para vincular objetos e incorporar objetos em documentos de contêiner. O primeiro formato é chamado formato OLE1.0, onde o objeto vinculado e os dados do objeto incorporado são dispostos como uma sequência de bytes dentro do documento contêiner. A segunda versão, o formato OLE2.0, aproveita a OLE Compound File Technology (MS-CFB) onde o objeto vinculado ou os dados do objeto incorporado estão contidos nesse armazenamento na forma de objetos OLE Compound File Stream. Consulte os Formatos OLE1.0 e OLE2.0 para obter mais detalhes sobre isso. A biblioteca Apache POI fornece APIs de biblioteca para o sistema de arquivos OLE2 chamado POIFS e Propriedades do Documento OLE2 chamado HPSF.
Componentes do Apache POI
A biblioteca Apache POI fornece classes e métodos para trabalhar com documentos compostos OLE2 do MS Office. Aqui está uma breve visão geral dos mais comumente usados:
- POIFS para Documentos OLE2:POIFS significa Sistema de Arquivos de Implementação de Ofuscação Pobre . Este é o elemento POI básico implementado na biblioteca para portar o Documento Composto OLE2. Ele suporta a funcionalidade de leitura e gravação para o formato binário não XML do Microsoft Office. Todas as APIs da biblioteca POI são baseadas nisso.
- HSSF e XSSF:O HSSF significa Horrible Spread Sheet Format . É uma porta de implementação Java para o formato de arquivo Excel 97 ou para arquivos .xls. XSSF significa XML Spread Sheet Format e é uma porta para o formato de arquivo OOXML ou formato de arquivo .xlsx.
- HWPF e XWPF:O HWPF significa Horible Word Processor Format . É uma porta somente leitura limitada para o formato de arquivo Word 6 ou Word 95 mais antigo. O XWPF significa XML Word Processor Format . É uma porta de implementação Java para o formato de arquivo .docx do Word 2007. Ambas as implementações suportam funcionalidades limitadas.
- HSLF e XSLF:o HSLF significa Horible Slide Layout Format . O XSLF significa XML Slide Layout Format . Ambos fornecem capacidade de leitura, gravação, criação e modificação de apresentações do PowerPoint, enquanto o HSLF suporta o formato PowerPoint 97 e o XSLF suporta versões posteriores.
- HPSF :O HPSF significa Horrible Property Set Format . É particularmente usado para trabalhar com propriedades de documentos, como definir o título, categoria, autor, data de modificação e assim por diante de um documento
- HDGF e XDGF:HDGF significa Horrible Diagram Format . Este componente contém classes para trabalhar com o formato de arquivo binário do Visio. Ele fornece APIs somente leitura de baixo nível para acessar documentos do Visio e arquivos VSD. O XDGF significa XML Diagram Format . É para o formato de arquivo XML do Visio ou arquivos VSDX.
- HPBF :O HPBF significa Horrible Publisher Format . É uma porta Java limitada para trabalhar com o formato de arquivo MS Publisher.
As siglas soam engraçadas porque esses sistemas de arquivos deveriam ser fechados e a Microsoft fez o possível para ofuscar o código para que eles não fossem apenas difíceis de entender, mas também difíceis de fazer engenharia reversa. Mas, os desenvolvedores do Apache o hackearam com facilidade e fizeram engenharia reversa com sucesso. Talvez, como sinal de regozijo ou condenação total do sistema fechado, eles jocosamente os nomearam como tal.
Trabalhando com arquivos HSSF e XSSF
Os componentes HSSF e XSSF da biblioteca Apache fornecem três modelos de acesso a um documento de planilha conforme a Documentação HSSF e XSSF. Eles estão:
- Estruturas de baixo nível para necessidades especiais
- As APIs eventmodel para acesso somente leitura a documentos do Excel
- As APIs usermodel para criar, ler e modificar arquivos do Excel
As APIs de eventmodel limitadas podem ser usadas apenas para ler dados de planilhas. Essas APIs estão localizadas no org.apache.poi.hssf.eventusermodel pacote e org.apache.poi.xssf.eventusermodel pacote, onde o primeiro é usado para ler dados do .xls formato de arquivo e o segundo é usado para ler dados do .xlsx formato de arquivo.
O usermodel é muito mais flexível e fácil de usar; ele pode ler, escrever, criar e modificar um documento de planilha do Excel. Mas, ele tem uma pegada de memória muito maior do que o eventmodel de baixo nível.
Além disso, acessar e manipular o formato de arquivo baseado em OOXML mais recente com XSSF tem uma pegada de memória muito maior do que os antigos arquivos binários suportados por HSSF.
Do POI 3.5 em diante, o modelo HSSF e XSSF foi incorporado ao modelo SS, bastante ajustado para funcionar em ambos os modelos. É mais um ajuste de nome do que uma mudança real. De certa forma, podemos dizer que SS=HSSF+XSSF.
Migrando dados da tabela de banco de dados para uma planilha do Excel
Aqui, criaremos um programa utilitário simples para migrar alguns dados do banco de dados para uma planilha do Excel. Isso também pode ser ajustado para trabalhar com outras maneiras, como migrar dados do Excel para uma tabela de banco de dados. Fica como exercício para o leitor. O programa é simples e autoexplicativo. Visite a documentação do Apache POI para obter informações detalhadas sobre quaisquer classes ou métodos. Para tentar o exemplo a seguir, o que usamos é o seguinte:
- JDK 8
- MS Excel 2007
- IDE do Intelij IDEA
- Apache POI 3.17
- Apache Derby 10.14
Visite os documentos apropriados e arquivos de ajuda para configurar o projeto. Aqui está o conteúdo do arquivo maven pom.xml que usamos.
<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>
Listagem 1: pom.xml
Uma tabela de banco de dados é criada com alguns registros fictícios antes de executar o programa utilitário. Aqui está o código desse arquivo.
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(); } }
Lista 2: DummyDatabase.java.
Este é o programa utilitário de que estamos falando. O código foi escrito com muita pressa e a estrutura não muito elegante. No entanto, funciona. Reestruture ou ajuste-o como achar melhor.
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()); } }
Listagem 3: SSFile.java
Este é o painel de controle a partir do qual o programa utilitário é chamado.
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")); } }
Listagem 4 :App.java
Antes de correr…
Certifique-se de que o test1.xls ou teste1.xlsx os arquivos não existem no d://temp diretório antes de executar o programa porque o programa não substitui nem verifica o arquivo com o mesmo nome no diretório onde o arquivo deve ser criado. Certifique-se disso toda vez que o programa for executado; caso contrário, o código fornece uma mensagem de erro desagradável. No entanto, você pode ajustar o código para colocar alguma verificação.
Conclusão
Existe outra alternativa para trabalhar com planilhas, como sugere a documentação do Apache POI através do serializador Cocoon, embora ainda use HSSF indiretamente. Cocoon pode serializar qualquer fonte de dados XML aplicando a folha de estilo e designando o serializador. O modelo HSSF e XSSF é bastante poderoso e fornece várias classes e métodos para lidar com diferentes aspectos de um documento Excel. Este artigo tentou dar um vislumbre do que podemos fazer com o Apache POI. Muitas vezes precisamos escrever um programa utilitário para fazer a ponte entre um sistema aberto e fechado. O Apache POI pode definitivamente servir ao nosso propósito como um de seu tipo.
Referências
- Apache POI – a API Java para documentos da Microsoft
- POI-HSSF e POI-XSSF – API Java para acessar arquivos no formato Microsoft Excel