首页 > 其他分享 >SpringBoot自定义注解导出Excel

SpringBoot自定义注解导出Excel

时间:2023-12-02 14:11:52浏览次数:43  
标签:Map return SpringBoot 自定义 Excel private import xssfWorkbook String

先定义一个注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelHander {
    String value() default "";
    String linkFiled() default "";
    CellType cellType() default CellType.STRING;
}

 

导出工具类

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.lazydong.pgsql.ExcelHander;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFHyperlink;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;

@SuppressWarnings({"unchecked", "rawtypes"})
public class ExcelUtil {
    private XSSFWorkbook xssfWorkbook;
    private String excelName;
    private XSSFCellStyle defHanderCellStyle;
    private XSSFCellStyle defContentCellStyle;
    private final List<ExcelBuilder> excelBuilderList = new ArrayList<>();

    public static ExcelUtil create() {
        ExcelUtil excelUtil = new ExcelUtil();
        excelUtil.xssfWorkbook = new XSSFWorkbook();
        return excelUtil;
    }

    public ExcelUtil setExcelName(String excelName) {
        this.excelName = excelName;
        return this;
    }

    public void write(String path) {
        System.out.println("正在生成" + excelName);
        verifyExcelHander();
        BufferedOutputStream outputStream = FileUtil.getOutputStream(path);
        try {
            defCellStyle(xssfWorkbook);
            for (ExcelBuilder excelBuilder : excelBuilderList) {
                writeSheet(excelBuilder, xssfWorkbook);
            }
            xssfWorkbook.write(outputStream);
        } catch (IOException exception) {
            exception.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException exception) {
                    exception.printStackTrace();
                }
            }
            if (xssfWorkbook != null) {
                try {
                    xssfWorkbook.close();
                } catch (IOException exception) {
                    exception.printStackTrace();
                }
            }
        }
    }

    private void defCellStyle(XSSFWorkbook xssfWorkbook) {
        defHanderCellStyle = xssfWorkbook.createCellStyle();
        defHanderCellStyle.setFillBackgroundColor(IndexedColors.BLUE.getIndex());
        defHanderCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        defContentCellStyle = xssfWorkbook.createCellStyle();
    }

    private void verifyExcelHander() {
        for (ExcelBuilder excelBuilder : excelBuilderList) {
            Class aClass = excelBuilder.getDataClass();
            Map<String, Field> otherFieldMap = excelBuilder.getOtherFieldMap();
            List<ExcelHander> columnExcelHander = excelBuilder.getColumnExcelHander();
            List<Field> columnField = excelBuilder.getColumnField();
            Map<String, Field> allFieldMap = ReflectUtil.getFieldMap(aClass);
            boolean hasExcelHander = false;
            Field[] fields = ReflectUtil.getFields(aClass);
            for (Field field : fields) {
                if (!field.isAnnotationPresent(ExcelHander.class)) {
                    continue;
                }
                if (!hasExcelHander) {
                    hasExcelHander = true;
                }
                ExcelHander annotation = field.getAnnotation(ExcelHander.class);
                String linkFiledKey = annotation.linkFiled();
                if (StrUtil.isNotBlank(linkFiledKey)) {
                    if (!allFieldMap.containsKey(linkFiledKey)) {
                        throw new RuntimeException("指定的链接字段有误");
                    }
                    Field linkFiled = allFieldMap.get(linkFiledKey);
                    if (linkFiled.isAnnotationPresent(ExcelHander.class)) {
                        throw new RuntimeException("指定的链接字段上不允许有ExcelHander注解");
                    }
                    otherFieldMap.put(linkFiled.getName(), linkFiled);
                }
                columnExcelHander.add(annotation);
                columnField.add(field);
            }
            if (!hasExcelHander) {
                throw new RuntimeException("没有找到ExcelHander注解");
            }
        }
    }

    private void writeSheet(ExcelBuilder excelBuilder, XSSFWorkbook xssfWorkbook) {
        String sheetName = excelBuilder.getSheetName();
        XSSFSheet xssfSheet = StrUtil.isNotBlank(sheetName)
                ? xssfWorkbook.createSheet(sheetName) : xssfWorkbook.createSheet();
        XSSFRow xssfHanderRow = xssfSheet.createRow(0);
        List<ExcelHander> columnExcelHander = excelBuilder.getColumnExcelHander();
        // 写表头
        for (int columnIndex = 0; columnIndex < columnExcelHander.size(); columnIndex++) {
            XSSFCell xssfRowCell = xssfHanderRow.createCell(columnIndex);
            ExcelHander excelHander = columnExcelHander.get(columnIndex);
            String value = excelHander.value();
            xssfRowCell.setCellStyle(defHanderCellStyle);
            xssfRowCell.setCellType(CellType.STRING);
            xssfRowCell.setCellValue(value);
        }
        // 写内容
        Map<String, Field> otherFieldMap = excelBuilder.getOtherFieldMap();
        List<Field> columnField = excelBuilder.getColumnField();
        List<Object> exportDataList = excelBuilder.getExportDataList();
        // 先判断是否有自定义样式
        Map<String, XSSFCellStyle> fieldCellStyleMap = excelBuilder.getFieldCellStyleMap();
        Map<String, XSSFCellStyle> customCellStyleMap = excelBuilder.getCustomCellStyleMap();
        Map<String, BiFunction<String, Map<String, XSSFCellStyle>, XSSFCellStyle>> customConditionalMap = excelBuilder.getCustomConditionalMap();
        int rowIndex = 1;
        for (Object data : exportDataList) {
            XSSFRow xssfRow = xssfSheet.createRow(rowIndex);
            rowIndex++;
            for (int columnIndex = 0; columnIndex < columnExcelHander.size(); columnIndex++) {
                XSSFCell xssfRowCell = xssfRow.createCell(columnIndex);
                // 单元格判断其他类型
                ExcelHander excelHander = columnExcelHander.get(columnIndex);
                CellType cellType = excelHander.cellType();
                if (Objects.equals(CellType.BLANK, cellType)) {
                    xssfRowCell.setCellType(CellType.BLANK);
                    String linkFiledKey = excelHander.linkFiled();
                    Field linkFiled = otherFieldMap.get(linkFiledKey);
                    Object linkValue = ReflectUtil.getFieldValue(data, linkFiled);
                    XSSFHyperlink hyperlink = xssfWorkbook.getCreationHelper().createHyperlink(HyperlinkType.URL);
                    hyperlink.setAddress(String.valueOf(linkValue));
                    xssfRowCell.setHyperlink(hyperlink);
                } else {
                    xssfRowCell.setCellType(CellType.STRING);
                }
                // 单元格赋值
                Field field = columnField.get(columnIndex);
                String fieldValue = String.valueOf(ReflectUtil.getFieldValue(data, field));
                xssfRowCell.setCellValue(fieldValue);
                // 单元格样式  优先级为,字段统一样式 > 根据字段的值来判断样式
                String fieldName = field.getName();
                if (fieldCellStyleMap.containsKey(fieldName)) {
                    // 这个字段存在 字段统一样式
                    XSSFCellStyle xssfCellStyle = fieldCellStyleMap.get(fieldName);
                    xssfRowCell.setCellStyle(xssfCellStyle);
                    continue;
                }

                if (customCellStyleMap.isEmpty()) {
                    // 根据字段的值来判断样式 设置为默认样式
                    xssfRowCell.setCellStyle(defContentCellStyle);
                    continue;
                }
                // 存在根据字段的值来判断样式
                if (customConditionalMap.containsKey(fieldName)) {
                    BiFunction<String, Map<String, XSSFCellStyle>, XSSFCellStyle> customConditionalBiFunction = customConditionalMap.get(fieldName);
                    XSSFCellStyle cellStyle = customConditionalBiFunction.apply(fieldValue, customCellStyleMap);
                    if (cellStyle != null) {
                        xssfRowCell.setCellStyle(cellStyle);
                        continue;
                    }
                    xssfRowCell.setCellStyle(defContentCellStyle);
                } else {
                    xssfRowCell.setCellStyle(defContentCellStyle);
                }
            }
        }
    }


    public <T> ExcelBuilder<T> sheetBuilder(Class<T> tClass) {
        ExcelBuilder<T> excelBudiler = new ExcelBuilder<>();
        excelBudiler.setExcelUtil(this);
        excelBudiler.setXSSFWorkbook(this.xssfWorkbook);
        excelBudiler.setDataClass(tClass);
        return excelBudiler;
    }

    public static class ExcelBuilder<T> {
        private ExcelUtil excelUtil;
        private XSSFWorkbook xssfWorkbook;
        private Class<T> dataClass;
        private List<T> exportDataList = new ArrayList<>();
        private String sheetName;
        private final List<ExcelHander> columnExcelHander = new ArrayList<>();
        private final List<Field> columnField = new ArrayList<>();
        private final Map<String, Field> otherFieldMap = new HashMap<>();
        // 自定义样式Map
        private final Map<String, XSSFCellStyle> fieldCellStyleMap = new HashMap<>();
        // 自定义样式Map
        private final Map<String, XSSFCellStyle> customCellStyleMap = new HashMap<>();

        private final Map<String, BiFunction<String, Map<String, XSSFCellStyle>, XSSFCellStyle>> customConditionalMap = new HashMap<>();


        private void setExcelUtil(ExcelUtil excelUtil) {
            this.excelUtil = excelUtil;
        }

        private void setXSSFWorkbook(XSSFWorkbook xssfWorkbook) {
            this.xssfWorkbook = xssfWorkbook;
        }

        public void setDataClass(Class<T> dataClass) {
            this.dataClass = dataClass;
        }

        public ExcelUtil end() {
            excelUtil.excelBuilderList.add(this);
            boolean assignableFrom = ExcelExportModel.class.isAssignableFrom(dataClass);
            if (assignableFrom) {
                // 是接口的实现类,把实现方法也加进来
                ExcelExportModel exportModel = null;
                try {
                    exportModel = (ExcelExportModel) dataClass.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                if (exportModel != null) {
                    exportModel.addFieldCellStyle(this.xssfWorkbook, this.fieldCellStyleMap);
                    exportModel.addCustomConditionalCellStyle(this.xssfWorkbook, this.customCellStyleMap);
                    exportModel.addCustomConditionalByFiled(this.customConditionalMap);
                }
            }
            return excelUtil;
        }

        public ExcelBuilder<T> setSheetName(String sheetName) {
            this.sheetName = sheetName;
            return this;
        }

        /**
         * 添加字段样式
         *
         * @param fieldCellStyleFunction 字段样式
         * @return this
         */
        public ExcelBuilder<T> setFieldCellStyleMap(Function<XSSFWorkbook, Map<String, XSSFCellStyle>> fieldCellStyleFunction) {
            Map<String, XSSFCellStyle> apply = fieldCellStyleFunction.apply(this.xssfWorkbook);
            if (apply != null && !apply.isEmpty()) {
                this.fieldCellStyleMap.putAll(apply);
            }
            return this;
        }

        /**
         * 添加自定义条件
         *
         * @param filedName         字段名
         * @param customConditional 自定义条件
         * @return this
         */
        public ExcelBuilder<T> addCustomConditionalByFiled(String filedName, BiFunction<String, Map<String, XSSFCellStyle>,
                XSSFCellStyle> customConditional) {
            this.customConditionalMap.put(filedName, customConditional);
            return this;
        }

        /**
         * 添加自定义样式
         *
         * @param styleKey 自定义样式Key值
         * @param style    自定义样式
         * @return this
         */
        public ExcelBuilder<T> addCustomCellStyle(String styleKey, XSSFCellStyle style) {
            this.customCellStyleMap.put(styleKey, style);
            return this;
        }

        /**
         * 添加自定义样式
         *
         * @param customCellStyleFunction 自定义样式
         * @return this
         */
        public ExcelBuilder<T> setCustomCellStyle(Function<XSSFWorkbook, Map<String, XSSFCellStyle>> customCellStyleFunction) {
            Map<String, XSSFCellStyle> apply = customCellStyleFunction.apply(this.xssfWorkbook);
            if (apply != null && !apply.isEmpty()) {
                this.customCellStyleMap.putAll(apply);
            }
            return this;
        }

        public ExcelBuilder<T> setExportDataList(List<T> exportDataList) {
            this.exportDataList = exportDataList;
            return this;
        }
        
//        -------------------   get方法 ---------------------


        private Class<T> getDataClass() {
            return dataClass;
        }

        private List<T> getExportDataList() {
            return exportDataList;
        }

        private String getSheetName() {
            return sheetName;
        }

        private List<ExcelHander> getColumnExcelHander() {
            return columnExcelHander;
        }

        private List<Field> getColumnField() {
            return columnField;
        }

        private Map<String, Field> getOtherFieldMap() {
            return otherFieldMap;
        }

        private Map<String, XSSFCellStyle> getFieldCellStyleMap() {
            return fieldCellStyleMap;
        }

        private Map<String, XSSFCellStyle> getCustomCellStyleMap() {
            return customCellStyleMap;
        }

        private Map<String, BiFunction<String, Map<String, XSSFCellStyle>, XSSFCellStyle>> getCustomConditionalMap() {
            return customConditionalMap;
        }
    }
}

 

