Springboot exporta el método EXCEL (si es por ejemplo)

Este artículo presenta el método para exportar los datos que se muestran en la interfaz a un archivo de tabla EXCEL en springboot. El método proviene de Ruoyi Ruoyi.

contenido

1. Configuración relacionada

1.1 Anotaciones para la configuración

1.2 Agregar campos

1.3 Añadir anotaciones

2. Clase de método de Excel

Hoja de ruta del método de exportación

2.1 Definir campos variables

2.2 Capa de controlador

2.3 exportExcel (lista de lista, nombre de hoja de cadena) 方法

2.3.1 método init (inicialización)

2.3.2 Llamar al método creteExcelField()

2.3.3 crear libro de trabajo ()

2.4 exportarExcel()


Hoja de ruta del método de exportación

1. Configuración relacionada

1.1 Introducción al entorno

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>

Hay muchas configuraciones al exportar datos a archivos EXCEL, como altura de fila, formato de fecha, tipo de exportación, etc. Para lograr la reutilización del código y la diversidad funcional, se deben usar métodos de anotación para diferentes clases de entidades, diferentes tipos de datos para la configuración individual .

1.2 Anotaciones para la configuración

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
   
   

@Rentention se usa para definir cómo se mantiene la anotación, es decir, el ciclo de vida

RetentionPolicy.SOURCE Las anotaciones solo se conservan en los archivos de origen, y cuando los archivos Java se compilan en archivos de clase, las anotaciones se descartan;
RetentionPolicy.CLASS Las anotaciones se mantienen en el archivo de clase, pero se abandonan cuando la JVM carga el archivo de clase, que es el ciclo de vida predeterminado;
RetentionPolicy.RUNTIME La anotación no solo se guarda en el archivo de clase, sino que aún existe después de que la JVM carga el archivo de clase;

@Target se usa para describir el alcance del uso de la anotación, donde se puede usar la anotación descrita, parámetros

1.3 Agregar campos

La configuración requerida para la tabla EXCEL

