Я собираюсь, я все еще читаю и пишу в Excel, это слишком неэффективно!

Java

предисловие

Адрес блога:studyidea.cn/easyexcel

Недавно читатель Сяо Х отправил личное сообщение Сяо Хэю:

Маленький черный брат, недавно я отвечал за разработку платформы отчетов компании, и мне нужно экспортировать отчет в Excel. Каждый раз, когда вы используете POI для разработки, вам приходится писать длинный кусок кода, несколько раз генерация завершается неудачно, потому что не добавляется пустое суждение. Я хочу спросить вас, есть ли более эффективный способ читать и писать в Excel?

Развивающиеся студенты с POI могут иметь этот опыт, каждый раз, когда вы должны написать код, последний код выглядит следующим образом:

Этот код вонючий и длинный? Когда количество полей велико, случайно легко писать ошибки. Xiaohei все еще помнит, что когда я использовал POI, чтобы экспортировать Excel с более чем 20 полями, я продолжал копировать и вставлять его, и номер линии случайно написал неправильно. Это была грустная вещь.

Сегодня Сяо Хей порекомендует проект с открытым исходным кодом от Али.EasyExcel», заставьте всех попрощаться с длинным и вонючим кодом выше и полностью решить эту проблему.

EasyExcel

EasyExcelЭто проект с открытым исходным кодом, созданный Али.Из названия видно, что этот проект предназначен для облегчения работы с Excel. Кроме тогоEasyExcelТакже решена проблема переполнения памяти poi, исправлены некоторые ошибки в некоторых случаях параллелизма.

адрес гитхаба:GitHub.com/Alibaba/EAS…

К тому времени, как Сяохэй написал статью, он уже13.6kзвездные данные, видно, что этот проект по-прежнему очень популярен.

Без лишних слов перейдем непосредственно к собственно боевой ссылке исходного кода.

Сначала нам нужно импортироватьEasyExcelпом зависимости:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.6</version>
</dependency>

Рекомендуется использовать официальную версию выше 2.0 и не использовать старую версию 1.0. API, используемые двумя, очень разные. Кроме тогоbetaВ версии могут быть некоторые ошибки, пожалуйста, используйте ее с осторожностью.

общий путь

Одна строка кода для создания Excel

// 写法1
String fileName = "temp/" + "test" + System.currentTimeMillis() + ".xlsx";
EasyExcel.write(fileName)
        .head(head())// 设置表头
        .sheet("模板")// 设置 sheet 的名字
        // 自适应列宽
        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
        .doWrite(dataList());// 写入数据

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

В приведенном выше коде используется стратегия адаптивной ширины столбца.

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

создать заголовок

/**
 * 创建表头,可以创建复杂的表头
 *
 * @return
 */
private static List<List<String>> head() {
    List<List<String>> list = new ArrayList<List<String>>();
    // 第一列表头
    List<String> head0 = new ArrayList<String>();
    head0.add("第一列");
    head0.add("第一列第二行");
    // 第二列表头
    List<String> head1 = new ArrayList<String>();
    head1.add("第一列");
    head1.add("第二列第二行");
    // 第三列
    List<String> head2 = new ArrayList<String>();
    head2.add("第一列");
    head2.add("第三列第二行");
    list.add(head0);
    list.add(head1);
    list.add(head2);
    return list;
}

Каждый из вышеперечисленныхList<String>представлятьстрока, все данные в коллекции будут последовательно записываться в каждую строку этого столбца. Если содержимое одинакового количества строк в каждом столбце одинаково, ячейки будут объединены автоматически. С помощью этого правила мы создаем сложные заголовки.

Заголовок финальной таблицы создается следующим образом:

записать данные тела таблицы

private static List dataList() {
    List<List<Object>> list = new ArrayList<List<Object>>();
    for (int i = 0; i < 10; i++) {
        List<Object> data = new ArrayList<Object>();
        data.add("点赞+" + i);
        // date 将会安装 yyyy-MM-dd HH:mm:ss 格式化
        data.add(new Date());
        data.add(0.56);
        list.add(data);
    }
    return list;
}

Затем также используются данные тела таблицы.List<List<Object>>Однако он отличается от руководителей.

каждыйList<Object>представлятьодна линияdata, данные будут записаны в каждый столбец по порядку.

данные в сбореEasyExcelВывод будет преобразован в соответствии с форматом по умолчанию, напримерdateтип данных будетyyyy-MM-dd HH:mm:ssформат.

Если вам нужно преобразовать его в другие форматы, рекомендуется отформатировать данные непосредственно в строку и добавить ее в список вместо передачиEasyExcelконвертировать.

Окончательный эффект выглядит следующим образом:

Прочитав это, вы хотите испытать это прямо сейчас? Подождите, приведенное выше использование все еще немного громоздко, используйтеEasyExcelТакже быстрее. Мы можем использовать метод аннотации без вручную установки заголовка и тела.

Способ аннотаций

Код Excel, сгенерированный методом аннотации, выглядит следующим образом:

String fileName = "temp/annotateWrite" + System.currentTimeMillis() + ".xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel
        .write(fileName, DemoData.class)
        .sheet("注解方式")
        .registerWriteHandler(createTableStyle())// Excel 表格样式
        .doWrite(data());

Код здесь примерно такой же, как и выше, за исключением того, что он должен быть вwriteметод передан вDemoDataтип данных.EasyExcelбудет основываться наDemoDataТипы автоматически генерируют заголовки.

Здесь мы смотрим наDemoDataЧто именно находится внутри этого класса?

