1.导入hutool的工具包

<!--hutool官网Api地址:https://apidoc.gitee.com/loolly/hutool/ -->

<!--maven中央库地址:https://mvnrepository.com/artifact/cn.hutool/hutool-all -->

    <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.2.5</version>
        </dependency>

2.编写工具类

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Workbook;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import io.swagger.annotations.ApiModelProperty;

/**
 * @author 作者 leanolee
 * @version 创建时间:
 * @Explain 类说明:hutool实现excel导出工具类
 */
public class ExportExcelUtil {

    static final Log logger = LogFactory.get(ExportExcelUtil .class);

    /**
     * 方法说明:hutool实现excel导出工具类
     *
     * @author :leanolee
     * @创建时间:
     * @param response
     * @param clazz    导出数据的类型
     * @param list     数据集合
     * @param fileName 文件名称,自动在后面添加当前时间(yyyyMMDDHHmmss)
     * @param removeField 去除字段(不需要导出到文件中的字段)
     * @return void
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static void exportMothod(HttpServletResponse response, Class clazz, List<?> list, String fileName,String[] removeField)
            throws Exception {
        if (CollUtil.isNotEmpty(list)) {
            if (!list.get(0).getClass().equals(clazz)) {
                logger.error("数据类型与传入的集合数据类型不一致!数据类型:{};集合数据类型:{}" ,clazz, list.get(0).getClass());
                throw new Exception("数据类型与传入的集合数据类型不一致!");
            } else {
                try {
                    // 获取输出构造器
                    ExcelWriter writer = ExcelUtil.getWriterWithSheet(fileName);
                    // 获取当前类字段(反射也可以使用hutool工具包里面的相关方法)
                    Field[] fields2 = clazz.getDeclaredFields();
                    // 字段名称集合
                    List<String> fieldNames = new ArrayList<>();
                    // 字段中文名称集合(ApiModelProperty注解的value值)
                    List<String> cnNames = new ArrayList<>();
                    // 时间字段的额列位置
                    for (Field field : fields2) {
                        // 设置属性
                        if (!field.isAccessible()) {
                            field.setAccessible(true);
                        }
                        // 去除序列好和id
                        String fieldName = field.getName();
                        if (!(Arrays.asList(removeField).contains(fieldName))) {
                            fieldNames.add(fieldName);
                            // 判断是否有注解Api

                            /**
                             * 此处判断需要导出的字段方式是使用的swagger的注解作为依据
                             * 如果项目中未使用swgger的注解,可以自定义注解作为依据或者能够作为判断依据的相关表示
                             * 此处除去id字段存在一定的问题,不影响的大局的情况下可以不用考虑
                             * 如果想要除去不必要的字段需要手动编写除去的相关功能
                             **/
                            boolean annotationPresent = field.isAnnotationPresent(ApiModelProperty.class);
                            if (annotationPresent) {
                                ApiModelProperty annotation = field.getAnnotation(ApiModelProperty.class);
                                // 获取注解的值作为导出的表头
                                String name = annotation.value();
                                cnNames.add(name);
                            }
                        } else {
                            //排除字段操作(如果为true,则不设置alias的字段将不被输出)
                            writer.setOnlyAlias(true);
                        }
                    }
                    // 获取表头和对应的字段
                    String[] fs = new String[fieldNames.size()];
                    String[] ns = new String[cnNames.size()];
                    // 集合转换为数组
                    String[] fields = fieldNames.toArray(fs);
                    String[] names = cnNames.toArray(ns);
                    // 设置excel表头及其对应的字段名
                    for (int i = 0; i < names.length; i++) {
                        writer.addHeaderAlias(fields[i], names[i]);
                    }

                    // 设置文本自动换行
                    Workbook workbook = writer.getWorkbook();
                    StyleSet ss = new StyleSet(workbook);
                    ss.setWrapText();
                    writer.setStyleSet(ss);

                    //文本行不自动换行注释掉上面部分的代码

                   //-------------------------------------------------------------------
                    // 一次性写出内容,使用默认样式,强制输出标题
                    writer.write(list, true);
                    // response为HttpServletResponse对象
                    response.setContentType("application/vnd.ms-excel;charset=utf-8");
                    // test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
                    ServletOutputStream out = null;
                    try {
                       /**
                         * 如果字段的值不是太长可以不用设置列宽
                         * 设置列宽
                         * 工具类有自动的列宽,相较于默认列宽较小
                         * 显示日期时间存在显示不全而自动转换隐藏的情况(xxxxxxxxxx)
                         * 显示数据为居中显示
                         **/
                        for (int m = 0; m <= fieldNames.size(); m++) {
                            writer.setColumnWidth(m, 23);
                        }

                       /**
                         * 设置文件名称
                         * 名称加时间的方式显示方便文件在本地磁盘的查看
                         **/
                        fileName = fileName + DateUtil.format(new Date(), "YYYYMMddHHmmss");
                        // 设置请求头属性
                        response.setHeader("Content-Disposition", "attachment;filename=" + new String((fileName + ".xlsx").getBytes(), "iso-8859-1"));
                        out = response.getOutputStream();
                        // 写出到文件
                        writer.flush(out, true);
                        // 关闭writer,释放内存
                        writer.close();
                        // 此处记得关闭输出Servlet流
                        IoUtil.close(out);
                    } catch (IOException e) {
                        logger.error(e.getMessage());
                        e.printStackTrace();
                    }

                } catch (SecurityException e) {
                    logger.error(e.getMessage());
                    e.printStackTrace();
                }
            }
        } else {
            logger.error("集合数据为空!");
            throw new Exception("集合数据为空!");
        }
    }
}

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