P.ej:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
   
     /**
     * 导出时在excel中排序
     */
    public int sort() default Integer.MAX_VALUE;

    /**
     * 导出到Excel中的名字.
     */
    public String name() default "";

    /**
     * 日期格式, 如: yyyy-MM-dd
     */
    public String dateFormat() default "";

    /**
     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";

    /**
     * 读取内容转表达式 (如: 0=男,1=女,2=未知)
     */
    public String readConverterExp() default "";

    /**
     * 分隔符,读取字符串组内容
     */
    public String separator() default ",";

    /**
     * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
     */
    public int scale() default -1;

    /**
     * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
     */
    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;

    /**
     * 导出类型(0数字 1字符串)
     */
    public ColumnType cellType() default ColumnType.STRING;

    /**
     * 导出时在excel中每个列的高度 单位为字符
     */
    public double height() default 14;

    /**
     * 导出时在excel中每个列的宽 单位为字符
     */
    public double width() default 16;

    /**
     * 文字后缀,如% 90 变成90%
     */
    public String suffix() default "";

    /**
     * 当值为空时,字段的默认值
     */
    public String defaultValue() default "";

    /**
     * 提示信息
     */
    public String prompt() default "";

    /**
     * 设置只能选择不能输入的列内容.
     */
    public String[] combo() default {};

    /**
     * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    public boolean isExport() default true;

    /**
     * 另一个类中的属性名称,支持多级获取,以小数点隔开
     */
    public String targetAttr() default "";

    /**
     * 是否自动统计数据,在最后追加一行统计数据总和
     */
    public boolean isStatistics() default false;

    /**
     * 导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
     */
    Align align() default Align.AUTO;

    public enum Align
    {
        AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
        private final int value;

        Align(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

    /**
     * 字段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    Type type() default Type.ALL;

    public enum Type
    {
        ALL(0), EXPORT(1), IMPORT(2);
        private final int value;

        Type(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

    public enum ColumnType
    {
        NUMERIC(0), STRING(1), IMAGE(2);
        private final int value;

        ColumnType(int value)
        {
            this.value = value;
        }

        public int value()
        {
            return this.value;
        }
    }

La configuración específica se determina según sus propias necesidades, y el tipo de enumeración se utiliza para juzgar el método de uso más adelante.

1.4 Añadir anotaciones

Luego, debe agregar anotaciones a los campos de las clases de entidad que deben exportarse

P.ej:

    /** 订单编号 */
    @Excel(name = "订单编号")
    private String orderId;

    /** 客户编号 */
    @Excel(name = "客户编号")
    private Long customerId;

    /** 姓名 */
    @Excel(name = "姓名")
    private String Person;

    @JsonFormat(pattern = "yyyy-MM-dd")
    @Excel(name = "时间", width = 30, dateFormat = "yyyy-MM-dd")
    private Date Time;

2. Clase de método de Excel

Hoja de ruta del método de exportación

2.1 Definir campos variables

La configuración general de la tabla debe agregarse en esta clase.

/**
 * Excel相关处理
 * 
 * @author ruoyi
 */
public class ExcelUtil<T>
{
    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);

    /**
     * Excel sheet最大行数,默认65536
     */
    public static final int sheetSize = 65536;

    /**
     * 工作表名称
     */
    private String sheetName;

    /**
     * 导出类型(EXPORT:导出数据;IMPORT:导入模板)
     */
    private Type type;

    /**
     * 工作薄对象
     */
    private Workbook wb;

    /**
     * 工作表对象
     */
    private Sheet sheet;

    /**
     * 样式列表
     */
    private Map<String, CellStyle> styles;

    /**
     * 导入导出数据列表
     */
    private List<T> list;

    /**
     * 注解列表
     */
    private List<Object[]> fields;

    /**
     * 最大高度
     */
    private short maxHeight;

    /**
     * 统计列表
     */
    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
    
    /**
     * 数字格式
     */
    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
    
    /**
     * 实体对象
     */
    public Class<T> clazz;

    public ExcelUtil(Class<T> clazz)
    {
        this.clazz = clazz;
    }

Diferencia entre libro de trabajo y nómina:

Después de crear un nuevo Excel, el sistema usa de forma predeterminada un libro de trabajo, en el que generalmente hay tres hojas de trabajo, hoja1, hoja2 y hoja3. Es así de simple. Un libro de trabajo puede contener hasta 255 hojas de trabajo y una hoja puede tener hasta 65536 filas

2.2 Capa de controlador

En la capa del controlador, primero debe consultar los datos, luego inicializar ExcelUtil y llamar al método

List<Order> list=service.selectOrder(ids);  

ExcelUtil<Order> util = new ExcelUtil<Order>(Order.class);
 
return util.exportExcel(list, "Excel数据表");

2.3 exportExcel(List<T> list, String sheetName)方法

Ingrese al método exportExcel(List<T> list, String sheetName)

/**
     * 对list数据源将其里面的数据导入到excel表单
     * 
     * @param list 导出数据集合
     * @param sheetName 工作表的名称
     * @return 结果
     */
    public AjaxResult exportExcel(List<T> list, String sheetName)
    {
        this.init(list, sheetName, Type.EXPORT);
        return exportExcel();
    }

2.3.1 método init (inicialización)

Como puede ver, primero se llamará a un método init (inicialización) y se pasará Type.EXPORT como datos de exportación

public void init(List<T> list, String sheetName, Type type)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list = list;
        this.sheetName = sheetName;
        this.type = type;
        createExcelField();
        createWorkbook();
    }

La lógica es asignar a la variable los datos exportados y el nombre de archivo requeridos, así como el Tipo que distingue entre exportar e importar.

2.3.2 Llamar al método creteExcelField()

código general

    /**
     * 得到所有定义字段
     */
    private void createExcelField()
    {   this.fields = new ArrayList<Object[]>();
        List<Field> tempFields = new ArrayList<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        for (Field field : tempFields)
        {
            // 单注解
            if (field.isAnnotationPresent(Excel.class))
            {
                putToField(field, field.getAnnotation(Excel.class));
            }

            // 多注解
            if (field.isAnnotationPresent(Excels.class))
            {
                Excels attrs = field.getAnnotation(Excels.class);
                Excel[] excels = attrs.value();
                for (Excel excel : excels)
                {
                    putToField(field, excel);
                }
            }
        }
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
        this.maxHeight = getRowHeight();
    }

Introducción línea por línea

/**
         * fields字段定义为存储所有注解的字段,为Object[]的数组
         * */
        this.fields = new ArrayList<Object[]>();

        List<Field> tempFields = new ArrayList<>();
/**
 * clazz字段存储的是实体类字段
* clazz.getSuperclass()为得到实体类的父类方法
* getDeclaredFields()为反射中的方法,获得某个类的所有声明的字段,即包括public,private            
* 和proteced,
* 但是不包括父类的申明字段,所以先获取了父类的声明字段,再获取当前类的声明字段
*
* Array.List()是将数组转化成List集合的方法,用此方法得到的List的长度是不可改变的,
*/

tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
 /**
         *遍历得到的所有字段
         */
        for (Field field : tempFields)
        {
            // 单注解
            /**
             * isAnnotationPresent() 判断该字段是否标注该注解
             */
            if (field.isAnnotationPresent(Excel.class))
            {
                /**
                 * 如果标注有@Excel注解,则调用该方法
                 */
                putToField(field, field.getAnnotation(Excel.class));
            }

            // 多注解
            /**
             * 如果字段标注有多个注解,则会进入循环
             */
            if (field.isAnnotationPresent(Excels.class))
            {
                Excels attrs = field.getAnnotation(Excels.class);
                Excel[] excels = attrs.value();
                for (Excel excel : excels)
                {
                    putToField(field, excel);
                }
            }
        }
  /**
         * 根据注解中定义的顺序int大小来排序,默认为Integer.MAX_VALUE;
         */
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());

        this.maxHeight = getRowHeight();

