O Apache POI é um framework para a plataforma Java que possibilita a leitura e a escrita de dados em um documento do Microsoft Office. Com ele, é possível ler e escrever dados em arquivos Excel, Word, PowerPoint e arquivos de e-mail do Outlook. Existem ainda projetos para adicionar suporte para arquivos do Visio. O POI é bastante utilizado em frameworks conhecidos, como o PrimeFaces e o RichFaces, que tem funcionalidades como exportar dados de um DataTable diretamente para um arquivo Excel.

O Apache POI é um projeto da controlado pela fundação Apache, e teve sua primeira versão disponibilizada em agosto de 2001, hoje o framework está na versão 3.10.1 que foi lançada em Julho de 2014. Já está disponível para download a versão 3.11.0 beta.

No exemplo desse artigo será criado um projeto simples que abre, escreve e edita um arquivo de notas de alunos de uma turma, com os campos Nome, RA, Nota1, Nota2, Média e Aprovado. A partir desses campos serão calculados diversos dados para essa turma, como a média de notas da turma inteira, o nome do aluno com a maior e menor nota, o número total de alunos e o número de alunos reprovados e aprovados na disciplina. O Excel pode calcular esses dados, mas uma possível utilização dessa aplicação seria jogar todos os dados da planilha diretamente em um banco de dados, ou mostrar os dados da planilha em uma página web. Por isso, a manipulação de arquivos Excel em aplicações Java é bastante utilizada.

Configurando o Projeto

Para a configuração do projeto, será utilizado o Maven Framework, que facilita a importação das dependências do framework POI. A Listagem 1 mostra o código do arquivo pom.xml do projeto: basta incluir a dependência do jar do framework. Nesse artigo usaremos a versão 3.10.1 que é a versão estável mais recente, que foi lançada em agosto de 2014.

Listagem 1. Configurando o POI com apoio do Maven.

  <project xmlns="http://maven.apache.org/POM/4.0.0" 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.devmedia</groupId>
         <artifactId>teste</artifactId>
         <version>0.0.1</version>
   
         <dependencies>
   
               <dependency>
                      <groupId>org.apache.poi</groupId>
                      <artifactId>poi</artifactId>
                      <version>3.10.1</version>
               </dependency>
   
   
         </dependencies>
  </project>

Abrindo o Arquivo

O primeiro passo agora é criar o código que abre o arquivo Excel. A Figura 1 mostra um exemplo do arquivo que será aberto. A primeira coluna do arquivo tem o nome de todos os alunos da disciplina, a segunda, o RA dos alunos, a terceira as notas da primeira prova, a quarta as notas da segunda prova e a quinta as medias dos alunos, que foi calculada pela formula (Nota1 + Nota2) / 2.

Arquivo
Excel utilizado no desenvolvimento da aplicação do exemplo

Figura 1. Arquivo Excel utilizado no desenvolvimento da aplicação do exemplo.

Para facilitar a manipulação dos dados do Excel, para cada linha do arquivo será criado um objeto do tipo Aluno, por isso foi criada a classe Aluno, que agrupa em seus atributos todos os dados que estarão no arquivo Excel. A Listagem 2 mostra o código dessa classe.

Listagem 2. Código da classe Aluno.

  package com.devmedia.teste;
   
  public class Aluno {
         
         private String nome;
         private String ra;
         private double nota1;
         private double nota2;
         private double media;
         private boolean aprovado;
         
         public Aluno() { }
         
         public Aluno(String nome, String ra, double nota1, double nota2,
                      double media, boolean aprovado) {
               super();
               this.nome = nome;
               this.ra = ra;
               this.nota1 = nota1;
               this.nota2 = nota2;
               this.media = media;
               this.aprovado = aprovado;
         }
   
   
   
         public String getNome() {
               return nome;
         }
         public void setNome(String nome) {
               this.nome = nome;
         }
         public String getRa() {
               return ra;
         }
         public void setRa(String ra) {
               this.ra = ra;
         }
         public double getNota1() {
               return nota1;
         }
         public void setNota1(double nota1) {
               this.nota1 = nota1;
         }
         public double getNota2() {
               return nota2;
         }
         public void setNota2(double nota2) {
               this.nota2 = nota2;
         }
         public double getMedia() {
               return media;
         }
         public void setMedia(double media) {
               this.media = media;
         }
   
         public boolean isAprovado() {
               return aprovado;
         }
   
         public void setAprovado(boolean aprovado) {
               this.aprovado = aprovado;
         }
  }

