Блог о программировании

Май 18, 2011

 

Java + Excel файлы (Apache POI)


С периодичностью раз в два-три года сталкиваюсь с проектами, в которых опять нужно работать с Excel файлами.
Наверно это у меня что-то кармическое...
Сейчас, в очередной раз приходиться реализовать полуавтоматический разбор сотен excel-файлов с прайсами.
В прошлых своих проектах использовал JExcelApi.
Ничего плохого про эту библиотеку сказать не могу, но хочется какого-то разнообразия в жизни поэтому в этот раз с товарищем решили попробовать Apache POI.

Apache POI поддерживает как формат для обычных *.xsl файлов (HSSF) так и *.xslx файлы (XSSF).

Кстати, формат для *.xsl файлы в Apache POI они обзывают "HSSF - Horrible SpreadSheet Format", то есть "Вселяющий ужас формат для электронных таблиц".
Для того, чтобы приступить к работе, как обычно прописываем зависимости в pom.xml:

<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <!-- версия 3.7 - стабильная, 3.8 в "beta 2" (на 18 мая 2011г). --> <version>3.7</version> </dependency> </dependencies>

Для примера, приведу очень простой файл - список ФИО, сумма + Итог:

Если нужно просто вытащить текст, можно использовать "класс-извелкатель": ExcelExtractor

  import java.io.FileInputStream; import java.io.InputStream; import java.util.Iterator; import org.apache.poi.hssf.extractor.ExcelExtractor; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;   public class App {   public static void main(String[] args) throws Exception { InputStream in = new FileInputStream("/tmp/1.xls"); // Внимание InputStream будет закрыт // Если нужно не закрывающий см. JavaDoc по POIFSFileSystem : http://goo.gl/1Auu7 HSSFWorkbook wb = new HSSFWorkbook(in);   ExcelExtractor extractor = new ExcelExtractor(wb); extractor.setFormulasNotResults(false); // Считать формулы extractor.setIncludeSheetNames(true); String text = extractor.getText();   System.out.println(text);   } }

Вывод на консоль:

Sheet1 &A Смирнов 40000.0 Иванов 40000.0 Кузнецов 50000.0 Попов 40000.0 Соколов 70000.0 Лебедев 70000.0 Козлов 50000.0 Новиков 50000.0 Морозов 50000.0 Петров 40000.0 Итого 500000.0 Page &P Sheet2 &A Page &P Sheet3 &A Page &P

Когда этого не достаточно (например нужно найти нужную ячейку и т.д.), без проблем можно использовать нормальное API:
Пример:

import java.io.FileInputStream; import java.io.InputStream; import java.util.Iterator; import org.apache.poi.hssf.extractor.ExcelExtractor; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*;   public class App {   public static void main(String[] args) throws Exception { InputStream in = new FileInputStream("/tmp/1.xls"); HSSFWorkbook wb = new HSSFWorkbook(in);   Sheet sheet = wb.getSheetAt(0); Iterator<Row> it = sheet.iterator(); while (it.hasNext()) { Row row = it.next(); Iterator<Cell> cells = row.iterator(); while (cells.hasNext()) { Cell cell = cells.next(); int cellType = cell.getCellType(); switch (cellType) { case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue() + "="); break; case Cell.CELL_TYPE_NUMERIC: System.out.print("[" + cell.getNumericCellValue() + "]"); break;   case Cell.CELL_TYPE_FORMULA: System.out.print("[" + cell.getNumericCellValue() + "]"); break; default: System.out.print("|"); break; } } System.out.println(); } } }

Вывод на консоль:

Смирнов=[40000.0] Иванов=[40000.0] Кузнецов=[50000.0] Попов=[40000.0] Соколов=[70000.0] Лебедев=[70000.0] Козлов=[50000.0] Новиков=[50000.0] Морозов=[50000.0] Петров=[40000.0] Итого=[500000.0]

Конечно если у вас не такие "рафинированные" примеры, то код будет намного более сложным.
Скорее всего вам придется делать еще один уровень API, заточенный под ваши нужды или ваши файлы.
Например у меня товарищ сделал для этих целей: Парсер на Scala поверх Apache POI для разбора Excel-файлов.