sql >> Base de Datos >  >> RDS >> Database

Cómo crear un documento de Excel desde un programa Java usando Apache POI

El punto de interés de Apache es una biblioteca de código abierto popular que se utiliza para leer, escribir y manipular archivos de MS Office y Open Office mediante el uso de código Java. La biblioteca es uno de los muchos productos de código abierto mantenidos por Apache Software Foundation (ASF) contribuyó a la comunidad de Java. La biblioteca contiene clases y métodos para decodificar formatos de archivo basados ​​en los estándares XML de Open Office y Microsoft OLE2. Aunque la biblioteca es capaz de manipular archivos de Word, hojas de cálculo de Excel y PowerPoint, este artículo se centra principalmente en documentos de hojas de cálculo, solo para hacerlo breve.

¡Aprende JAVA y comienza tu prueba gratuita hoy!

La biblioteca de puntos de interés de Apache

Curiosamente, en el nombre Apache POI, el POI significa "Implementación de ofuscación deficiente" y el objetivo de la biblioteca es proporcionar API de Java para manipular varios formatos de archivo basados ​​en los estándares Office Open XML (OOXML) y el formato de documento compuesto OLE 2 de Microsoft. (OLE2). En resumen, esto permite leer y escribir archivos de MS Excel, MS Word y MS PowerPoint mediante el uso de código Java. La mayoría de los archivos de Microsoft Office, como los formatos de archivo basados ​​en la API de serialización XLS, DOC, PPT y MFC, se basan en el estándar OLE2. El OLE, básicamente, es una técnica propietaria desarrollada por Microsoft, y proporciona el formato para vincular objetos e incrustar objetos dentro de documentos contenedores. El primer formato se denomina formato OLE1.0, donde el objeto vinculado y los datos del objeto incrustado se presentan como una secuencia de bytes dentro del documento contenedor. La segunda versión, el formato OLE2.0, aprovecha la tecnología de archivo compuesto OLE (MS-CFB) donde el objeto vinculado o los datos del objeto incrustado están contenidos en este almacenamiento en forma de objetos OLE Compound File Stream. Consulte Formatos OLE1.0 y OLE2.0 para obtener más detalles al respecto. La biblioteca Apache POI proporciona API de biblioteca para el sistema de archivos OLE2 llamado POIFS y OLE2 Document Properties llamado HPSF.

Componentes de puntos de interés de Apache

La biblioteca Apache POI proporciona clases y métodos para trabajar con documentos compuestos OLE2 de MS Office. Aquí hay una breve descripción de los más utilizados:

  • POIFS para documentos OLE2:POIFS significa Sistema de archivo de implementación de ofuscación pobre . Este es el elemento PDI básico implementado en la biblioteca para portar el documento compuesto OLE2. Admite la funcionalidad de lectura y escritura para el formato binario no XML de Microsoft Office. Todas las API de la biblioteca de puntos de interés se basan en esto.
  • HSSF y XSSF:HSSF significa Horrible Spread Sheet Format . Es un puerto de implementación de Java para el formato de archivo Excel 97 o para archivos .xls. XSSF significa Formato de hoja de cálculo XML y es un puerto para el formato de archivo OOXML o el formato de archivo .xlsx.
  • HWPF y XWPF:HWPF significa Horrible Word Processor Format . Es un puerto limitado de solo lectura para el formato de archivo anterior de Word 6 o Word 95. XWPF significa Formato de procesador de textos XML . Es un puerto de implementación de Java para el formato de archivo .docx de Word 2007. Ambas implementaciones admiten una funcionalidad limitada.
  • HSLF y XSLF:HSLF significa Horrible Slide Layout Format . XSLF significa Formato de diseño de diapositivas XML . Ambos brindan capacidad de lectura, escritura, creación y modificación de presentaciones de PowerPoint, mientras que HSLF admite el formato de PowerPoint 97 y XSLF admite versiones posteriores.
  • HPSF :HPSF significa Horrible Property Set Format . Se utiliza especialmente para trabajar con propiedades de documentos, como establecer el título, la categoría, el autor, la fecha de modificación, etc. de un documento
  • HDGF y XDGF:HDGF significa Horrible Diagram Format . Este componente contiene clases para trabajar con el formato de archivo binario de Visio. Proporciona API de solo lectura de bajo nivel para acceder a documentos de Visio y archivos VSD. XDGF significa Formato de diagrama XML . Es para el formato de archivo Visio XML o archivos VSDX.
  • HPBF :HPBF significa Horrible Publisher Format . Es un puerto Java limitado para trabajar con el formato de archivo de MS Publisher.

