Работа с Microsoft Excel в Java

Работа с Microsoft Excel в Java

1. Вступление

В этом руководстве мы продемонстрируем использованиеApache POI and JExcel APIs for working with Excel spreadsheets.

Обе библиотеки могут использоваться для динамического чтения, записи и изменения содержимого электронной таблицы Excel и обеспечения эффективного способа интеграции Microsoft Excel в приложение Java.

2. Maven Зависимости

Для начала нам нужно будет добавить следующие зависимости в наш файлpom.xml:


    org.apache.poi
    poi
    3.15


    org.apache.poi
    poi-ooxml
    3.15

Последние версииpoi-ooxml иjxls-jexcel можно загрузить с Maven Central.

3. Apache POI

Apache POI library supports both .xls and .xlsx files и - более сложная библиотека, чем другие библиотеки Java, для работы с файлами Excel.

Он предоставляет интерфейсWorkbook для моделирования файлаExcel, а также интерфейсыSheet,Row иCell, которые моделируют элементы файла Excel, как а также реализации каждого интерфейса для обоих форматов файлов.

При работе с новым форматом файлов.xlsx вы должны использовать классыXSSFWorkbook, XSSFSheet, XSSFRow, and XSSFCell.

Для работы со старым форматом.xls используйте классыHSSFWorkbook, HSSFSheet, HSSFRow, иHSSFCell.

3.1. Чтение из Excel

Давайте создадим метод, который открывает файл.xlsx, а затем считывает содержимое с первого листа файла.

Способ чтения содержимого ячейки варьируется в зависимости от типа данных в ячейке. Тип содержимого ячейки можно определить с помощью методаgetCellTypeEnum() интерфейсаCell.

Во-первых, давайте откроем файл из заданного места:

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

Затем извлечем первый лист файла и переберем каждую строку:

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. Давайте расширим содержание каждого случая переключения выше.

Когда значение перечисления типа ячейки равноSTRING, содержимое будет считываться с использованием методаgetRichStringCellValue() интерфейсаCell:

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

Ячейки с типом содержимогоNUMERIC могут содержать дату или число и читаются следующим образом:

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

Для значенийBOOLEAN у нас есть методgetBooleanCellValue():

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

А когда тип ячейкиFORMULA, мы можем использовать методgetCellFormula():

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

3.2. Запись в Excel

Apache POI использует те же интерфейсы, что и в предыдущем разделе, для записи в файл Excel и имеет лучшую поддержку стилей, чем JExcel.

Давайте создадим метод, который записывает список людей на лист с названием“Persons”. Сначала мы создадим и стилизуем строку заголовка, содержащую ячейки“Name” и“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);

Затем давайте напишем содержимое таблицы в другом стиле:

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

Наконец, давайте запишем содержимое в файл‘temp.xlsx' в текущем каталоге и закроем книгу:

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

Давайте протестируем вышеуказанные методы в тестеJUnit, который записывает содержимое в файлtemp.xlsx, а затем читает тот же файл, чтобы убедиться, что он содержит текст, который мы написали:

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

Библиотека JExcel - это легкая библиотека, имеющая то преимущество, что ее проще использовать, чем Apache POI, но с недостатком, заключающимся в том, что она обеспечивает только поддержку обработки файлов Excel в формате.xls (1997-2003).

На данный момент файлы.xlsx не поддерживаются.

4.1. Чтение из Excel

Для работы с файлами Excel эта библиотека предоставляет серию классов, которые представляют различные части файла Excel. The Workbook class represents the entire collection of sheets. КлассSheet представляет отдельный лист, а классCell представляет одну ячейку электронной таблицы.

Давайте напишем метод, который создает книгу из указанного файла Excel, получает первый лист файла, затем просматривает его содержимое и добавляет каждую строку вHashMap:

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. Запись в Excel

Для записи в файл Excel библиотека JExcel предлагает классы, аналогичные использованным выше, которые моделируют файл электронной таблицы:WritableWorkbook,WritableSheet иWritableCell.

The WritableCell class has subclasses corresponding to the different types of content, которое можно записать:Label,DateTime,Number,Boolean,Blank иFormula.

Эта библиотека также обеспечивает поддержку основных форматов, таких как управление шрифтом, цветом и шириной ячейки.

Давайте напишем метод, который создает книгу с именем‘temp.xls' в текущем каталоге, а затем записывает то же содержимое, которое мы написали в разделе Apache POI.

Сначала создадим книгу:

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

Затем давайте создадим первый лист и напишем заголовок файла Excel, содержащий ячейки“Name” и“Age”:

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

В новом стиле запишем содержимое созданной таблицы:

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

Очень важно не забыть записать в файл и закрыть его в конце, чтобы его могли использовать другие процессы, используя методыwrite() иclose() классаWorkbook:

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

5. Заключение

В этом руководстве показано, как использовать APIApache POI иJExcel API для чтения и записи файла Excel из программы Java.

Полный исходный код этой статьи можно найти в папкеGitHub project.