1. Обзор
В этом руководстве мы продемонстрируем использование API-интерфейсов Apache POI и JExcel для работы с электронными таблицами Excel.
Обе библиотеки могут использоваться для динамического чтения, записи и изменения содержимого электронной таблицы Excel и обеспечивают эффективный способ интеграции Microsoft Excel в приложение Java.
2. Зависимости Maven
Для начала нам нужно добавить следующие зависимости в наш файл pom.xml
:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
Последние версии poi-ooxml и jxls-jexcel можно загрузить с Maven Central.
3. Апач POI
Библиотека Apache POI поддерживает файлы .xls
и .xlsx
и является более сложной библиотекой, чем другие библиотеки Java для работы с файлами Excel.
Он предоставляет интерфейс Workbook
для моделирования файла Excel и интерфейсы
Sheet
, Row
и Cell
, которые моделируют элементы файла Excel, а также реализации каждого интерфейса для обоих форматов файлов.
При работе с более новым форматом файлов .xlsx мы будем использовать
классы XSSFWorkbook
, XSSFSheet
, XSSFRow и
XSSFCell .
Для работы со старым форматом .xls
мы используем классы HSSFWorkbook
, HSSFSheet
, HSSFRow
и HSSFCell
.
3.1. Чтение из Excel
Давайте создадим метод, который открывает файл .xlsx
, а затем считывает содержимое с первого листа файла.
Метод чтения содержимого ячейки зависит от типа данных в ячейке. Тип содержимого ячейки можно определить с помощью метода getCellType()
интерфейса Cell .
Во-первых, давайте откроем файл из заданного места:
FileInputStream file = new FileInputStream(new File(fileLocation));
Workbook workbook = new XSSFWorkbook(file);
Затем давайте извлечем первый лист файла и пройдемся по каждой строке:
Sheet sheet = workbook.getSheetAt(0);
Map<Integer, List<String>> data = new HashMap<>();
int i = 0;
for (Row row : sheet) {
data.put(i, new ArrayList<String>());
for (Cell cell : row) {
switch (cell.getCellType()) {
case STRING: ... break;
case NUMERIC: ... break;
case BOOLEAN: ... break;
case FORMULA: ... break;
default: data.get(new Integer(i)).add(" ");
}
}
i++;
}
Apache POI имеет разные методы чтения каждого типа данных. Давайте расширим содержание каждого случая переключателя выше.
Когда значение перечисления типа ячейки равно 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() + "");
}
Для логических
значений у нас есть метод getBooleanCellValue()
:
data.get(i).add(cell.getBooleanCellValue() + "");
И когда тип ячейки FORMULA
, мы можем использовать метод getCellFormula()
:
data.get(i).add(cell.getCellFormula() + "");
3.2. Запись в Excel
Apache POI использует те же интерфейсы, что и в предыдущем разделе, для записи в файл Excel и имеет лучшую поддержку стилей, чем JExcel.
Давайте создадим метод, который записывает список людей на лист под названием «Люди»
.
Во-первых, мы создадим и настроим строку заголовка, содержащую ячейки «Имя»
и «Возраст» :
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<Integer, List<String>> 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 — это облегченная библиотека с тем преимуществом, что ее проще использовать, чем Apache POI, но с тем недостатком, что она поддерживает только обработку файлов Excel в формате .xls
(1997–2003).
На данный момент файлы .xlsx не поддерживаются.
4.1. Чтение из Excel
Для работы с файлами Excel эта библиотека предоставляет ряд классов, представляющих различные части файла Excel. Класс Workbook
представляет всю коллекцию листов. Класс Sheet
представляет один лист, а класс Cell
представляет одну ячейку электронной таблицы.
Давайте напишем метод, который создает книгу из указанного файла Excel, получает первый лист файла, затем просматривает его содержимое и добавляет каждую строку в HashMap
:
public class JExcelHelper {
public Map<Integer, List<String>> readJExcel(String fileLocation)
throws IOException, BiffException {
Map<Integer, List<String>> 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<String>());
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
.
Класс WritableCell
имеет подклассы, соответствующие различным типам содержимого , которое может быть записано: 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-файла, содержащего ячейки «Имя»
и «Возраст» :
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. Заключение
В этой статье показано, как использовать Apache POI
API и JExcel
API для чтения и записи файла Excel из программы Java.
Полный исходный код этой статьи можно найти в проекте GitHub .