拓展接口

import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.util.Map;
import java.util.function.BiFunction;

public interface ExcelExportModel {

    /**
     * 设置字段统一样式
     *
     * @param xssfWorkbook xssfWorkbook
     * @param fieldCellStyle String 字段,  XSSFCellStyle 样式
     */
    default void addFieldCellStyle(XSSFWorkbook xssfWorkbook, Map<String, XSSFCellStyle> fieldCellStyle) {
    }

    /**
     * 设置自定义条件样式
     *
     * @param xssfWorkbook xssfWorkbook
     * @param customCellStyle  String样式Key值,XSSFCellStyle 样式
     */
    default void addCustomConditionalCellStyle(XSSFWorkbook xssfWorkbook, Map<String, XSSFCellStyle> customCellStyle) {
    }

    /**
     * 自定义条件
     * 优先级 高于 getCustomConditionalCellStyle
     * 需要基于 addCustomConditionalCellStyle 方法实现
     *
     * @param filed2conditionalMap String字段, BiFunction自定义条件
     */
    default void addCustomConditionalByFiled(Map<String, BiFunction<String, Map<String, XSSFCellStyle>, XSSFCellStyle>> filed2conditionalMap) {
    }

    /**
     * 获取自定义条件样式
     * 需要基于 addCustomConditionalCellStyle 方法实现
     *
     * @param filedName 字段名
     * @param value 字段值
     * @param cellStyleMap 自定义样式Map
     * @return cellStyle
     */
    default XSSFCellStyle getCustomConditionalCellStyle(String filedName, String value, Map<String, XSSFCellStyle> cellStyleMap) {
        return null;
    }
}

 

