Быстрый старт
Введение
GridExcel — это универсальное решение для простого чтения и записи в Excel, основанное на функциональном программировании и POI EventModel.
Основные преимущества:
Apache POI — это API, который часто используется разработчиками в бизнес-среде для импорта и экспорта Excel.
EventModel — это пакет SS eventmodel, представляющий собой API для чтения файлов Excel без загрузки всей электронной таблицы в память. Он требует от пользователя больше знаний, но снижает потребление памяти более чем в десять раз. Он основан на модели событий AWT в сочетании с SAX. Если вам нужен доступ только для чтения, это лучший способ сделать это.
Говоря о функциональном программировании, нельзя не упомянуть лямбда-выражения. Если вы не знакомы или не понимаете Java 8 Lambda, вы можете посмотреть эту статью на официальном сайте Oracle. Я считаю, что это одна из лучших статей о Java 8 Lambda от начального до продвинутого уровня.
Цель функционального программирования — реализовать передачу блоков кода, то есть передачу методов в качестве параметров между методами. Для этого с развитием языка Java постоянно появляются новые решения:
Примечание: пункты 5, 6 и 7 взяты из книги «Глубокое понимание виртуальной машины Java», второе издание, раздел 8.3.3 Поддержка динамических типов языков.
Решение двух проблем
В процессе использования POI большинство пользователей API часто сталкиваются с двумя проблемами, которые также пытается решить GridExcel.
Проблема 1: При использовании только простых функций импорта и экспорта данные объекты структуры различаются каждый раз, и необходимо повторно писать методы обработки, что очень хлопотно!
Решение: Извлеките логику чтения и записи из Excel и сосредоточьтесь только на бизнес-логике, упаковав её в инструмент класса.
Условия упаковки: Как и большинство API Java, POI уделяет больше внимания обработке высокоуровневых функций, таких как формулы, условное форматирование и масштабирование. Для пользователей API, использующих только функции импорта и экспорта данных, эти высокоуровневые функции используются редко, что позволяет пользователям API настраивать использование POI.
Способ упаковки: Независимо от того, чтение это или запись, нам необходимо решить проблему сопоставления отношений между столбцами в Excel и полями данных в Java. Это отношение сопоставления используется в качестве параметра (Map объекта HashMap или LinkedHashMap) и передаётся инструменту класса.
Для столбцов легко понять, что они могут быть упорядоченными числами или буквами или другими строками, используемыми в качестве первой строки для обозначения значения данных в этом столбце.
Что касается полей, их обработка требует совместимости со сложными ситуациями, такими как:
Отражение: Сначала подумайте, что большинство упаковщиков используют Reflection API. Из раздела функционального программирования мы знаем, что отражение имеет большой вес, что может снизить производительность кода, и оно не очень хорошо поддерживает обработку сложных ситуаций.
Отражение + аннотации: Этот метод может лучше поддерживать сложные ситуации, но отражение всё равно снизит производительность, а аннотации добавят код в объект данных, что, несомненно, увеличит сложность изучения для других пользователей инструментального класса.
Анонимные внутренние классы — в качестве функций прослушивания: этот метод также может хорошо поддерживать сложные ситуации, но использование анонимных внутренних классов явно имеет «вертикальную проблему» (это означает, что для выражения основных понятий требуется слишком много строк кода), что слишком громоздко. Что касается производительности, она должна быть не так хороша, как прямая передача функций.
Функциональный интерфейс (лямбда) — в качестве функции прослушивания: этот метод реализуется с использованием инструкции байт-кода invokeDynamic, напрямую передавая блок кода функции, поддерживая сложные ситуации, высокую производительность и простоту написания кода, более простую структуру, более лаконичную и не вторгающуюся в код объекта данных.
Проблема 2: Когда Excel импортируется или экспортируется за один раз, объём данных велик, что приводит к переполнению памяти или частой полной сборке мусора. Как это решить?
Решение: Чтение Excel — eventmodel. Запись Excel — streaming.SXSSFWorkbook.
Принцип: Использование POI является обычным явлением в нашей работе, и мы должны быть знакомы с этими двумя понятиями: HSSFWorkbook (обработка 97 (-2007) .xls) и XSSFWorkbook (обработка OOXML 2007 (.xlsx)). Однако eventmodel и streaming.SXSSFWorkbook встречаются редко. Они являются низкоуровневыми API POI, специально разработанными для решения проблемы потребления памяти. Используя их, можно читать и записывать данные большого объёма в Excel, избегая переполнения памяти или частых полных сборок мусора. Streaming.SXSSFWorkbook используется для записи в Excel (это оболочка для XSSFWorkbook, поддерживает только формат .xlsx). Работает по принципу скользящего окна: в памяти сохраняется только количество строк, соответствующее размеру скользящего окна, а остальные строки записываются во временный файл. Когда вызывается метод write(OutputStream stream)
, содержимое временного файла напрямую записывается в указанный OutputStream.
Использование SXSSFWorkbook имеет некоторые ограничения:
Существует инструмент на основе Java-функций (Lambda), который поддерживает потоковый API и требует версии Java 1.8 или выше. Изучение этого инструмента требует определённых усилий, но он может упростить использование.
На самом деле, на официальном сайте POI уже есть примеры использования для пользователей, а упомянутый инструмент просто предоставляет свою собственную оболочку, делая его более удобным в использовании.
<dependency>
<groupId>com.github.liuhuagui</groupId>
<artifactId>gridexcel</artifactId>
<version>2.3</version>
</dependency>
GridExcel.java предоставляет множество статических методов, которые можно использовать напрямую. Подробные примеры можно найти в тестовом коде (предоставляются тестовые данные и файлы):
/**
* Бизнес-логика обработки может быть выполнена одним из трёх способов:
* 1. Включить windowListener и поместить бизнес-логику в эту функцию.
* 2. Не включать windowListener, использовать метод get() для получения всего набора данных и выполнить последующую обработку.
* 3. Использовать функцию readFunction для непосредственной обработки или использовать локальные переменные final или effective final для хранения данных и выполнения последующей обработки.
* Обратите внимание: при использовании EventModel входные данные функции readFunction представляют собой набор значений ячеек List<String> для каждой строки.
* @throws Exception
*/
@Test
public void readXlsxByEventModel() throws Exception {
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("2007.xlsx");
GridExcel.readByEventModel(resourceAsStream,TradeOrder.class,ExcelType.XLSX)
.window(2,ts -> System.out.println(JSON.toJSONString(ts)))//Рекомендуется выполнять здесь свою бизнес-логику
.process(cs ->{
TradeOrder tradeOrder = new TradeOrder();
tradeOrder.setTradeOrderId(Long.valueOf(cs.get(0)));
Consultant consultant = new Consultant();
consultant.setConsultantName(cs.get(3));
tradeOrder.setConsultant(consultant);
tradeOrder.setPaymentRatio(cs.get(16));
return tradeOrder;
},1);
}
/**
* Использование Streaming UserModel для записи данных в Excel
* @throws Exception
*/
@Test
public void writeExcelByStreaming() throws Exception {
GridExcel.writeByStreaming(TradeOrder.class)
.head(writeFunctionMap())//Сопоставление полей объекта с столбцами Excel
.createSheet()
.process(MockData.data())//Данные моделирования. Здесь устанавливается набор данных для бизнеса.
.write(FileUtils.openOutputStream(new File("/excel/test.xlsx")));
}
Поскольку нет пользовательских бизнес-сущностей, мы можем использовать Map.class вместо них. Вот пример чтения Excel, а пример записи можно посмотреть в реализации.
/**
* No Entity — чтение Excel без сущностей
* Бизнес-логика может обрабатываться одним из трёх способов:
* 1. Включить windowListener и разместить бизнес-логику в этой функции.
* 2. Не включать windowListener, использовать метод get() для получения всего набора данных и выполнить последующую обработку.
* 3. Использовать функцию readFunction для прямой обработки или использовать локальные переменные final или effective final для сохранения данных и выполнения последующей обработки.
* Обратите внимание: при использовании EventModel входные данные функции readFunction представляют собой список значений ячеек List<String> для каждой строки.
* @throws Exception
*/
@Test
public void readXlsxByEventModelWithoutEntity() throws Exception {
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("2007.xlsx");
GridExcel.readByEventModel(resourceAsStream,Map.class,ExcelType.XLSX)
.window(2,ts -> System.out.println(JSON.toJSONString(ts)))//Рекомендуется выполнять здесь свою бизнес-логику
.process(cs ->{
Map<String, Object> map = new HashMap<String, Object>();
map.put("tradeOrderId",cs.get(0));
map.put("consultantName",cs.get(3));
map.put("paymentRatio",cs.get(16));
return map;
},1);
}
Используйте пользовательскую модель для чтения файла Excel. userModel ——
Используйте модель событий для чтения файла Excel. eventModel ——
Используйте пользовательскую модель для записи файла Excel. userModel —— Недостатки: создаваемые объекты spreadsheets целиком сохраняются в памяти, поэтому размер записи в Excel ограничен размером кучи (Heap space).
Преимущества: проще в использовании и понимании.
Сценарии использования: подходит для создания небольших таблиц Excel.
Используйте совместимое с API потоковое расширение XSSF для записи очень больших файлов Excel. Потоковая модель пользователя —
Недостатки:
Преимущества: реализуется через скользящее окно, в памяти сохраняется только содержимое указанного размера строк, остальное записывается во временный файл, размер записи Excel больше не ограничен размером кучи.
Сценарии использования: можно создавать очень большие таблицы Excel.
Если при использовании инструмента возникают проблемы или есть требования к добавлению или изменению функций, вы можете создать Issue и обратиться к автору: https://github.com/liuhuagui/gridexcel/issues. Например, если вы хотите расширить стили на строки и столбцы, кроме первой строки.
Вы можете следить за автором в его публичном аккаунте.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )