• Spring Boot项目基于POI框架导出Excel表格


    1.    依赖

         我的项目是基于Spring Boot的,这里只贴出POI框架需要依赖的两个包,其他的都无所谓,只要能提供Controller让浏览器访问即可。在pom.xml配置文件中增加如下两个包:

           <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.1.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.1.2</version>
            </dependency>

    2. 代码实现

    package com.eg.wiener.controller;
    
    import com.eg.wiener.dto.User;
    import com.eg.wiener.utils.ExcelUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections4.CollectionUtils;
    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.hssf.util.HSSFColor;
    import org.apache.poi.ss.usermodel.BorderStyle;
    import org.apache.poi.ss.usermodel.Font;
    import org.apache.poi.ss.usermodel.HorizontalAlignment;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.stream.Stream;
    
    /**
     * @author Wiener
     * @date 2020/9/5
     */
    @Slf4j
    @RestController
    @RequestMapping("/excel")
    public class ExcelExportController {
    
        private static HSSFWorkbook workbook = null;
        // 代表一行记录
        private static HSSFCell cell = null;
        private static HSSFRow row = null;
    
        @RequestMapping(value = "/exportExcel")
        public Object exportExcel(HttpServletRequest request, HttpServletResponse response) throws Exception {
            String fileSuffix = ".xls";
            String fileName = "导出数据至Excel示例"+ "_" + (int) (Math.random() * 9000 + 1000) + ".xls";
    
            //【1】创建excel
            workbook = new HSSFWorkbook();
            // 设置表头的类型
            HSSFCellStyle style = setCellStyle(workbook);
    
            // 创建一个sheet
            HSSFSheet sheet = workbook.createSheet("sheet1");
    
            try {
                List<User> dataList = getUsers();
    
                if (CollectionUtils.isNotEmpty(dataList)) {
                    //【2】 设置表头:对Excel每列命名
                    String[] tableHeader = Stream.of("编号", "姓名", "年龄").toArray(String[]::new);
                    // 设置Excel表头
                    row = ExcelUtils.getExcelRow(workbook, sheet, tableHeader);
                    //通过反射,获取POJO对象。由于同一个dataList中,POJO相同,故定义在for循环外部,提高遍历性能
                    Class cl = dataList.get(0).getClass();
                    //获取类的所有字段
                    Field[] fields = cl.getDeclaredFields();
                    //写入每一行的记录
                    for (int i = 0; i < dataList.size(); i++) {
                        //创建新的一行,递增
                        row = sheet.createRow(i + 1);
                        // 设置行高
                        row.setHeight((short) 400);
                        for (int j = 0; j < fields.length; j++) {
                            //设置字段可见,否则会报错,禁止访问
                            fields[j].setAccessible(true);
                            //创建单元格
                            cell = row.createCell(j);
                            cell.setCellValue(Objects.toString(fields[j].get(dataList.get(i)), ""));
                            cell.setCellStyle(style);
                        }
                    }
                } else {
                    // 没有查到数据提示行
                    row = ExcelUtils.getNotResultInfoRow(workbook, sheet, "记录为空");
                }
            } catch (Exception e) {
                log.error("导出数据失败:", e);
                // 写入Excel失败原因
                row = ExcelUtils.getNotResultInfoRow(workbook, sheet, "导出数据失败");
                fileName = "导出数据失败";
            }
            fileName = fileName + "_" + (int) (Math.random() * 9000 + 1000) + fileSuffix;
    
            //下载文件
            ExcelUtils.outputExcelStream(request, response, workbook, fileName);
    
            return "导出成功";
        }
    
        private List<User> getUsers() {
            List<User> list = new ArrayList<>();
            User aUser = new User();
            aUser.setAge(18);
            aUser.setId(1);
            aUser.setName("Tony");
            list.add(aUser);
    
            aUser = new User();
            aUser.setAge(21);
            aUser.setId(2);
            aUser.setName("Tom");
            list.add(aUser);
            aUser = new User();
            aUser.setAge(20);
            aUser.setId(3);
            aUser.setName("店小二");
            list.add(aUser);
            return list;
        }
    
        private HSSFCellStyle setCellStyle(HSSFWorkbook myWorkbook) {
            HSSFCellStyle style = myWorkbook.createCellStyle();
            //设置自动换行
            style.setWrapText(true);
            style.setAlignment(HorizontalAlignment.CENTER);
            //设置边框样式
            style.setBorderTop(BorderStyle.THIN);
            style.setBorderBottom(BorderStyle.THIN);
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);
            //设置边框颜色
            style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
    
            HSSFDataFormat format = workbook.createDataFormat();
            // 设置文本格式
            style.setDataFormat(format.getFormat("@"));
            // 设置字体
            HSSFFont font = workbook.createFont();
            font.setColor(Font.COLOR_RED);
            font.setFontName("宋体");
            font.setFontHeightInPoints((short) 12);// 12号字体
            style.setFont(font);
            return style;
        }
    }

        通过反射获取POJO对象,故传入不同类型的POJO对象的dataList就可以了。下面是依赖的一个工具类:

    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.hssf.util.HSSFColor;
    import org.apache.poi.ss.usermodel.BorderStyle;
    import org.apache.poi.ss.usermodel.HorizontalAlignment;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.URLEncoder;
    
    /**
     * 导出Excel工具类
     *
     * @author Wiener
     * @date 2020/9/5
     */
    @Slf4j
    public class ExcelUtils {
    
        /**
         * 设置Excel表头
         *
         * @param workbook
         * @param sheet
         * @param tableHeader
         * @return
         */
        public static HSSFRow getExcelRow(HSSFWorkbook workbook, HSSFSheet sheet, String[] tableHeader) {
            short cellNumber = (short) tableHeader.length;
            // Excel的第一行表头
            HSSFRow row = sheet.createRow(0);
            // 设置行高
            row.setHeight((short) 560);
            // Excel的列
            HSSFCell cell = null;
            HSSFFont font = workbook.createFont();
            // 粗体显示
            font.setBold(Boolean.TRUE);
            font.setFontHeightInPoints((short) 15);
            // 设置单元格字体的颜色
            font.setColor(HSSFFont.COLOR_NORMAL);
            // 样式
            HSSFCellStyle style = workbook.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            //设置边框样式
            style.setBorderTop(BorderStyle.DOTTED);
            style.setBorderBottom(BorderStyle.DOTTED);
            style.setBorderLeft(BorderStyle.DOTTED);
            style.setBorderRight(BorderStyle.DOTTED);
            //设置边框颜色
            style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
            style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
    
            for (int k = 0; k < cellNumber; k++) {
                int i = 0;
                i += k;
                short b = 6000;
                cell = row.createCell(i);                       // 创建第0行第k列
                cell.setCellValue(tableHeader[k]);              // 设置第0行第k列的值
                sheet.setColumnWidth(i, b);                     // 设置列的宽度
                style.setFont(font);                           // 设置字体风格
                cell.setCellStyle(style);
            }
            return row;
        }
    
        /**
         * 设置Excel未获取数据提示行
         *
         * @param workbook
         * @param sheet
         * @return
         */
        public static HSSFRow getNotResultInfoRow(HSSFWorkbook workbook, HSSFSheet sheet, String message) {
            // Excel的第一行表头
            HSSFRow row = sheet.createRow(0);
            // Excel的列
            HSSFCell cell = null;
            // 设置表头的类型
            HSSFCellStyle style = workbook.createCellStyle();
            //设置自动换行
            style.setWrapText(true);
            style.setAlignment(HorizontalAlignment.CENTER);
    
            // 没有查到数据
            row = sheet.createRow((short) (0));             // 创建第j+1行
            row.setHeight((short) 1000);                    // 设置行高
            sheet.setColumnWidth(0, 10000);
            cell = row.createCell(0);                       // 创建第i+1行第1列
            cell.setCellValue(message);//
            cell.setCellStyle(style);                       // 设置风格
    
            return row;
        }
    
        /**
         * 下载EXCEL,对不同浏览器做中文名称兼容<br/>
         * 如果不对文件名进行编码处理,那么有些浏览器无法识别下载文件
         *
         * @param request
         * @param response
         * @param workbook
         * @param fileName
         */
        public static void outputExcelStream(HttpServletRequest request, HttpServletResponse response, HSSFWorkbook workbook, String fileName) {
            OutputStream out = null;
            try {
                String excelFileName = fileName + "_" + (int) (Math.random() * 9000 + 1000) + ".xls";
                if (isMsBrowser(request)) {
                    // ie,edge 浏览器
                    excelFileName = URLEncoder.encode(excelFileName, "UTF-8");
                } else {
                    //其他的浏览器
                    excelFileName = new String(excelFileName.getBytes("UTF-8"), "iso-8859-1");
                }
                //输出流对象
                out = response.getOutputStream();
                // 设置文件头编码方式和文件名
                response.setHeader("Content-Disposition", "attachment;filename=" + excelFileName);
                // 设置类型
                response.setContentType("application/msexcel;charset=UTF-8");
                response.setHeader("Pragma", "No-cache");
                response.setHeader("Cache-Control", "no-cache");
                response.setDateHeader("Expires", 0);
                workbook.write(out);
                out.flush();
                workbook.write(out);
            } catch (IOException e) {
                log.error("下载EXCEL失败,", e);
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (IOException e) {
                    log.error("下载EXCEL关闭文件流失败,", e);
                }
            }
        }
    
        //判断是否是IE浏览器
        private static boolean isMsBrowser(HttpServletRequest request) {
            String userAgent = request.getHeader("User-Agent");
            if (StringUtils.isBlank(userAgent)) {
                return false;
            }
            String[] IEBrowserSignals = {"msie", "trident", "edge"};
            for (String signal : IEBrowserSignals) {
                if (userAgent.toLowerCase().contains(signal)) {
                    return true;
                }
            }
            return false;
        }
    
    }

          在使用的时候,仅仅需要传入不同的表头集合、实体类集合,就能实现需求,这就是封装的魅力所在。

  • 相关阅读:
    微信小程序授权获取用户详细信息openid
    微信开发之微信网页授权 完整示例
    linux 安装MySql 5.7.20 操作步骤【亲测】
    CentOS7下rabbitmq的详细安装教程
    Makefile:248: /usr/local/otp_src_18.1/make/x86_64-unknown-linux-gnu/otp_ded.mk: No such file
    Calendar的add()方法介绍
    怎样梳理属于自己的项目管理套路?
    项目经理必备9大获得领导支持秘技
    为什么绝大多数项目经理在不断救火?
    Java IO流学习总结
  • 原文地址:https://www.cnblogs.com/east7/p/13629098.html
Copyright © 2020-2023  润新知