百万数据导出生成一个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); } }

 

posted @ 2021-02-01 10:32  糊涂蜗牛  阅读(536)  评论(0编辑  收藏  举报