O framework Apache POI trabalha tanto com arquivos xls, com planilhas de versões antigas do Excel, como com arquivos xslx das versões mais recentes do Excel. O código para abrir um arquivo tanto de uma versão quanto da outra é bem parecido. O que muda é qual classe utilizar. Para versões antigas do Excel é utilizada a classe HSSFWorkbook e HSSFSheet, enquanto que para arquivos das novas versões do Excel são utilizadas as classes XSSFWorkbook e XSSFSheet, mas todo o restante do código é igual. No desenvolvimento desse artigo utilizaremos a classe HSSFWorkbook.

A sigla HSSF é uma piada da equipe de desenvolvimento do POI, por eles considerarem a formatação do arquivo do Excel muito ruim, a sigla HSSF significa Horrible SpreadShet Format. A sigla XSSF significa XML SpreadShet Format.

A Listagem 3 mostra o código para abrir o arquivo Excel. O código apesar de grande é bastante simples. O primeiro passo é abrir o arquivo, com a classe FileInputStream, passando o PATH completo do arquivo. Depois utilizando a classe HSSFWorkbook, o arquivo é validado se é ou não um arquivo Excel. A classe HSSFSheet abre uma planilha específica do arquivo. O POI pode abrir diversas planilhas que estejam dentro de um arquivo Excel, no exemplo, como existe apenas uma planilha, é aberta a planilha com índice 0.

Depois de aberto o arquivo, e com a planilha que será processado aberta, é necessário ler célula a célula do arquivo, para isso, é recuperado um iterator sobre todas as linhas do arquivo excel. Dentro de cada linha, é recuperado outro iterator, agora para iterar sobre as colunas de cada linha. Para ler as linhas do arquivo, é utilizada a classe Row, e para a célula especifica é utilizada a classe Cell.

A classe Cell possui diversos métodos para a manipulação dos dados do arquivo, por exemplo, é possível recuperar os dados que estão na célula com o tipo Java correto, por isso existem métodos para recuperar String, Números, Booleans entre outros. Também existem métodos para verificar qual o tipo de dado que está célula. Também é possível verificar se o valor da célula é calculado por uma formula.

