1. Что такое Apache POI и зачем он нужен?
Apache POI (Poor Obfuscation Implementation) — это мощная библиотека с открытым исходным кодом на языке Java, предназначенная для создания, чтения и модификации файлов форматов Microsoft Office (Excel, Word, PowerPoint, Outlook). Она позволяет разработчикам программно управлять документами без необходимости установки самого пакета Microsoft Office. Библиотека предоставляет два основных API: HSSF (Horrible Spreadsheet Format) для работы с файлами формата .xls (Excel 97-2003) и XSSF (XML Spreadsheet Format) для работы с современным форматом .xlsx (Excel 2007+). Для Word файлов используются аналогичные компоненты: HWPF (для .doc) и XWPF (для .docx).
Зачем это нужно? В современной разработке часто возникает необходимость автоматизировать работу с офисными документами: генерировать отчёты, импортировать данные из таблиц, создавать шаблоны договоров или формировать сложные аналитические сводки. Apache POI решает эти задачи, предоставляя Java-разработчикам полный контроль над структурой документа: от форматирования ячеек и создания графиков в Excel до работы с таблицами, изображениями и стилями в Word.
Библиотека активно поддерживается сообществом Apache Software Foundation, имеет обширную документацию и используется в крупных корпоративных проектах. Она совместима с Java 8 и выше, что делает её универсальным инструментом для большинства современных Java-приложений, включая веб-сервисы, десктопные приложения и системы обработки данных.
2. Установка
Apache POI распространяется через Maven Central Repository. Для подключения к проекту необходимо добавить зависимости в файл pom.xml (для Maven) или build.gradle (для Gradle).
Maven
<!-- Основная зависимость для работы с Excel (.xls и .xlsx) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.3.0</version>
</dependency>
<!-- Для работы с Word документами (.doc и .docx) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.3.0</version>
</dependency>
Gradle
implementation 'org.apache.poi:poi-ooxml:5.3.0'
implementation 'org.apache.poi:poi-scratchpad:5.3.0'
Важно: Версия 5.3.0 актуальна на момент написания статьи. Рекомендуется проверять последнюю версию на Maven Repository. Также обратите внимание, что poi-ooxml уже включает в себя poi (базовый модуль) и poi-ooxml-lite (для работы с OOXML форматами).
3. Быстрый старт: минимальный рабочий пример
Создадим простой Excel файл с одной строкой данных и запишем его на диск.
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
public class QuickStart {
public static void main(String[] args) {
// Создаем новую рабочую книгу (Workbook) для формата .xlsx
try (Workbook workbook = new XSSFWorkbook()) {
// Создаем лист с именем "Данные"
Sheet sheet = workbook.createSheet("Данные");
// Создаем строку (индекс 0 — первая строка)
Row row = sheet.createRow(0);
// Создаем ячейку в колонке A (индекс 0)
Cell cell = row.createCell(0);
cell.setCellValue("Hello, Apache POI!");
// Создаем ячейку в колонке B (индекс 1) с числовым значением
Cell cell2 = row.createCell(1);
cell2.setCellValue(42);
// Записываем книгу в файл
try (FileOutputStream fos = new FileOutputStream("example.xlsx")) {
workbook.write(fos);
}
System.out.println("Файл example.xlsx успешно создан!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
После запуска в корне проекта появится файл example.xlsx, который можно открыть в Excel. Этот пример демонстрирует базовый цикл: создание книги → создание листа → создание строки → создание ячейки → запись в файл.
4. Основные классы и методы
Ниже приведены ключевые классы и методы библиотеки Apache POI с подробным описанием и примерами.
4.1. Workbook (интерфейс) — рабочая книга
Сигнатура: Workbook workbook = new XSSFWorkbook(); (для .xlsx) или new HSSFWorkbook(); (для .xls)
Что делает: Представляет собой весь Excel-документ. Через этот объект создаются листы, управляются стили, шрифты и формулы.
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Отчёт");
// ... работа с данными ...
workbook.close(); // Всегда закрывайте Workbook для освобождения ресурсов
4.2. Sheet (интерфейс) — лист рабочей книги
Сигнатура: Sheet createSheet(String sheetname)
Что делает: Создаёт новый лист с указанным именем. Позволяет управлять строками, колонками и настройками печати.
Sheet sheet = workbook.createSheet("Продажи");
// Установка ширины колонки A (индекс 0) в 20 символов
sheet.setColumnWidth(0, 20 * 256);
// Заморозка первой строки (шапка таблицы)
sheet.createFreezePane(0, 1);
4.3. Row (интерфейс) — строка листа
Сигнатура: Row createRow(int rownum)
Что делает: Создаёт строку с указанным индексом (0 — первая строка). Через объект Row создаются ячейки.
Row headerRow = sheet.createRow(0);
Row dataRow = sheet.createRow(1);
// Получение существующей строки (если она есть)
Row existingRow = sheet.getRow(0);
4.4. Cell (интерфейс) — ячейка
Сигнатура: Cell createCell(int columnIndex)
Что делает: Создаёт ячейку в указанной колонке. Поддерживает различные типы данных: String, Number, Date, Boolean, Formula.
Cell cell = row.createCell(0);
cell.setCellValue("Текст");
cell.setCellValue(123.45);
cell.setCellValue(true);
cell.setCellValue(new Date());
// Установка формулы
Cell formulaCell = row.createCell(2);
formulaCell.setCellFormula("SUM(A1:B1)");
4.5. CellStyle (интерфейс) — стиль ячейки
Сигнатура: CellStyle createCellStyle() (метод Workbook)
Что делает: Определяет внешний вид ячейки: шрифт, цвет, границы, выравнивание, заливка. Стили должны создаваться на уровне Workbook и переиспользоваться.
CellStyle style = workbook.createCellStyle();
// Установка границ
style.setBorderBottom(BorderStyle.THIN);
style.setBorderTop(BorderStyle.THIN);
// Выравнивание по центру
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
// Заливка цветом
style.setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// Применение стиля к ячейке
cell.setCellStyle(style);
4.6. Font (интерфейс) — шрифт
Сигнатура: Font createFont() (метод Workbook)
Что делает: Создаёт объект шрифта, который можно применить к CellStyle. Поддерживает имя, размер, цвет, жирность, курсив, подчёркивание.
Font headerFont = workbook.createFont();
headerFont.setFontName("Arial");
headerFont.setFontHeightInPoints((short) 14);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFont(headerFont);
headerStyle.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
4.7. DataFormatter — форматирование вывода
Сигнатура: String formatCellValue(Cell cell)
Что делает: Позволяет читать значение ячейки с учётом её форматирования (например, дата, проценты, валюта). Полезно при чтении файлов.
DataFormatter formatter = new DataFormatter();
Cell cell = row.getCell(0);
String cellValue = formatter.formatCellValue(cell);
System.out.println("Отформатированное значение: " + cellValue);
4.8. XWPFDocument — работа с Word (.docx)
Сигнатура: XWPFDocument document = new XWPFDocument();
Что делает: Представляет собой Word-документ. Позволяет создавать параграфы, таблицы, изображения, списки и управлять форматированием текста.
import org.apache.poi.xwpf.usermodel.*;
try (XWPFDocument doc = new XWPFDocument()) {
// Создание параграфа
XWPFParagraph paragraph = doc.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Привет, мир!");
run.setBold(true);
run.setFontSize(16);
// Создание таблицы
XWPFTable table = doc.createTable(3, 3);
table.getRow(0).getCell(0).setText("Заголовок 1");
table.getRow(0).getCell(1).setText("Заголовок 2");
// Запись в файл
try (FileOutputStream fos = new FileOutputStream("example.docx")) {
doc.write(fos);
}
}
5. Реальный практический пример (150+ строк кода)
Создадим полноценный генератор отчёта о продажах. Программа создаёт Excel-файл с данными, форматированием, формулами и графиком (диаграммой).
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
public class SalesReportGenerator {
public static void main(String[] args) {
String[] months = {"Январь", "Февраль", "Март", "Апрель", "Май", "Июнь"};
double[] sales = {15000.50, 22000.75, 18000.00, 25000.30, 21000.90, 28000.60};
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet("Продажи 2024");
// === Стили ===
Font titleFont = workbook.createFont();
titleFont.setFontName("Calibri");
titleFont.setFontHeightInPoints((short) 18);
titleFont.setBold(true);
titleFont.setColor(IndexedColors.DARK_BLUE.getIndex());
CellStyle titleStyle = workbook.createCellStyle();
titleStyle.setFont(titleFont);
titleStyle.setAlignment(HorizontalAlignment.CENTER);
Font headerFont = workbook.createFont();
headerFont.setFontName("Calibri");
headerFont.setFontHeightInPoints((short) 12);
headerFont.setBold(true);
headerFont.setColor(IndexedColors.WHITE.getIndex());
CellStyle headerStyle = workbook.createCellStyle();
headerStyle.setFont(headerFont);
headerStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
headerStyle.setAlignment(HorizontalAlignment.CENTER);
headerStyle.setBorderBottom(BorderStyle.THIN);
headerStyle.setBorderTop(BorderStyle.THIN);
CellStyle dataStyle = workbook.createCellStyle();
dataStyle.setBorderBottom(BorderStyle.THIN);
dataStyle.setBorderLeft(BorderStyle.THIN);
dataStyle.setBorderRight(BorderStyle.THIN);
dataStyle.setBorderTop(BorderStyle.THIN);
dataStyle.setAlignment(HorizontalAlignment.CENTER);
dataStyle.setDataFormat(workbook.createDataFormat().getFormat("#,##0.00"));
// === Заголовок отчёта ===
Row titleRow = sheet.createRow(0);
titleRow.setHeightInPoints(30);
Cell titleCell = titleRow.createCell(0);
titleCell.setCellValue("Отчёт о продажах за первое полугодие 2024");
titleCell.setCellStyle(titleStyle);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2));
// === Шапка таблицы ===
Row headerRow = sheet.createRow(2);
String[] headers = {"Месяц", "Продажи (руб.)", "Доля (%)"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
cell.setCellStyle(headerStyle);
}
// === Данные и формулы ===
double totalSales = 0;
for (int i = 0; i < months.length; i++) {
Row row = sheet.createRow(i + 3);
// Месяц
Cell monthCell = row.createCell(0);
monthCell.setCellValue(