Excel模板导出工具类--支持多sheet、并且兼容2003和2007

package com.jtech.toa.controller.outclaim.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class ExportExcelUtils {


    // 2007 版本以上 最大支持1048576行
    public final static String EXCEl_FILE_2007 = "2007";


    // 2003 版本 最大支持65536 行
    public final static String EXCEL_FILE_2003 = "2003";


    public static void exportExcel2browser(String title, Object data, String templatePath, HttpServletResponse response, String version) {
        response.reset();
        response.setContentType("application/ms-excel;charset=UTF-8");
        OutputStream os = null;
        try {
            if (StringUtils.isEmpty(version) || EXCEL_FILE_2003.equals(version.trim())) {
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title, "UTF-8") + ".xls");
            } else {
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title, "UTF-8") + ".xlsx");
            }
            os = response.getOutputStream();
            exportExcel(data, templatePath, version, os);
            os.flush();
        } catch (Exception e) {
            log.error("导出excel出现异常{}", e);
        } finally {
            closeOutPutStream(os);
        }
    }

    public static void exportExcel(Object data, String templatePath, String version, OutputStream out) {
        if (StringUtils.isEmpty(version) || EXCEL_FILE_2003.equals(version.trim())) {
            exportExcel2003(data, templatePath, out);
        } else {
            exportExcel2007(data, templatePath, out);
        }
    }

    /**
     * 导出2007以下
     *
     * @param data
     * @param templatePath
     * @param out
     */
    private static void exportExcel2003(Object data, String templatePath, OutputStream out) {
        try {
            HSSFWorkbook workbook;
            FileInputStream tps = new FileInputStream(new File(templatePath));
            final HSSFWorkbook tpWorkbook = new HSSFWorkbook(tps);
            workbook = tpWorkbook;
            int numbers = workbook.getNumberOfSheets();
            for (int i = 0; i < numbers; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                addDataToSheet(data, sheet);
            }
            workbook.write(out);
        } catch (IOException e) {
            log.error("导出Excel2003出现异常");
        }

    }

    private static void exportExcel2007(Object data, String templatePath, OutputStream out) {
        try {
            XSSFWorkbook workbook;
            FileInputStream tps = new FileInputStream(new File(templatePath));
            final XSSFWorkbook tpWorkbook = new XSSFWorkbook(tps);
            workbook = tpWorkbook;
            int numbers = workbook.getNumberOfSheets();
            for (int i = 0; i < numbers; i++) {
                Sheet sheet = workbook.getSheetAt(i);
                addDataToSheet(data, sheet);
            }
            workbook.write(out);
        } catch (IOException e) {
            log.error("导出Excel2007以上出现异常");
        }
    }


    private static void closeOutPutStream(OutputStream os) {
        try {
            os.close();
        } catch (Exception e) {
            log.error("关闭流出现异常");
        }
    }


    /**
     * 向模板内赋值
     *
     * @param
     */
    private static void addDataToSheet(Object data, Sheet sheet) {
        Map> listRecord = new LinkedHashMap<>();
        int lastRowNum = sheet.getLastRowNum();
        for (int i = lastRowNum; i >= 0; i--) {
            Row row = sheet.getRow(i);
            if (row == null) {
                continue;
            }
            int lastCellNum = row.getLastCellNum();
            for (int j = 0; j < lastCellNum; j++) {
                Cell cell = row.getCell(j);
                if (cell == null) {
                    continue;
                }
                try {
                    String cellValue = cell.getStringCellValue();
                    if (cellValue.matches(".*\\$\\{[\\w.()]+}.*")) {
                        fillCell(cell, cellValue, data);
                    } else if (cellValue.matches(".*\\$\\{[\\w.]+\\[#][\\w.]+}.*")) {
                        Map rowRecord = listRecord.computeIfAbsent(i, k -> new HashMap<>());
                        rowRecord.put(j, cell);
                    }
                } catch (Exception e) {
                    log.error("异常信息{}", e);
                }
            }
        }

        Map listInData = new HashMap<>();
        Map listCellStyle = new HashMap<>();
        Map listCellPath = new HashMap<>();
        listRecord.forEach((rowNum, colMap) -> {
            Pattern p = Pattern.compile("\\$\\{[\\w.\\[#\\]]+}");
            Set listPath = new HashSet<>();
            colMap.forEach((colNum, cell) -> {
                String cellValue = cell.getStringCellValue();
                Matcher m = p.matcher(cellValue);
                if (m.find()) {
                    String reg = m.group();
                    String regPre = reg.substring(2, reg.indexOf("["));
                    String regSuf = reg.substring(reg.lastIndexOf("].") + 2, reg.length() - 1);
                    listPath.add(regPre);
                    listCellStyle.put(String.format("%s.%s", regPre, regSuf), cell.getCellStyle());
                    listCellPath.put(cell, String.format("%s#%s", regPre, regSuf));
                }
            });
            int maxRow = 0;
            for (String s : listPath) {
                Object list = getAttributeByPath(data, s);
                if (list == null) {
                    list = new ArrayList<>();
                }
                if (list instanceof List) {
                    int len = ((List) list).size();
                    maxRow = maxRow > len ? maxRow : len;
                    listInData.put(s, ((List) list));
                } else {
                    throw new IllegalArgumentException(String.format("%s is not a list but a %s", s, list.getClass().getSimpleName()));
                }
            }
        });

        listRecord.forEach((rowNum, colMap) -> {
            colMap.forEach((colNum, cell) -> {
                String path = listCellPath.get(cell);
                String[] pathData = path.split("#");
                List list = listInData.get(pathData[0]);
                int baseRowIndex = cell.getRowIndex();
                int colIndex = cell.getColumnIndex();
                CellStyle style = listCellStyle.get(String.format("%s.%s", pathData[0], pathData[1]));
                for (int i = 0; i < list.size(); i++) {
                    int rowIndex = baseRowIndex + i;
                    Row row = sheet.getRow(rowIndex);
                    if (row == null) {
                        row = sheet.createRow(rowIndex);
                    }
                    Boolean flag = row.getZeroHeight();
                    if (flag) {
                        row.setZeroHeight(false);
                    }

                    Cell cellToFill = row.getCell(colIndex);
                    if (cellToFill == null) {
                        cellToFill = row.createCell(colIndex);
                    }
                    cellToFill.setCellStyle(style);
                    setCellValue(cellToFill, getAttribute(list.get(i), pathData[1]));
                }
            });
        });
    }


    /**
     * @param cell       要置换的单元格
     * @param expression 单元格内的置换标记
     * @param data       数据源
     */
    private static void fillCell(Cell cell, String expression, Object data) {
        Pattern p = Pattern.compile("\\$\\{[\\w.\\[\\]()]+}");
        Matcher m = p.matcher(expression);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String exp = m.group();
            String path = exp.substring(2, exp.length() - 1);
            Object value = getAttributeByPath(data, path);
            m.appendReplacement(sb, value == null ? "" : value.toString());
        }
        setCellValue(cell, sb.toString());
    }


    /**
     * @param cell  单元格
     * @param value 值
     */
    private static void setCellValue(Cell cell, Object value) {
        if (value == null) {
            cell.setCellValue("");
        } else if (value instanceof Date) {
            cell.setCellValue((Date) value);
        } else if (value instanceof Integer) {
            cell.setCellValue((Integer) value);
        } else if (value instanceof Long) {
            cell.setCellValue((Long) value);
        } else if (value instanceof Double) {
            cell.setCellValue((Double) value);
        } else if (value instanceof Float) {
            cell.setCellValue((Float) value);
        } else if (value instanceof Character) {
            cell.setCellValue((Character) value);
        } else if (value instanceof BigDecimal) {
            cell.setCellValue(((BigDecimal) value).doubleValue());
        } else {
            cell.setCellValue(value.toString());
        }
    }


    /**
     * @param obj  访问对象
     * @param path 属性路径,形如(cls.type, cls.students.size())
     * @return
     */
    private static Object getAttributeByPath(Object obj, String path) {
        String[] paths = path.split("\\.");
        Object o = obj;
        for (String s : paths) {
            o = getAttribute(o, s);
        }
        return o;
    }

    private static Object getAttribute(Object obj, String member) {
        if (obj == null) {
            return null;
        }
        boolean isMethod = member.endsWith("()");
        if (!isMethod && obj instanceof Map) {
            return ((Map) obj).get(member);
        }
        try {
            Class cls = obj.getClass();
            if (isMethod) {
                Method method = cls.getDeclaredMethod(member.substring(0, member.length() - 2));
                return method.invoke(obj);
            } else {
                Field field = cls.getDeclaredField(member);
                field.setAccessible(true);
                return field.get(obj);
            }
        } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
            log.error("异常信息{}",e);
        }
        return null;
    }

}

你可能感兴趣的:(Excel模板导出工具类--支持多sheet、并且兼容2003和2007)