Средство экспорта Excel нового поколения: знакомство с ExcelUtil + RunnerUtil

Java задняя часть Excel Fastjson

Предыстория - задайте хороший вопрос

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

С этой проблемой я начал свой собственный "ExcelUtil" путь.В процессе я в основном контактировал с easypoi, но все равно не был удовлетворен. Поскольку easypoi похожа на большинство библиотек Java: напишите конфигурацию на основе полей. Конечно, это не значит, что это плохо, таких библиотек много, например, fastjson, Jackson и т. д. все пишут аннотации к полям для описания информации или функций этого поля. Но для экспорта в Excel мне всегда кажется, что есть более общий способ.

После периода исследований и исследований я нашел вдохновение в этикетке внешнего интерфейса и подумал, что этот метод был очень хорошим и очень хорошим. Сам тег таблицы содержит много описательной информации, такой как строки, столбцы, объединенные строки, объединенные столбцы, которые «поразительно похожи» на страницу листа Excel, а также активное развитие трех интерфейсных фреймворков за последние годы. , особенно angular и vue То, как эти две среды настраивают свойства меток, еще больше вдохновило меня на написание ExcelUtil.

Введение

ExcelUtil иRunnerUtil(GitHub), он, вероятно, был написан в мае или июне этого года и недавно был реорганизован и загружен.GitHub # ExcelUtil (не забудьте поставить звездочку!).

ExcelUtil определяет свою собственную область в соответствии с иерархической структурой файла Excel, страницы листа, строки строки и ячейки ячейки. Переменные могут быть настроены в определенной степени в каждой области, и области не влияют друг на друга. Переменные с одинаковыми именами являются нижними уровнями.Объявления, такие как область действия, имеют приоритет над областями верхнего уровня и т. д. Они согласуются со структурой области действия таких языков, как java и JavaScript.

Разница в том, что частота использования ExcelUtil намного выше, чем у RunnerUtil. Первоначальное намерение написать RunnerUtil также для этого экспорта ExcelUtil. Сначала я подумал о встроенном механизме сценариев Java (ScriptEngine), но эффективность встроенного скриптового движка слишком низкая, а объем данных чуть больше (не обязательно слишком большой) и застревает напрямую (так плевать не должно, но реально не подходит для этой сцены). Тем не менее, RunnerUtil имеет независимые и полные функции и хорошую производительность, может запускать различные сложные строковые формулы Java и может использоваться отдельно.

Введение

  1. Используйте ExcelUtil перед первой подготовкой данных, и никаких особых требований к форматированию, может быть любой тип данных Java, такой как Collection, Iterable, Iterator (режим итераторов, который вдохновлен полученным, когда интервью может использоваться большой экспорт Excel, хотя последний не прошел, но кто еще хотел бы поблагодарить интервьюера!), карта, массив, POJO, номер и так далее.

  2. Второй шаг — выполнить «программирование аннотаций» для метода создания местоположения рабочей книги — да, функция аннотации Java очень мощная, и ее можно использовать как «язык программирования» только в Java (фактически, простой анализ написано.В плане снаряжения закрой лицо и улыбнись).