Listagem 3. Código que abre e lê os dados do arquivo excel.

  package com.devmedia.teste;
   
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
   
  import org.apache.poi.hssf.usermodel.HSSFSheet;
  import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  import org.apache.poi.ss.usermodel.Cell;
  import org.apache.poi.ss.usermodel.Row;
   
  public class AbreExcel {
   
         private static final String fileName = "C:/teste/teste.xls";
   
         public static void main(String[] args) throws IOException {
   
               List<Aluno> listaAlunos = new ArrayList<Aluno>();
   
               try {
                      FileInputStream arquivo = new FileInputStream(new File(
                                    AbreExcel.fileName));
   
                      HSSFWorkbook workbook = new HSSFWorkbook(arquivo);
   
                      HSSFSheet sheetAlunos = workbook.getSheetAt(0);
   
                      Iterator<Row> rowIterator = sheetAlunos.iterator();
   
                      while (rowIterator.hasNext()) {
                             Row row = rowIterator.next();
                             Iterator<Cell> cellIterator = row.cellIterator();
   
                             Aluno aluno = new Aluno();
                             listaAlunos.add(aluno);
                             while (cellIterator.hasNext()) {
                                    Cell cell = cellIterator.next();
                                    switch (cell.getColumnIndex()) {
                                    case 0:
                                          aluno.setNome(cell.getStringCellValue());
                                          break;
                                    case 1:
                                          aluno.setRa(String.valueOf(cell.getNumericCellValue()));
                                          break;
                                    case 2:
                                          aluno.setNota1(cell.getNumericCellValue());
                                          break;
                                    case 3:
                                          aluno.setNota2(cell.getNumericCellValue());
                                          break;
                                    case 4:
                                           aluno.setMedia(cell.getNumericCellValue());
                                          break;
                                    case 5:
                                          aluno.setAprovado(cell.getBooleanCellValue());
                                          break;
                                    }
                             }
                      }
                      arquivo.close();
   
               } catch (FileNotFoundException e) {
                      e.printStackTrace();
                      System.out.println("Arquivo Excel não encontrado!");
               }
   
               if (listaAlunos.size() == 0) {
                      System.out.println("Nenhum aluno encontrado!");
               } else {
                      double soma = 0;
                      double maior = 0;
                      double menor = listaAlunos.get(0).getMedia();
                      int aprovados = 0;
                      int reprovados = 0;
                      for (Aluno aluno : listaAlunos) {
                             System.out.println("Aluno: " + aluno.getNome() + " Média: "
                                          + aluno.getMedia());
                             soma = soma + aluno.getMedia();
                             if (aluno.getMedia() > maior) {
                                    maior = aluno.getMedia();
                             }
                             if (aluno.getMedia() < menor) {
                                    menor = aluno.getMedia();
                             }
                             if (aluno.getMedia() >= 6) {
                                    aprovados++;
                             }
                             if (aluno.getMedia() < 6) {
                                    reprovados++;
                             }
                      }
                      double media = soma / listaAlunos.size();
                      System.out.println("A media de notas e: " + media);
                      System.out.println("A maior nota e: " + maior);
                      System.out.println("A menor nota e: " + menor);
                      System.out.println("O numero de alunos aprovados e: " + aprovados);
                      System.out
                                    .println("O numero de alunos reprovados e: " + reprovados);
                      System.out.println("Número total de alunos: " + listaAlunos.size());
               }
   
         }
  }

A Figura 2 mostra o console do Eclipse com a saída para a execução do código, no console são exibidos o nome de todos os alunos que estão no arquivo Excel e suas médias, também são exibidos os cálculos da turma, como a média geral dos alunos, o número de alunos reprovados e aprovados, e o número total de alunos.

Saída
do console do Eclipse com os cálculos efetuados

Figura 2. Saída do console do Eclipse com os cálculos efetuados.

Além de ler o arquivo Excel, para cada linha do arquivo, é criado um objeto do tipo Aluno, esse objeto é adicionado em um ArrayList de alunos, e os dados dessa lista são analisados. Alguns cálculos realizados foram o cálculo da média das notas de todos os alunos que estavam no arquivo Excel, a maior e menor nota que estavam no arquivo, e o número de alunos aprovados e reprovados.

O Apache POI também possibilita a criação e a escrita de dados em um arquivo Excel, o código para isso também é bastante simples, e também existe a mesma diferença para arquivos XLS e XSLX apontada anteriormente. A Listagem 4 apresenta o código para criar um arquivo Excel, caso ele ainda não exista, e escrever alguns dados de alunos no arquivo. Inicialmente são criados os dados de alguns alunos, e depois esses alunos são salvos no arquivo.

O primeiro passo, é criar o arquivo, com a classe HSSFWorkbook, e depois criar a planilha com a classe HSSFSheet, é possível nomear essa planilha, no exemplo, a planilha é chamada de Alunos. Depois de criada a planilha, é feito um for que itera sobre a lista onde os alunos estão cadastrados. A cada aluno que existe na lista, é criada uma linha no arquivo excel, e para cada célula dessa linha são adicionados os atributos do aluno, na mesma ordem do arquivo utilizado no exemplo para a leitura dos dados. Por fim, é dado um nome para o arquivo, utilizando a classe FIleOutputStream, e os dados do criados para a planilha são salvos no arquivo.