que llama al  método putToField()

Coloque la suma de los campos y los parámetros de anotación obtenidos por el ciclo si en fields<Object[]>, Object[0] es el campo y Object[1] es el parámetro de anotación

/**
     * 放到字段集合中
     */
    private void putToField(Field field, Excel attr)
    {
        if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
        {
            this.fields.add(new Object[] { field, attr });
        }
    }

y el método getRowHeight()

Compare los valores de altura en los parámetros de anotación uno por uno y tome el valor máximo como la altura de fila final

 /**
     * 根据注解获取最大行高
     */
    public short getRowHeight()
    {
        double maxHeight = 0;
        for (Object[] os : this.fields)
        {
            Excel excel = (Excel) os[1];
            maxHeight = maxHeight > excel.height() ? maxHeight : excel.height();
        }
        return (short) (maxHeight * 20);
    }

2.3.3 crear libro de trabajo ()

El último paso del método inti, llamar al método createWorkbook()

  /**
     * 创建一个工作簿
     */
    public void createWorkbook()
    {
        this.wb = new SXSSFWorkbook(500);
    }

2.4 exportarExcel()

Ver la hoja de ruta

Después de llamar al método init, llame al método exportExcel sin parámetros

    /**
     * 对list数据源将其里面的数据导入到excel表单
     *
     * @return 结果
     */
    public AjaxResult exportExcel()
    {
        OutputStream out = null;
        try
        {
            // 取出一共有多少个sheet.
            double sheetNo = Math.ceil(list.size() / sheetSize);
            for (int index = 0; index <= sheetNo; index++)
            {
                createSheet(sheetNo, index);

                // 产生一行
                Row row = sheet.createRow(0);
                int column = 0;
                // 写入各个字段的列头名称
                for (Object[] os : fields)
                {
                    Excel excel = (Excel) os[1];
                    this.createCell(excel, row, column++);
                }
                if (Type.EXPORT.equals(type))
                {
                    fillExcelData(index, row);
                    addStatisticsRow();
                }
            }
            String filename = encodingFilename(sheetName);
            out = new FileOutputStream(getAbsoluteFile(filename));
            wb.write(out);
            return AjaxResult.success(filename);
        }
        catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
            throw new CustomException("导出Excel失败,请联系网站管理员!");
        }
        finally
        {
            if (wb != null)
            {
                try
                {
                    wb.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
            if (out != null)
            {
                try
                {
                    out.close();
                }
                catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        }
    }

Supongo que te gusta

Origin blog.csdn.net/xsj5211314/article/details/123917816
Recomendado
Clasificación