zoukankan      html  css  js  c++  java
  • 百万数据导出生成一个Excel多个sheet

    因为公司禁止使用第三方工具,所以使用的原生poi来实现的。(如果公司没要求,建议使用阿里的esayExcel)

    一、创建导出类的扫描注解,判断是否是导出的信息

    @Retention(RetentionPolicy.RUNTIME)
    public @interface ExcelColumn {
        /**
         * 列索引
         * @return
         */
        public int columnIndex() default 0;
    
        /**
         * 列名
         * @return
         */
        public String columnName() default "";
    }

    二、创建导出对应的java类,并加上面的自定义注解;

    @Data
    public class BillMeituanPaymentOrderDto {
    
        @ExcelColumn(columnIndex = 0,columnName = "产品类型")
        private String productType;
    
        @ExcelColumn(columnIndex = 1,columnName = "车型")
        private String carType;
    
        @ExcelColumn(columnIndex = 2,columnName = "订单号")
        private String orderNo;
    
        @ExcelColumn(columnIndex = 3,columnName = "城市")
        private String city;
    
        @ExcelColumn(columnIndex = 4,columnName = "订单支付状态")
        private String orderPayState;
    
        @ExcelColumn(columnIndex = 5,columnName = "订单创建时间")
        private String orderTime;
    
        @ExcelColumn(columnIndex = 6,columnName = "订单支付完成时间")
        private String payTime;
    
        @ExcelColumn(columnIndex = 7,columnName = "服务商订单id")
        private String operatorOrderId;
    
        @ExcelColumn(columnIndex = 8,columnName = "订单是否归属当月账期")
        private String isCurrentMonth;
    
        @ExcelColumn(columnIndex = 9,columnName = "是否垫付")
        private String isAdvance;
    }

    三、生成公用的excel导出util类:ExportExcelUtils

    import lombok.extern.slf4j.Slf4j;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.hssf.util.HSSFColor;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.xssf.streaming.SXSSFRow;
    import org.apache.poi.xssf.streaming.SXSSFSheet;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    import org.springframework.util.CollectionUtils;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.lang.reflect.Field;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.GregorianCalendar;
    import java.util.List;
    
    @Slf4j
    public class ExportExcelUtils {
    
      /**
         *  将数据填充到excel里
         * @param workbook  要生成excel
         * @param list  填充数据集合
         * @param isCreateTitle 是否创建标题
         * @param isCreateSheet 是否创建sheet
         * @param sheetName  sheet名称
         * @return
         * @throws IOException
         */
        public static SXSSFWorkbook updateWorkbook(SXSSFWorkbook workbook, List<?> list, boolean isCreateTitle, boolean isCreateSheet, String sheetName) throws IOException {
            SXSSFSheet sheet;
            // 设置工作表的名称
            if (isCreateSheet) {
                sheet = workbook.createSheet(sheetName);
            } else {
                sheet = workbook.getSheet(sheetName);
            }
            // 获取实体所有属性
            Field[] fields = list.get(0).getClass().getDeclaredFields();
            ExcelColumn excelColumn;
            // 列索引
            int index = 0;
            //
            SXSSFRow row;
            //创建标题
            if (isCreateTitle) {
                Font font = workbook.createFont();
                //设置标题高度、字体
                font.setFontHeightInPoints((short) 16);
                font.setFontName("宋体");
                font.setBold(true);
                // 创建单元格标题样式
                CellStyle styleTitle = workbook.createCellStyle();
                styleTitle.setAlignment(HorizontalAlignment.CENTER);
                // 设置标题的下左右边框
                styleTitle.setBorderBottom(BorderStyle.THIN);
                styleTitle.setBorderLeft(BorderStyle.THIN);
                styleTitle.setBorderRight(BorderStyle.THIN);
                styleTitle.setFont(font);
                //设置标题背景颜色
                styleTitle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
                styleTitle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                // 创建第1行
                row = sheet.createRow(0);
                // 列名称
                String name;
                // 创建表头
                for (Field f : fields) {
                    // 是否是注解
                    if (f.isAnnotationPresent(ExcelColumn.class)) {
                        // 获取注解
                        excelColumn = f.getAnnotation(ExcelColumn.class);
                        // 获取列索引
                        index = excelColumn.columnIndex();
                        // 列名称
                        name = excelColumn.columnName();
                        //设置表单元格宽度值
                        sheet.setColumnWidth(index, (name.getBytes().length + 2) * 256);
                        //设置标题单元格高度
                        row.setHeightInPoints(35);
                        // 创建单元格
                        creCell(row, index, name, styleTitle);
                    }
                }
            }
            // 创建单元格样式
            CellStyle style = workbook.createCellStyle();
            // 居中显示
            style.setAlignment(HorizontalAlignment.CENTER);
            // 设置上下左右边框
            style.setBorderBottom(BorderStyle.THIN);
            style.setBorderLeft(BorderStyle.THIN);
            style.setBorderRight(BorderStyle.THIN);
            style.setBorderTop(BorderStyle.THIN);
            // 行索引  因为表头已经设置,索引行索引从1开始
            int rowIndex = sheet.getLastRowNum()+1;
            for (Object obj : list) {
                // 创建新行,索引加1,为创建下一行做准备
                row = sheet.createRow(rowIndex++);
                for (Field f : fields) {
                    // 设置属性可访问
                    f.setAccessible(true);
                    // 判断是否是注解
                    if (f.isAnnotationPresent(ExcelColumn.class)) {
                        // 获取注解
                        excelColumn = f.getAnnotation(ExcelColumn.class);
                        // 获取列索引
                        index = excelColumn.columnIndex();
                        //设置表单元格宽度值
                        try {
                            creCell(row, index, String.valueOf(f.get(obj)), style);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
    
                    }
                }
            }
            return workbook;
        }
    
        /**
         *  将excel生成到指定的路径
         * @param workbook
         * @param filepath 路径
         * @param filename 文件名称
         * @return
         */
        public static boolean exportExe(SXSSFWorkbook workbook, String filepath, String filename) {
            boolean success = false;
            FileOutputStream output = null;
            try {
                //判断是否存在目录. 不存在则创建
                isChartPathExist(filepath);
                //输出Excel文件
                output = new FileOutputStream(filepath + "/" + filename);
                //写入磁盘
                workbook.write(output);
                success = true;
            } catch (Exception e) {
                log.info("导出错误", e);
            } finally {
                if (workbook != null) {
                    //消除生成excel表格生成的临时文件
                    workbook.dispose();
                }
                Streams.close(workbook);
                Streams.close(output);
            }
            return success;
        }
    
        /**
         * 导出设置返回头
         *
         * @param response
         * @param excelName
         */
        public static void setHeader(HttpServletResponse response, String excelName) {
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-type", "application/xls;charset=UTF-8");
            try {
                String fileName = new String(excelName.getBytes("UTF-8"),
                        "ISO8859-1");
                response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");
            } catch (UnsupportedEncodingException e) {
                log.error("设置返回头出错啦,", e);
            }
    
        }
    
        /**
         * 创建单元格
         *
         * @param row
         * @param c
         * @param cellValue
         * @param style
         */
        public static void creCell(Row row, int c, String cellValue, CellStyle style) {
            Cell cell = row.createCell(c);
            cell.setCellValue(cellValue);
            cell.setCellStyle(style);
        }
    
       /**
         * 生成excel到指定路径
         *
         * @param wb
         * @param path
         * @throws Exception
         */
        public static void generateExcelToPath(HSSFWorkbook wb, String path) throws Exception {
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(path);
                wb.write(fos);
            } finally {
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
                if (wb != null) {
                    wb.close();
                }
            }
        }
    
        /**
         * 判断文件夹是否存在,如果不存在则新建
         *
         * @param dirPath 文件夹路径
         */
        public static void isChartPathExist(String dirPath) {
            File file = new File(dirPath);
            if (!file.exists()) {
                file.mkdirs();
            }
        }
    
        public static boolean delAllFile(String path) {
            boolean flag = false;
            File file = new File(path);
            if (!file.exists()) {
                return flag;
            }
            if (!file.isDirectory()) {
                return flag;
            }
            String[] tempList = file.list();
            File temp = null;
            for (int i = 0; i < tempList.length; i++) {
                if (path.endsWith(File.separator)) {
                    temp = new File(path + tempList[i]);
                } else {
                    temp = new File(path + File.separator + tempList[i]);
                }
                if (temp.isFile()) {
                    temp.delete();
                }
                if (temp.isDirectory()) {
                    delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
                    flag = true;
                }
            }
            return flag;
        }
    }

    四、使用

    
    @Slf4j
    @Service
    public class BizExportMeituanExcelService {
    
        //默认10分钟
        protected int workSeconds = 60 ;
        @Autowired
        private WorkLock workLock;
        @Autowired
        private WorkLogService workLogService;
      //这里是application里的配置生成文件路径信息,并设置了默认值 @Value(
    "${test.bill.file:/app/data/bill}") private String axebillFile; /** * 批量导出Excel * * @param response * @param req 为生成excel的过滤条件,这个自己根据需求定义 * @throws IOException */ public JsonResult exportExcel(HttpServletResponse response, ExportBillMeituanReq req) throws IOException { workLock.lock(workSeconds); JsonResult result = new JsonResult(); if (StringUtils.isBlank(req.getActNo()) || StringUtils.isBlank(req.getChannel())) { result.setSuccess(false); result.setMessage("账期和产品类型不能为空!"); return result; } String msg = ""; Date startTime = new Date(); try { boolean success = false; String actNo = req.getActNo(); String channel = req.getChannel(); List<String> cityList = settleDayService.getCityList(actNo,channel); //如果账期内有交易的城市,才生成excel if (!CollectionUtils.isEmpty(cityList)) { String filepath = getAxebillFile() + "/meituan/" + actNo + "/" + channel; ExportExcelUtils.delAllFile(filepath); for (String s : cityList) { success = exportSingleExcel(response, actNo, s, channel, filepath); } } else { result.setSuccess(true); result.setMessage("请先点击【生成结算单】,或者没有数据!"); return result; } if (success) { result.setSuccess(true); result.setMessage("生成成功!"); } else { result.setSuccess(false); result.setMessage("生成失败!"); } } catch (Exception e) {throw e; } finally { workLock.unLock(); } return result; } /** * 生成单个excel表格 */ private boolean exportSingleExcel(HttpServletResponse response, String actNo, String city, String channel, String filepath) throws IOException { //单张表格的各个sheet // 创建Excel工作簿对象 SXSSFWorkbook workbook = new SXSSFWorkbook(100); //查询3个sheet的数据 List<BillMeituanPaymentOrderDto> paymentOrderTotalList = new ArrayList<>(); int total = paymentOrderService.getTotal(actNo, city,channel); int pageSize = 10000; for (int i = 0; i < (total + pageSize - 1) / pageSize; i++) {
              //这里是分页查要导出的询数据 List
    <BillMeituanPaymentOrderDto> paymentOrderList = paymentOrderService.getPaymentOrderList(actNo, city, channel, i*pageSize, pageSize); if (i == 0) {
              //将要导出的数据生成excel ExportExcelUtils.updateWorkbook(workbook, paymentOrderList,
    true, true, "订单明细"); } else { ExportExcelUtils.updateWorkbook(workbook, paymentOrderList, false, false, "订单明细"); } } List<BillMeituanSettleDayDto> settleDayList = settleDayService.getSettleDayList(actNo, city,channel); if (!CollectionUtils.isEmpty(settleDayList)) { ExportExcelUtils.updateWorkbook(workbook, settleDayList, true, true, "账单汇总"); } //设置生成excel的名称 String filename = actNo + "-" + city + "-" + channel + "账单.xlsx"; return ExportExcelUtils.exportExe(workbook, filepath, filename); } }
  • 相关阅读:
    [转]oracle数据库定时任务dbms_job的用法详解
    身份证号码的正则表达式及验证详解(JavaScript,Regex)
    js数组操作
    jq滚动到底部加载更多方法
    jq之实现轮播
    node之npm一直出错
    Jq之21点游戏
    移动端屏幕适配viewport
    meta属性
    用户体验之表单结构
  • 原文地址:https://www.cnblogs.com/dupenghui/p/14355385.html
Copyright © 2011-2022 走看看