Trabalhando com Microsoft Excel em Java

Trabalhando com Microsoft Excel em Java

1. Introdução

Neste tutorial, demonstraremos o uso deApache POI and JExcel APIs for working with Excel spreadsheets.

As duas bibliotecas podem ser usadas para ler, gravar e modificar dinamicamente o conteúdo de uma planilha do Excel e fornecer uma maneira eficaz de integrar o Microsoft Excel a um aplicativo Java.

2. Dependências do Maven

Para começar, precisaremos adicionar as seguintes dependências ao nosso arquivopom.xml:


    org.apache.poi
    poi
    3.15


    org.apache.poi
    poi-ooxml
    3.15

As versões mais recentes depoi-ooxml ejxls-jexcel podem ser baixadas do Maven Central.

3. Apache POI

OApache POI library supports both .xls and .xlsx filese é uma biblioteca mais complexa do que outras bibliotecas Java para trabalhar com arquivos Excel.

Ele fornece a interfaceWorkbook para modelar um arquivoExcel, e as interfacesSheet,RoweCell que modelam os elementos de um arquivo Excel, como bem como implementações de cada interface para ambos os formatos de arquivo.

Ao trabalhar com o formato de arquivo.xlsx mais recente, você usaria as classesXSSFWorkbook, XSSFSheet, XSSFRow, and XSSFCell.

Para trabalhar com o formato.xls mais antigo, use as classesHSSFWorkbook, HSSFSheet, HSSFRow,eHSSFCell.

3.1. Lendo do Excel

Vamos criar um método que abre um arquivo.xlsx e, em seguida, lê o conteúdo da primeira folha do arquivo.

O método para ler o conteúdo da célula varia de acordo com o tipo de dados na célula. O tipo de conteúdo da célula pode ser determinado usando o métodogetCellTypeEnum() da interfaceCell.

Primeiro, vamos abrir o arquivo de um determinado local:

FileInputStream file = new FileInputStream(new File(fileLocation));
Workbook workbook = new XSSFWorkbook(file);

A seguir, vamos recuperar a primeira folha do arquivo e iterar em cada linha:

Sheet sheet = workbook.getSheetAt(0);

Map> data = new HashMap<>();
int i = 0;
for (Row row : sheet) {
    data.put(i, new ArrayList());
    for (Cell cell : row) {
        switch (cell.getCellTypeEnum()) {
            case STRING: ... break;
            case NUMERIC: ... break;
            case BOOLEAN: ... break;
            case FORMULA: ... break;
            default: data.get(new Integer(i)).add(" ");
        }
    }
    i++;
}

Apache POI has different methods for reading each type of data. Vamos expandir o conteúdo de cada caixa de switch acima.

Quando o valor enum do tipo de célula éSTRING, o conteúdo será lido usando o métodogetRichStringCellValue() da interfaceCell:

data.get(new Integer(i)).add(cell.getRichStringCellValue().getString());

As células com o tipo de conteúdoNUMERIC podem conter uma data ou um número e são lidas da seguinte maneira:

if (DateUtil.isCellDateFormatted(cell)) {
    data.get(i).add(cell.getDateCellValue() + "");
} else {
    data.get(i).add(cell.getNumericCellValue() + "");
}

Para valores deBOOLEAN, temos o métodogetBooleanCellValue():

data.get(i).add(cell.getBooleanCellValue() + "");

E quando o tipo de célula éFORMULA, podemos usar o métodogetCellFormula():

data.get(i).add(cell.getCellFormula() + "");

3.2. Escrevendo para Excel

O Apache POI usa as mesmas interfaces apresentadas na seção anterior para gravar em um arquivo do Excel e tem um suporte melhor ao estilo do que o JExcel.

Vamos criar um método que escreva uma lista de pessoas em uma planilha intitulada“Persons”. Primeiro, vamos criar e estilizar uma linha de cabeçalho que contém células“Name”e“Age”:

Workbook workbook = new XSSFWorkbook();

Sheet sheet = workbook.createSheet("Persons");
sheet.setColumnWidth(0, 6000);
sheet.setColumnWidth(1, 4000);

Row header = sheet.createRow(0);

CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

XSSFFont font = ((XSSFWorkbook) workbook).createFont();
font.setFontName("Arial");
font.setFontHeightInPoints((short) 16);
font.setBold(true);
headerStyle.setFont(font);

Cell headerCell = header.createCell(0);
headerCell.setCellValue("Name");
headerCell.setCellStyle(headerStyle);

headerCell = header.createCell(1);
headerCell.setCellValue("Age");
headerCell.setCellStyle(headerStyle);

A seguir, vamos escrever o conteúdo da tabela com um estilo diferente:

CellStyle style = workbook.createCellStyle();
style.setWrapText(true);

Row row = sheet.createRow(2);
Cell cell = row.createCell(0);
cell.setCellValue("John Smith");
cell.setCellStyle(style);

cell = row.createCell(1);
cell.setCellValue(20);
cell.setCellStyle(style);

Por fim, vamos gravar o conteúdo em um arquivo‘temp.xlsx' no diretório atual e fechar a pasta de trabalho:

File currDir = new File(".");
String path = currDir.getAbsolutePath();
String fileLocation = path.substring(0, path.length() - 1) + "temp.xlsx";