标签:Map,return,SpringBoot,自定义,Excel,private,import,xssfWorkbook,String
From: https://www.cnblogs.com/Lazydong/p/17871529.html

相关文章

  • 在使用SpringBoot装配mybatis时出现异常
    在使用SpringBoot装配mybatis时出现异常***************************APPLICATIONFAILEDTOSTART***************************Description:FieldstudentServiceincom.example.demo.action.StudentControllerrequiredabeanoftype'com.example.demo.service.Stude......
  • 2023版SpringBoot2 仿B站高性能前端+后端项目开发全流程
    2023版SpringBoot2仿B站高性能前端+后端项目51xuebc+尾缀SpringBoot2仿B站高性能前端+后端项目:打造高效、稳定、可扩展的应用在当今的互联网时期,网站的性能、稳定性和可扩展性成为了权衡一个项目胜利与否的关键要素。本文将引见如何运用SpringBoot2构建一个仿B站的高性能前......
  • springboot 启动命令过长问题处理(Error running 'xxxxApplication': Command line is
      翻译搜索复制......
  • poi 导出Excel Date日期为数字解决方案
    原本直接输入,怎么都是CST格式乱七八糟的。row.createCell(2).setCellValue("盘点日期:");SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");StringbatchDate=sdf.format(batchInfo.getDate());row.createCell(3).setCellVa......
  • Python中使用OpenpyXL操作Excel
    一、安装openpyxl库可以使用命令pipinstallopenpyxl指定版本与切换国内源请查看pyMySQL库那那一文章的详细解答Python中使用PyMySQL库连接MySQL数据库-AiniIT琦玉-博客园(cnblogs.com)二、读取Excel1、读取全部读取excel写法逻辑如下:读取#调用函数,传递文件名#......
  • 在Unity中模块化管理自定义功能和资源
    之前在做Unity项目时,有时会遇到多个项目共用同一部分代码或资源的情况。而当被共用的部分需要更新的时候,手动复制替换非常麻烦,并且可能会有遗漏。对于这个问题,一个很好的解决办法是将可复用的文件打包为自定义包(CustomPackage),使用git等版本控制工具来管理每个包的内容。什么是Pa......
  • springboot创建线程池
    1.线程池的配置:@ConfigurationpublicclassThreadPoolConfig{@Bean(name="myThreadPool")//告诉你这个线程池的名字publicThreadPoolTaskExecutorthreadPoolTaskExecutor(){ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor();ex......
  • springboot如何用jar包启动,同时为不同机房设置不同的配置文件
    1、首先先把配置文件从jar中抽离示例代码:<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.2.0</version><configuration><excludes>......
  • springboot云HIS信息管理系统
    系统功能:为居民建立一份动态、连续、实时、共享的个人电子健康档案,包括家庭和个人信息采集、编辑、常见病诊疗、疾病预防控制服务和健康教育。针对基层医院的业务特点,实现以财务核算为基础,以临床医疗服务为中心的全程信息化管理,主要包括以下业务模块:门诊住院收费管理、以电子病历......
  • 1、自定义上传组件实现动态指定action
    1、增加ynamicAction:String2、修改constuploadImgUrl=ref(props.dynamicAction||import.meta.env.VITE_APP_BASE_API+"/common/upload");//上传的图片服务器地址<el-uploadmultiple:action="uploadImgUrl"3、父组件<el-form-itemlab......