Los acrónimos suenan divertidos porque se suponía que estos sistemas de archivos estaban cerrados y Microsoft hizo todo lo posible para ofuscar el código para que no solo sean difíciles de entender sino también difíciles de aplicar ingeniería inversa. Pero, los desarrolladores de Apache lo hackearon con facilidad y lo aplicaron ingeniería inversa con éxito. Tal vez, como señal de regocijo o de total condenación del sistema cerrado, los nombraron jocosamente como tales.

Trabajar con archivos HSSF y XSSF

Los componentes HSSF y XSSF de la biblioteca Apache proporcionan tres modelos para acceder a un documento de hoja de cálculo según la documentación HSSF y XSSF. Ellos son:

  • Estructuras de bajo nivel para necesidades especiales
  • Las API de eventmodel para acceso de solo lectura a documentos de Excel
  • Las API de modelo de usuario para crear, leer y modificar archivos de Excel

Las API limitadas del modelo de eventos se pueden usar solo para leer datos de hojas de cálculo. Estas API se encuentran en el org.apache.poi.hssf.eventusermodel paquete y org.apache.poi.xssf.eventusermodel paquete, donde el primero se usa para leer datos del .xls formato de archivo y el segundo se utiliza para leer datos de .xlsx formato de archivo.

El modelo de usuario es mucho más flexible y fácil de usar; puede leer, escribir, crear y modificar un documento de hoja de cálculo de Excel. Pero tiene una huella de memoria mucho mayor que el modelo de eventos de bajo nivel.

Además, acceder y manipular el formato de archivo más nuevo basado en OOXML con XSSF tiene una huella de memoria mucho mayor que los archivos binarios compatibles con HSSF antiguos.

Desde POI 3.5 en adelante, el modelo HSSF y XSSF se ha incluido en el modelo SS, más bien ajustado para que funcione con ambos modelos. Es más un ajuste de nombre que un cambio real. En cierto modo, podemos decir que SS=HSSF+XSSF.

Migración de datos de tablas de bases de datos a una hoja de cálculo de Excel

Aquí, crearemos un programa de utilidad simple para migrar algunos datos de la base de datos a una hoja de Excel. Esto también se puede modificar para que funcione de otras formas, como migrar datos de Excel a una tabla de base de datos. Esto se deja como ejercicio para el lector. El programa es simple y se explica por sí mismo. Visite la documentación de Apache POI para obtener información detallada sobre cualquier clase o método. Para probar el siguiente ejemplo, lo que hemos utilizado es lo siguiente:

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

Visite los documentos apropiados y los archivos de ayuda para configurar el proyecto. Estos son los contenidos del archivo Maven pom.xml que hemos usado.

<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>

Listado 1: pom.xml

Se crea una tabla de base de datos con algunos registros ficticios antes de ejecutar el programa de utilidad. Aquí está el código de ese archivo.

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();
   }
}

Listado 2: Base de datos ficticia.java.

Este es el programa de utilidad del que estamos hablando. El código fue escrito con mucha prisa y la estructura no es muy elegante. Sin embargo, funciona. Reestructúrelo o ajústelo como mejor le parezca.

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());
   }
}

Listado 3: SSFfile.java

Este es el panel de control desde el que se invoca el programa de utilidades.

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"));
   }
}

Listado 4 :Aplicación.java

Antes de ejecutar...

Asegúrese de que test1.xls o prueba1.xlsx los archivos no existen en d://temp directorio antes de ejecutar el programa porque el programa no sobrescribe ni verifica el archivo con el mismo nombre en el directorio donde se supone que se debe crear el archivo. Asegúrese de esto cada vez que se ejecute el programa; de lo contrario, el código da un desagradable mensaje de error. Sin embargo, puede modificar el código para comprobarlo.

Conclusión

Hay otra alternativa para trabajar con hojas de cálculo, como sugiere la documentación de Apache POI a través del serializador Cocoon, aunque todavía usa HSSF indirectamente. Cocoon puede serializar cualquier fuente de datos XML aplicando la hoja de estilo y designando el serializador. El modelo HSSF y XSSF es bastante potente y proporciona una serie de clases y métodos para tratar diferentes aspectos de un documento de Excel. Este artículo trató de dar una idea de lo que podemos hacer con Apache POI. A menudo necesitamos escribir un programa de utilidad para unir un sistema abierto y cerrado. Apache POI definitivamente puede cumplir nuestro propósito como único en su clase.

Referencias

  • Apache POI:la API de Java para documentos de Microsoft
  • POI-HSSF y POI-XSSF:API de Java para acceder a archivos con formato de Microsoft Excel