Listagem 4. Código que cria e salva os dados em um arquivo Excel.

  package com.devmedia.teste;
   
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.util.ArrayList;
  import java.util.List;
   
  import org.apache.poi.hssf.usermodel.HSSFSheet;
  import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  import org.apache.poi.ss.usermodel.Cell;
  import org.apache.poi.ss.usermodel.Row;
   
  public class CriaExcel {
         
         private static final String fileName = "C:/teste/novo.xls";
   
         public static void main(String[] args) throws IOException {
   
               HSSFWorkbook workbook = new HSSFWorkbook();
               HSSFSheet sheetAlunos = workbook.createSheet("Alunos");
                
               List<Aluno> listaAlunos = new ArrayList<Aluno>();
               listaAlunos.add(new Aluno("Eduardo", "9876525", 7, 8, 0, false));
               listaAlunos.add(new Aluno("Luiz", "1234466", 5, 8, 0, false));
               listaAlunos.add(new Aluno("Bruna", "6545657", 7, 6, 0, false));
               listaAlunos.add(new Aluno("Carlos", "3456558", 10, 3, 0, false));
               listaAlunos.add(new Aluno("Sonia", "6544546", 7, 8, 0, false));
               listaAlunos.add(new Aluno("Brianda", "3234535", 6, 5, 0, false));
               listaAlunos.add(new Aluno("Pedro", "4234524", 7, 5, 0, false));
               listaAlunos.add(new Aluno("Julio", "5434513", 7, 2, 0, false));
               listaAlunos.add(new Aluno("Henrique", "6543452", 7, 8, 0, false));
               listaAlunos.add(new Aluno("Fernando", "4345651", 5, 8, 0, false)); 
               listaAlunos.add(new Aluno("Vitor", "4332341", 7, 9, 0, false));                  
                
               int rownum = 0;
               for (Aluno aluno : listaAlunos) {
                   Row row = sheetAlunos.createRow(rownum++);
                   int cellnum = 0;
                   Cell cellNome = row.createCell(cellnum++);
                   cellNome.setCellValue(aluno.getNome());
                   Cell cellRa = row.createCell(cellnum++);
                   cellRa.setCellValue(aluno.getRa());
                   Cell cellNota1 = row.createCell(cellnum++);
                   cellNota1.setCellValue(aluno.getNota1());
                   Cell cellNota2 = row.createCell(cellnum++);
                   cellNota2.setCellValue(aluno.getNota2());
                   Cell cellMedia = row.createCell(cellnum++);
                   cellMedia.setCellValue((aluno.getNota1() + aluno.getNota2()) / 2);
                   Cell cellAprovado =row.createCell(cellnum++);
                   cellAprovado.setCellValue(cellMedia.getNumericCellValue() >= 6);
               }
                
               try {
                   FileOutputStream out = 
                           new FileOutputStream(new File(CriaExcel.fileName));
                   workbook.write(out);
                   out.close();
                   System.out.println("Arquivo Excel criado com sucesso!");
                    
               } catch (FileNotFoundException e) {
                   e.printStackTrace();
                      System.out.println("Arquivo não encontrado!");
               } catch (IOException e) {
                   e.printStackTrace();
                      System.out.println("Erro na edição do arquivo!");
               }
   
         }
   
  }

A Figura 3 mostra o arquivo Excel criado após a execução do código da Listagem 4. O arquivo foi criado com o nome definido na linha do FIleOutputStream, e o nome da planilha que foi definido na linha createSheet(“Alunos”).

Arquivo
Excel criado após a execução do código da Listagem
4

Figura 3. Arquivo Excel criado após a execução do código da Listagem 4.

Editando um arquivo Excel já existente