@ContentRowHeight(30)// 表体行高
@HeadRowHeight(20)// 表头行高
@ColumnWidth(35)// 列宽
@Data
public class DemoData {
    /**
     * 单独设置该列宽度
     */
    @ColumnWidth(50)
    @ExcelProperty("字符串标题")
    private String string;
    /**
     * 年月日时分秒格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty(value = "日期标题")
    private Date date;
    /**
     * 格式化百分比
     */
    @NumberFormat("#.##%")
    @ExcelProperty("数字标题")
    private Double doubleData;
    @ExcelProperty(value = "枚举类",converter = DemoEnumConvert.class)
    private DemoEnum demoEnum;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

DemoDataпросто обычныйPOJOкласс, используемый вышеExayExcelродственное понимание,ExayExcelТип поля и связанные с ним аннотации будут прочитаны посредством отражения, а Excel будет сгенерирован напрямую.

ExayExcel предоставляет связанные классы решений для непосредственного определения модели данных Excel:

  • @ExcelPropertyОпределяет текущее поле соответствует Excel в строке, атрибут внутреннего значения указывает имя заголовка столбца
  • @ExcelIgnoreПо умолчанию все поля будут сопоставлены с Excel. При добавлении этой аннотации это поле будет игнорироваться.
  • @ContentRowHeightУкажите высоту строки тела таблицы
  • @HeadRowHeightУкажите высоту строки заголовка
  • @ColumnWidthОпределяет ширину столбца

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

  • @DateTimeFormat
  • @NumberFormat

Кроме того, мы можем настроить схему преобразования формата, которую необходимо реализоватьConverterИли родственные методы могут быть.

public class DemoEnumConvert implements Converter<DemoEnum> {
    @Override
    public Class supportJavaTypeKey() {
        return DemoEnum.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * excel 转化为 java 类型,excel 读时将会被调用
     * @param cellData
     * @param contentProperty
     * @param globalConfiguration
     * @return
     * @throws Exception
     */
    @Override
    public DemoEnum convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return null;
    }

    /**
     * java 类型转 excel 类型,excel 写时将会被调用
     * @param value
     * @param contentProperty
     * @param globalConfiguration
     * @return
     * @throws Exception
     */
    @Override
    public CellData convertToExcelData(DemoEnum value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData(value.getDesc());
    }
}

Наконец, нам также нужно@ExcelPropertyиспользовать в аннотацияхconverterУкажите пользовательскую схему преобразования формата.

Он используется следующим образом:

@ExcelProperty(value = "枚举类",converter = DemoEnumConvert.class)
private DemoEnum demoEnum;

Наконец, давайте запустим его и посмотрим, как на самом деле работает Excel:

Во всяком случае, это все еще работает.

Кстати, стиль таблицы стилей по умолчанию не такой, этот эффект потому, что мы находимся вregisterWriteHandlerПользовательский стиль задается в методе, а конкретный код выглядит следующим образом:

/***
 * 设置 excel 的样式
 * @return
 */
private static WriteHandler createTableStyle() {
    // 头的策略
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    // 背景设置为红色
    headWriteCellStyle.setFillForegroundColor(IndexedColors.PINK.getIndex());
    // 设置字体
    WriteFont headWriteFont = new WriteFont();
    headWriteFont.setFontHeightInPoints((short) 20);
    headWriteCellStyle.setWriteFont(headWriteFont);
    // 内容的策略
    WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
    // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定
    contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
    // 背景绿色
    contentWriteCellStyle.setFillForegroundColor(IndexedColors.LEMON_CHIFFON.getIndex());

    WriteFont contentWriteFont = new WriteFont();
    // 字体大小
    contentWriteFont.setFontHeightInPoints((short) 20);
    contentWriteCellStyle.setWriteFont(contentWriteFont);
    // 设置边框的样式
    contentWriteCellStyle.setBorderBottom(BorderStyle.DASHED);
    contentWriteCellStyle.setBorderLeft(BorderStyle.DASHED);
    contentWriteCellStyle.setBorderRight(BorderStyle.DASHED);
    contentWriteCellStyle.setBorderTop(BorderStyle.DASHED);

    // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
    HorizontalCellStyleStrategy horizontalCellStyleStrategy =
            new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    return horizontalCellStyleStrategy;
}

Примечания по использованию

проблема конфликта пои

теоретически в настоящее времяeasyexcelСовместимость с poi-поддержкой3.17,4.0.1,4.1.0Все более новые версии, но если в проекте ранее использовалась более старая версия poi, некоторые классы были удалены из-за внутренних настроек кода poi, поэтому прямой запуск, скорее всего, вызовет следующее исключение:

  • NoSuchMethodException
  • ClassNotFoundException
  • NoClassDefFoundError

Следовательно, необходимо использоватьОбратите внимание на версию пои в проекте юнити.

Пользовательская высота строки и ширина столбца в режиме без аннотации

Более проблематично настроить высоту строки и ширину столбца в методе без аннотаций, и в настоящее время нет прямого ввода настроек. Проверены проблемы, связанные с github, ответ разработчика должен быть реализованWriteHandlerИнтерфейс, настраиваемый стиль таблицы.

Суммировать

В этой статье в основном рассказывается о мощных функциях Amway EasyExcel, рассказывается о двух способах создания Excel в EasyExcel и демонстрируются соответствующие примеры кодов.EasyExcelПомимо записи, разумеется, также поддерживает функцию быстрого чтения и чтения Excel, о которой здесь подробно рассказывать не будем. На Github есть множество соответствующих примеров документации, и вы можете обратиться к ним самостоятельно.

Адрес документа на гитхабе:alibaba-easyexcel.github.io/index.html

Reference

  1. GitHub.com/Alibaba/EAS…
  2. alibaba-easyexcel.github.io/index.html
  3. cloud.Tencent.com/developer/ ах…

Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: программа для общения, ежедневный толчок галантерейных товаров. Если вам интересен мой рекомендуемый контент, вы также можете подписаться на мой блог:studyidea.cn

公号底图