1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/51Bigod-gridexcel

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

Быстрый старт

  • Быстрый старт (Quick start)
    • Поддержка потокового API (Streaming API)
    • Поддержка чтения и записи Excel без использования объектов (No entity class reading and writing Excel)

Введение

GridExcel — это универсальное решение для простого чтения и записи в Excel, основанное на функциональном программировании и POI EventModel.

Основные преимущества:

  • На основе POI EventModel при чтении и записи данных из Excel большого объёма снижается использование памяти и предотвращается OOM с частым FullGC.
  • На основе функционального программирования поддерживается обработка сложных ситуаций, таких как связанные объекты, а также обеспечивается простота обучения.
  • Поддерживается потоковый API, что упрощает написание и понимание кода, делая его более наглядным.
  • Поддерживается использование «прокручиваемого окна» + «функции прослушивания» для обработки данных, считываемых из Excel.

Apache POI — это API, который часто используется разработчиками в бизнес-среде для импорта и экспорта Excel.

EventModel — это пакет SS eventmodel, представляющий собой API для чтения файлов Excel без загрузки всей электронной таблицы в память. Он требует от пользователя больше знаний, но снижает потребление памяти более чем в десять раз. Он основан на модели событий AWT в сочетании с SAX. Если вам нужен доступ только для чтения, это лучший способ сделать это.

Говоря о функциональном программировании, нельзя не упомянуть лямбда-выражения. Если вы не знакомы или не понимаете Java 8 Lambda, вы можете посмотреть эту статью на официальном сайте Oracle. Я считаю, что это одна из лучших статей о Java 8 Lambda от начального до продвинутого уровня.

Цель функционального программирования — реализовать передачу блоков кода, то есть передачу методов в качестве параметров между методами. Для этого с развитием языка Java постоянно появляются новые решения:

  1. В Java 1.0 использовался Abstract Window Toolkit (AWT) EventModel, но он был неуклюжим и непригодным для использования.
  2. В Java 1.1 были предложены серии «слушателей».
  3. Позже использовались внутренние классы и анонимные внутренние классы, но в большинстве случаев они использовались только в качестве обработчиков событий.
  4. Позже было обнаружено, что передача блоков кода в виде объектов (фактически данных) не только полезна, но и необходима, но функциональное программирование в Java всё ещё неуклюже и нуждается в развитии.
  5. До Java 1.7 Java представила java.lang.invoke пакет, предоставляющий новый механизм динамического определения целевых методов (не нужно полагаться исключительно на байт-код вызова инструкций, закреплённых в виртуальной машине), называемый MethodHandle, имитирующий указатель метода вызова байт-кода, аналогичный C/C++ Function Pointer, и введение инструкции вызова пятого метода invokedynamic.
  6. До Java 1.8 на основе инструкции байт-кода invokedynamic в Java 1.7 была реализована технология Lamda, которая позволяет передавать функции в качестве параметров между методами, и Java начала лучше поддерживать функциональное программирование.
  7. Разве нельзя было добиться этого с помощью отражения? Отражение имеет большой вес и низкую производительность.

Примечание: пункты 5, 6 и 7 взяты из книги «Глубокое понимание виртуальной машины Java», второе издание, раздел 8.3.3 Поддержка динамических типов языков.


Решение двух проблем

В процессе использования POI большинство пользователей API часто сталкиваются с двумя проблемами, которые также пытается решить GridExcel.

Проблема 1: При использовании только простых функций импорта и экспорта данные объекты структуры различаются каждый раз, и необходимо повторно писать методы обработки, что очень хлопотно!

Решение: Извлеките логику чтения и записи из Excel и сосредоточьтесь только на бизнес-логике, упаковав её в инструмент класса.

Условия упаковки: Как и большинство API Java, POI уделяет больше внимания обработке высокоуровневых функций, таких как формулы, условное форматирование и масштабирование. Для пользователей API, использующих только функции импорта и экспорта данных, эти высокоуровневые функции используются редко, что позволяет пользователям API настраивать использование POI.

Способ упаковки: Независимо от того, чтение это или запись, нам необходимо решить проблему сопоставления отношений между столбцами в Excel и полями данных в Java. Это отношение сопоставления используется в качестве параметра (Map объекта HashMap или LinkedHashMap) и передаётся инструменту класса.