Outra possibilidade é abrir um arquivo já existente, e alterar os dados das células. Por exemplo, caso o professor queira adicionar um ponto na nota 1 de todos os alunos que estão no arquivo. É preciso alterar os dados da coluna Nota1, Média e também da coluna Aprovado. A Listagem 5 mostra o código que abre o arquivo, e altera os valores das colunas citadas.

Na classe Cell, assim como existe os métodos get para recuperar os valores que estão nas células, existe também o método set, então para alterar os valores das células basta utilizar esses dois métodos.

Listagem 5. Código que abre o arquivo Excel, e altera os dados das colunas.

  package com.devmedia.teste;
   
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
   
  import org.apache.poi.hssf.usermodel.HSSFSheet;
  import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  import org.apache.poi.ss.usermodel.Cell;
  import org.apache.poi.ss.usermodel.Row;
   
  public class EditaExcel {
   
         private static final String fileName = "C:/teste/novo.xls";
         
         public static void main(String[] args) throws IOException  {
   
               try {
                      FileInputStream file = new FileInputStream(new File(
                                    EditaExcel.fileName));
   
                      HSSFWorkbook workbook = new HSSFWorkbook(file);
                      HSSFSheet sheetAlunos = workbook.getSheetAt(0);
   
                      for (int i = 0; i < sheetAlunos.getPhysicalNumberOfRows(); i++) {
   
                             Row row = sheetAlunos.getRow(i);
                             Cell cellNota1 = row.getCell(2);
                             if (cellNota1.getNumericCellValue() < 9) {
                                    cellNota1.setCellValue(cellNota1.getNumericCellValue() + 1);
                             } else {
                                    cellNota1.setCellValue(10);
                             }
   
                             Cell cellNota2 = row.getCell(3);
                             Cell cellMedia = row.getCell(4);
                             cellMedia
                                          .setCellValue((cellNota1.getNumericCellValue() + cellNota2
                                                        .getNumericCellValue()) / 2);
                             Cell cellAprovado = row.getCell(5);
                             cellAprovado.setCellValue(cellMedia.getNumericCellValue() >= 6);
                      }
                      file.close();
   
                      FileOutputStream outFile = new FileOutputStream(new File(EditaExcel.fileName));
                      workbook.write(outFile);
                      outFile.close();
                      System.out.println("Arquivo Excel editado com sucesso!");
   
               } catch (FileNotFoundException e) {
                      e.printStackTrace();
                      System.out.println("Arquivo Excel não encontrado!");
               } catch (IOException e) {
                      e.printStackTrace();
                      System.out.println("Erro na edição do arquivo!");
               }
   
         }
   
  }

A Figura 4 mostra o arquivo Excel que foi criado no exemplo anterior, mas com os dados alterados pela execução do código da Listagem 5. A nota1 foi incrementada em 1 ponto para todos os alunos, com isso os dados da coluna média e da coluna aprovado foram alterados.

Dados
alterados na planilha

Figura 4. Dados alterados na planilha.

O Apache POI permite a manipulação completa de uma planilha Excel, esse artigo mostrou os comandos mais utilizados, mas ainda existem outras funcionalidades, como criar e alterar formulas nas células, alterar fontes dos dados para cada célula. Abrir diversas planilhas no mesmo arquivo. Além que o POI permite ainda abrir arquivos do Word, do PowerPoint e arquivos de e-mail do Outlook.

Esse artigo mostrou como utilizar o framework Apache POI para a manipulação de arquivos do Microsoft Excel. Isso ainda é bastante utilizado, porque ainda hoje, muitas empresas ainda utilizam esse tipo de arquivo para o controle de diversas atividades. A aplicação desenvolvida neste exemplo mostra as principais funcionalidades do framework como abrir, criar e editar arquivos Excel.

Para mais informações sobre o projeto POI, o endereço do site do projeto é http://poi.apache.org/.

Espero que esse artigo seja útil! Até a próxima