// 在什么地方导出,就在那个方法上进行声明式“注解编程”
// 首先要声明这是一个 Excel,用 type 指定是 xls 或者 xlsx
@TableExcel(type = TableExcel.Type.XLS, value = {
    /* 
     * value 包含的是所有 sheet 页的信息
     * 自 sheet 向下,每个标签可以判断、循环等
     * 用 sheetName 指定 sheet 名
     * 为什么要用单引号再多包裹一层呢?详见 RunnerUtil
     * 因为这里面的所有内容都是用 RunnerUtil 解析的,需要符合它的格式
     */ 
    @TableSheet(sheetName = "'人员信息'", value = {
        /*
         * 在这儿声明了一个名为 names 的数组,用作标题
         */
        @TableRow(var = "names = {'序号','姓名','性别','年龄','电话','家庭住址', '备注'}", value = {
            /*
             * 这儿用了迭代,迭代 row 上声明的 names
             * 这个迭代将按 names 的内容生成对应数量和内容的 cell 单元格
             */
            @TableCell(var = "name:names", value = name)
        }),
        /*
         * 上面 cell 的迭代用的是冒号,这儿用了 in,二者意义完全一样
         * 支持 in 完全是为了向灵感的来源(前端)致敬
         * 但是 in 并不是关键字,仍可作为普通变量
         * 不同的是 in 的两端至少各有一个空格
         * 可迭代的数据类型一会儿详细介绍
         */
        @TableRow(var = "($rowData, index) in collect", value = {
            @TableCell("index + 1"), // 序号
            @TableCell("$rowData.name"), // 姓名
            @TableCell("$rowData.sex"), // 性别
            @TableCell("$rowData.age"), // 年龄
            @TableCell("$rowData.mobile"), // 电话
            @TableCell("$rowData.address"), // 家庭住址
            // 最后这个对于上面的备注,这儿有个 when,只有 index == 0 才创建这个单元格
            // 同时这儿还用到了并合并行,另外 colspan 是合并列
            @TableCell(when = "index == 0", rowspan = "data.size()")
        })
    })
})
public Workbook exportExcel(Object data){
    /*
     * 写好注解后只需要调用这个方法便可得到一个 Workbook
     * 在哪儿调用 render 方法就在哪儿写上面那些注解
     */
    return ExcelUtil.render(data);
}
  • ExcelUtil.render(data); Итерируемые данные in (или двоеточие :) при рендеринге:
  1. число (целое), например, var = "$item in 10", цикл десять раз;
  2. String, повторяет каждый символ в строке, но поскольку RunnerUtil не поддерживает данные типа char, он фактически повторяет одну строку символов.
  3. Коллекция, Итерируемый, Список, Набор и т.д.
  4. Map, перебирает значение каждой пары ключ-значение;
  5. POJO, обычный объект Java выполняет итерацию по имени поля и повторяет значение поля
  • Возвращаемое значение выражения, следующего за when, должно быть логического типа.
  • Возвращаемое значение выражений colspan и rowspan должно иметь тип int.
  • Другие значения heigit, width и т. д. также должны иметь тип int.

Эффект:

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/11/28/16758316e9699b4d~tplv-t2oaga2asx-image.image

  • Сгенерированы соответствующие визуализации Excel

https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/11/28/16758316e9782ec1~tplv-t2oaga2asx-image.image

Тестирование производительности

Вставьте таблицу теста производительности Excel с 10 столбцами, экспортированную этим инструментом (собственная среда i7-8700K 16G Win10)

Количество строк (10 000 строк) Время генерации данных (мс) Время записи в файл (мс) Общее время (мс)
100 6,182 5,565 11,747
300 14,800 16,693 31,493
500 25,876 27,317 53,193
700 36,121 42,171 78,292
999 53,532 54,745 108,277
4000 240,453 271,832 512,285
6000 366,987 423,351 790,338
8000 528,654 498,490 1,027,144

Из этих данных видно, что по мере увеличения объема данных связь между временем и данными имеет положительную корреляцию, которая близка к линейной зависимости.Для создания рабочей книги с 1 миллионом строк данных требуется 6 с, а общее время составляет 12 с, что соответствует требованиям времени в обычных бизнес-сценариях.

другие инструкции

  • Когда объем данных Excel превышает 1,5 миллиона строк, не рекомендуется использовать формат xls (эти данные должны быть разными на разных машинах, xls 1,5 миллиона строк этой машины можно экспортировать нормально, а 1,8 миллиона строк ООМ);
  • Когда объем данных превышает 5 миллионов строк (зависит от среды), значение типа TableExcel должно быть SUPER (type = TableExcel.Type.SUPER), а SUPER соответствует формату xlsx, но SUPER используется для поддержки больших данных. экспорт;
  • 1,5 миллиона строк и 5 миллионов строк — это нормальные ограничения для бизнеса.
  • В настоящее время поддерживает только экспорт, а не импорт.

ExcelUtil # GitHub # star ~!

Введение в использование RunnerUtil