Для столбцов легко понять, что они могут быть упорядоченными числами или буквами или другими строками, используемыми в качестве первой строки для обозначения значения данных в этом столбце.

Что касается полей, их обработка требует совместимости со сложными ситуациями, такими как:

  • Возникновение исключений при запросе полей;
  • Значение поля или ячейки равно null;
  • Возможно, значение этого столбца соответствует связанному объекту или даже полю в связанном наборе;
  • Значения поля или ячейки требуют специальной обработки, например, value == true? Завершить: сбой.

Отражение: Сначала подумайте, что большинство упаковщиков используют 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 имеет некоторые ограничения:

  • В каждый момент времени доступно только ограниченное количество строк.
  • Не поддерживается метод Sheet.clone().
  • Не поддерживается оценка формул.

Решение проблемы

Существует инструмент на основе Java-функций (Lambda), который поддерживает потоковый API и требует версии Java 1.8 или выше. Изучение этого инструмента требует определённых усилий, но он может упростить использование.

На самом деле, на официальном сайте POI уже есть примеры использования для пользователей, а упомянутый инструмент просто предоставляет свою собственную оболочку, делая его более удобным в использовании.


Быстрое использование

<dependency>
    <groupId>com.github.liuhuagui</groupId>
    <artifactId>gridexcel</artifactId>
    <version>2.3</version>
</dependency>

GridExcel.java

GridExcel.java предоставляет множество статических методов, которые можно использовать напрямую. Подробные примеры можно найти в тестовом коде (предоставляются тестовые данные и файлы):

Потоковый API

/**
  * Бизнес-логика обработки может быть выполнена одним из трёх способов:
  * 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")));
}

Чтение Excel без использования сущностей

Поскольку нет пользовательских бизнес-сущностей, мы можем использовать 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);
    }

ReadExcel

ReadExcelByUserModel

Используйте пользовательскую модель для чтения файла Excel. userModel ——

  • Недостатки: большой расход памяти, весь контент Excel будет загружен в память перед обработкой.
  • Преимущества: готовый API, простой в использовании и понимании.
  • Сценарии использования: подходит для обработки небольших объёмов данных Excel.
ReadExcelByEventModel

Используйте модель событий для чтения файла Excel. eventModel ——

  • Недостатки: нет готового API, сложный в использовании и понимании, подходит для опытных разработчиков (одна из целей GridExcel — сделать использование EventModel проще).
  • Преимущества: очень небольшой объём используемой памяти, обработка основного содержимого (хранение, использование, удаление) передаётся пользователю, пользователь может настроить функцию прослушивания для обработки этого содержимого.
  • Сценарии использования: подходит для обработки больших объёмов данных Excel, помогает избежать OOM и частых FullGC.

WriteExcel

WriteExcelByUserModel

Используйте пользовательскую модель для записи файла Excel. userModel —— Недостатки: создаваемые объекты spreadsheets целиком сохраняются в памяти, поэтому размер записи в Excel ограничен размером кучи (Heap space).

Преимущества: проще в использовании и понимании.

Сценарии использования: подходит для создания небольших таблиц Excel.

WriteExcelByStreaming

Используйте совместимое с API потоковое расширение XSSF для записи очень больших файлов Excel. Потоковая модель пользователя —

Недостатки:

  • поддерживается только XSSF;
  • не поддерживается Sheet.clone();
  • не поддерживается вычисление формул;
  • одновременно доступно только ограниченное количество строк.

Преимущества: реализуется через скользящее окно, в памяти сохраняется только содержимое указанного размера строк, остальное записывается во временный файл, размер записи Excel больше не ограничен размером кучи.

Сценарии использования: можно создавать очень большие таблицы Excel.

Проблемы

Если при использовании инструмента возникают проблемы или есть требования к добавлению или изменению функций, вы можете создать Issue и обратиться к автору: https://github.com/liuhuagui/gridexcel/issues. Например, если вы хотите расширить стили на строки и столбцы, кроме первой строки.

Вы можете следить за автором в его публичном аккаунте. Вставьте изображение здесь

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

GridExcel — это универсальное решение для простого чтения и записи Excel, реализованное с использованием Java 8 и функционального программирования, а также POI EventModel. Развернуть Свернуть
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/51Bigod-gridexcel.git
git@api.gitlife.ru:oschina-mirror/51Bigod-gridexcel.git
oschina-mirror
51Bigod-gridexcel
51Bigod-gridexcel
master