FileOutputStream outputStream = new FileOutputStream(fileLocation);
workbook.write(outputStream);
workbook.close();

Vamos testar os métodos acima em um testeJUnit que grava o conteúdo no arquivotemp.xlsx e depois lê o mesmo arquivo para verificar se ele contém o texto que escrevemos:

public class ExcelTest {

    private ExcelPOIHelper excelPOIHelper;
    private static String FILE_NAME = "temp.xlsx";
    private String fileLocation;

    @Before
    public void generateExcelFile() throws IOException {
        File currDir = new File(".");
        String path = currDir.getAbsolutePath();
        fileLocation = path.substring(0, path.length() - 1) + FILE_NAME;

        excelPOIHelper = new ExcelPOIHelper();
        excelPOIHelper.writeExcel();
    }

    @Test
    public void whenParsingPOIExcelFile_thenCorrect() throws IOException {
        Map> data
          = excelPOIHelper.readExcel(fileLocation);

        assertEquals("Name", data.get(0).get(0));
        assertEquals("Age", data.get(0).get(1));

        assertEquals("John Smith", data.get(1).get(0));
        assertEquals("20", data.get(1).get(1));
    }
}

4. JExcel

A biblioteca JExcel é uma biblioteca leve, tendo a vantagem de ser mais fácil de usar do que o Apache POI, mas com a desvantagem de fornecer suporte apenas para o processamento de arquivos Excel no formato.xls (1997-2003).

No momento,.xlsx arquivos não são suportados.

4.1. Lendo do Excel

Para trabalhar com arquivos do Excel, esta biblioteca fornece uma série de classes que representam as diferentes partes de um arquivo do Excel. The Workbook class represents the entire collection of sheets. A classeSheet representa uma única planilha, e a classeCell representa uma única célula de uma planilha.

Vamos escrever um método que cria uma pasta de trabalho a partir de um arquivo Excel especificado, obtém a primeira planilha do arquivo e, em seguida, percorre seu conteúdo e adiciona cada linha em umHashMap:

public class JExcelHelper {

    public Map> readJExcel(String fileLocation)
      throws IOException, BiffException {

        Map> data = new HashMap<>();

        Workbook workbook = Workbook.getWorkbook(new File(fileLocation));
        Sheet sheet = workbook.getSheet(0);
        int rows = sheet.getRows();
        int columns = sheet.getColumns();

        for (int i = 0; i < rows; i++) {
            data.put(i, new ArrayList());
            for (int j = 0; j < columns; j++) {
                data.get(i)
                  .add(sheet.getCell(j, i)
                  .getContents());
            }
        }
        return data;
    }
}

4.2. Escrevendo para Excel

Para gravação em arquivo Excel, a biblioteca JExcel oferece classes semelhantes às utilizadas acima, que modelam um arquivo de planilha:WritableWorkbook,WritableSheeteWritableCell.

The WritableCell class has subclasses corresponding to the different types of content que pode ser escrito:Label,DateTime,Number,Boolean,Blank eFormula.

Essa biblioteca também oferece suporte para formatação básica, como controle de fonte, cor e largura da célula.

Vamos escrever um método que cria uma pasta de trabalho chamada‘temp.xls' no diretório atual e, em seguida, escreve o mesmo conteúdo que escrevemos na seção Apache POI.

Primeiro, vamos criar a pasta de trabalho:

File currDir = new File(".");
String path = currDir.getAbsolutePath();
String fileLocation = path.substring(0, path.length() - 1) + "temp.xls";

WritableWorkbook workbook = Workbook.createWorkbook(new File(fileLocation));

A seguir, vamos criar a primeira planilha e escrever o cabeçalho do arquivo excel, contendo“Name”e“Age” células:

WritableSheet sheet = workbook.createSheet("Sheet 1", 0);

WritableCellFormat headerFormat = new WritableCellFormat();
WritableFont font
  = new WritableFont(WritableFont.ARIAL, 16, WritableFont.BOLD);
headerFormat.setFont(font);
headerFormat.setBackground(Colour.LIGHT_BLUE);
headerFormat.setWrap(true);

Label headerLabel = new Label(0, 0, "Name", headerFormat);
sheet.setColumnView(0, 60);
sheet.addCell(headerLabel);

headerLabel = new Label(1, 0, "Age", headerFormat);
sheet.setColumnView(0, 40);
sheet.addCell(headerLabel);

Com um novo estilo, vamos escrever o conteúdo da tabela que criamos:

WritableCellFormat cellFormat = new WritableCellFormat();
cellFormat.setWrap(true);

Label cellLabel = new Label(0, 2, "John Smith", cellFormat);
sheet.addCell(cellLabel);
Number cellNumber = new Number(1, 2, 20, cellFormat);
sheet.addCell(cellNumber);

É muito importante lembrar de gravar no arquivo e fechá-lo no final para que possa ser usado por outros processos, usando os métodoswrite()eclose() da classeWorkbook:

workbook.write();
workbook.close();

5. Conclusão

Este tutorial ilustrou como usar a APIApache POI e a APIJExcel para ler e gravar um arquivo Excel a partir de um programa Java.

O código-fonte completo deste artigo pode ser encontrado emGitHub project.