Перейти к основному содержимому

Работа с Microsoft Excel в Java

· 6 мин. чтения

Задача: Наибольшая подстрока палиндром

Для заданной строки s, верните наибольшую подстроку палиндром входящую в s. Подстрока — это непрерывная непустая последовательность символов внутри строки. Стока является палиндромом, если она читается одинаково в обоих направлениях...

ANDROMEDA 42

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 .