Leitura de arquivos Excel com Apache POI: Soluções para problemas comuns

O Apache POI é uma biblioteca amplamente utilizada para manipular arquivos do Microsoft Excel em ambientes Java. Este artigo aborda os principais desafios enfrentados durante a leitura de arquivos .xls (Excel 2003) e .xlsx (Excel 2007+), além de soluções práticas para erros frequentes.

1. Diferenças entre .xls e .xlsx

Os formatos .xls e .xlsx são incompatíveis em nível estrutural. O primeiro é baseado em binários antigos, enquanto o segundo utiliza XML dentro de um arquivo ZIP. Para lidar com ambos, recomenda-se o uso da classe WorkbookFactory, que detecta automaticamente o tipo de arquivo:

Workbook workbook = WorkbookFactory.create(new File("caminho/arquivo.xlsx"));

Essa abordagem elimina a necessidade de escolher manualmente entre HSSFWorkbook (para .xls) ou XSSFWorkbook (para .xlsx).

No entanto, o uso do formato .xlsx exige a inclusão da dependência xmlbeans, pois o Apache POI não inclui essa biblioteca por padrão. A ausência de xmlbeans.jar resulta em erros como:

java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlObject

Certifique-se de adicionar a dependência correta no projeto (Maven ou Gradle).

2. Problema de Registro Inválido: Unexpected record type

Durante a leitura de alguns arquivos, pode ocorrer uma exceção como:

java.lang.RuntimeException: Unexpected record type (org.apache.poi.hssf.record.DefaultRowHeightRecord)

Esse erro geralmente está relacionado a arquivos corrompidos ou criados com versões não padronizadas do Excel. A solução mais simples é abrir o arquivo no Excel, salvar novamente e tentar novamente.

3. Processamento em Lote: Leitura de Todos os Aruqivos Excel em uma Pasta

A seguir, um exemplo funcional que percorre todos os arquivos Excel em um diretório, lê suas planilhas e salva os dados em um arquivo de texto:

import org.apache.poi.ss.usermodel.*;
import java.io.*;
import java.util.Arrays;

public class LeitorExcelLote {

    public static void main(String[] args) {
        String caminhoPasta = "C:\\Users\\Usuario\\Documentos\\Planilhas";
        File pasta = new File(caminhoPasta);
        File[] arquivos = pasta.listFiles((dir, nome) -> 
            nome.toLowerCase().endsWith(".xls") || nome.toLowerCase().endsWith(".xlsx")
        );

        if (arquivos == null || arquivos.length == 0) {
            System.out.println("Nenhum arquivo Excel encontrado.");
            return;
        }

        System.out.println("Total de arquivos Excel: " + arquivos.length);

        for (File arquivo : arquivos) {
            processarArquivo(arquivo.getAbsolutePath());
        }
    }

    private static void processarArquivo(String caminho) {
        try (Workbook workbook = WorkbookFactory.create(new File(caminho))) {
            Sheet planilha = workbook.getSheetAt(0);

            for (Row linha : planilha) {
                StringBuilder linhaTexto = new StringBuilder();
                for (Cell celula : linha) {
                    linhaTexto.append(obterValorCelula(celula)).append("---");
                }
                salvarEmArquivo(linhaTexto.toString());
                System.out.println(linhaTexto);
            }
        } catch (Exception e) {
            System.err.println("Erro ao processar " + caminho + ": " + e.getMessage());
        }
    }

    private static Object obterValorCelula(Cell celula) {
        switch (celula.getCellType()) {
            case BLANK: return null;
            case BOOLEAN: return celula.getBooleanCellValue();
            case ERROR: return celula.getErrorCellValue();
            case FORMULA: return celula.getCellFormula();
            case NUMERIC: return celula.getNumericCellValue();
            case STRING: return celula.getStringCellValue();
            default: return null;
        }
    }

    private static void salvarEmArquivo(String conteudo) {
        File arquivo = new File("resultados.txt");
        if (!arquivo.exists()) {
            try {
                arquivo.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        try (FileWriter escritor = new FileWriter(arquivo, true);
             PrintWriter saida = new PrintWriter(escritor)) {
            saida.println(conteudo);
            saida.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Este código garante tratamento adequado de exceções, uso seguro de recursos com try-with-resources, e evita vazamentos de memória. Além disso, o método obterValorCelula foi simplificado e centralizado para melhor legibilidade.

Tags: apache poi Excel java XSSF HSSF

Publicado em 9-22 14:53