java 反射实现excel导出通用工具类

废话不多说,直接上代码吧,使用的方法在最下面

此导出工具类借鉴了一些大神的写法以及结合自己业务上的需求



import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.*;

import java.awt.*;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

public class ExcelUtil {


    /**
     * @param title:sheet名称
     * @param propertyHeaderMap:)
     *                                     用LinkedHashMap保证读取的顺序和put的顺序一样
     * @param dataSet:实体类集合
     * @description: 适用于单表导出
     * @author: xch
     * @date: 2018/5/23 9:38
     * 根据输入的数据生成一个XSSFWorkbook
     * @return:XSSFWorkbook
     */
    public static <T> XSSFWorkbook generateXlsxWorkbook(String title, LinkedHashMap<String, String> propertyHeaderMap, Collection<T> dataSet) {
        // 声明一个工作薄
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 生成一个表格
        XSSFSheet sheet = workbook.createSheet(title);

        // 设置表格默认列宽度为20个字节
        sheet.setDefaultColumnWidth((int) 20);

        XSSFCellStyle headerStyle = getHeaderStyle(workbook);
        XSSFCellStyle contentStyle = getContentStyle(workbook);

        // 生成表格标题行
        XSSFRow row = sheet.createRow(0);
        int i = 0;
        //传过来的map设置表头
        for (String key: propertyHeaderMap.keySet()) {
            XSSFCell cell = row.createCell(i);
            cell.setCellStyle(headerStyle);
            XSSFRichTextString text = new XSSFRichTextString(propertyHeaderMap.get(key));
            cell.setCellValue(text);
            i++;
        }

        //循环dataSet,每一条对应一行
        int index = 0;
        for (T data: dataSet) {
            index++;
            row = sheet.createRow(index);

            int j = 0;
            for (String property: propertyHeaderMap.keySet()) {
                XSSFCell cell = row.createCell(j);
                cell.setCellStyle(contentStyle);

                //拼装getter方法名              //toUpperCase()英文字符转换为大写字母,例如P+kId;完成拼出:getPkId
                String getMethodName = "get" + property.substring(0, 1).toUpperCase() + property.substring(1);

                try {
                    //利用反射机制获取dataSet中的属性值,填进cell中
                    Class<? extends Object> tCls = data.getClass();
                    Method getMethod = tCls.getMethod(getMethodName, new Class[]{});
                    Object value = getMethod.invoke(data, new Object[]{}); //调用getter从data中获取数据

                    // 判断值的类型后进行类型转换
                    String textValue = null;

                    if (value != null) {
                        if (value instanceof Double) {
                            //double类型如果小数点后为零显示整数,否则保留
                            if ((Double) value % 1.0 == 0) {
                                textValue = String.valueOf(((Double) value).longValue());
                            } else {
                                textValue = value.toString();
                            }
                        } else if (value instanceof Date) {
                            Date date = (Date) value;
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            textValue = sdf.format(date);
                        } else {
                            // 其它数据类型都当作字符串简单处理
                            textValue = value.toString();
                        }
                    } else {
                        textValue = "";
                    }
                    XSSFRichTextString richString = new XSSFRichTextString(textValue);
                    cell.setCellValue(richString);

                } catch (Exception e) {
                    e.printStackTrace();
                }
                j++;
            }
        }

        return workbook;

    }


   
    public static <T> XSSFWorkbook generateXlsxWorkbook(String title, LinkedHashMap<String, String> propertyHeaderMap, Collection<T> dataSet, Map<String, Object[]> map) {
        // 声明一个工作薄
        XSSFWorkbook workbook = new XSSFWorkbook();
        // 生成一个表格
        XSSFSheet sheet = workbook.createSheet(title);

        // 设置表格默认列宽度为20个字节
        sheet.setDefaultColumnWidth((int) 20);

        XSSFCellStyle headerStyle = getHeaderStyle(workbook);
        XSSFCellStyle contentStyle = getContentStyle(workbook);

        // 生成表格标题行
        XSSFRow row = sheet.createRow(0);
        int i = 0;
        //传过来的map设置表头
        for (String key: propertyHeaderMap.keySet()) {
            XSSFCell cell = row.createCell(i);
            cell.setCellStyle(headerStyle);
            XSSFRichTextString text = new XSSFRichTextString(propertyHeaderMap.get(key));
            cell.setCellValue(text);
            i++;
        }

        //循环dataSet,每一条对应一行
        int index = 0;
        for (T data: dataSet) {
            index++;
            row = sheet.createRow(index);

            int j = 0;
            for (String property: propertyHeaderMap.keySet()) {
                XSSFCell cell = row.createCell(j);
                cell.setCellStyle(contentStyle);

                //拼装getter方法名              //toUpperCase()英文字符转换为大写字母,例如P+kId
                String getMethodName = "get" + property.substring(0, 1).toUpperCase() + property.substring(1);

                try {
                    //利用反射机制获取dataSet中的属性值,填进cell中
                    Class<? extends Object> tCls = data.getClass();
                    Method getMethod = tCls.getMethod(getMethodName, new Class[]{});
                    Object value = getMethod.invoke(data, new Object[]{}); //调用getter从data中获取数据


                    int a = 0;
                    int b = 0;
                    if (map != null) {
                        if (map.get(property) != null) {
                            a = Integer.parseInt(value.toString());
                            b = map.get(property).length;
                            for (int n = 0; n < b; n++) {
                                value = map.get(property)[a];
                            }
                        }
                    }
                    // 判断值的类型后进行类型转换
                    String textValue = null;
                    if (value != null) {
                        if (value instanceof Double) {
                            //double类型如果小数点后为零显示整数,否则保留
                            if ((Double) value % 1.0 == 0) {
                                textValue = String.valueOf(((Double) value).longValue());
                            } else {
                                textValue = value.toString();
                            }
                        } else if (value instanceof Date) {
                            Date date = (Date) value;
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            textValue = sdf.format(date);
                        } else {
                            // 其它数据类型都当作字符串简单处理
                            textValue = value.toString();
                        }
                    } else {
                        textValue = "";
                    }
                    XSSFRichTextString richString = new XSSFRichTextString(textValue);
                    cell.setCellValue(richString);

                } catch (Exception e) {
                    e.printStackTrace();
                }
                j++;
            }
        }

        return workbook;

    }


    /**
     * @param workbook
     * @return style
     * @description: 生成一个标题style
     * @author: xch
     * @date: 2018/5/23 9:39
     */
    public static XSSFCellStyle getHeaderStyle(XSSFWorkbook workbook) {
        return getHeaderStyle(workbook, Color.WHITE, IndexedColors.BLACK.getIndex());
    }

    /**
     * @param workbook
     * @param foregroundColor
     * @param fontColor
     * @description: 生成一个指定颜色的标题style
     * @author: xch
     * @date: 2018/5/23 9:39
     */
    public static XSSFCellStyle getHeaderStyle(Workbook workbook, Color foregroundColor, short fontColor) {

        // 生成一个样式(用于标题)
        XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
        // 设置这些样式
        style.setFillForegroundColor(new XSSFColor(foregroundColor));
        style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);
        style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        // 生成一个字体
        XSSFFont font = (XSSFFont) workbook.createFont();
        font.setColor(fontColor);
        font.setFontHeightInPoints((short) 12);
        font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 把字体应用到当前的样式
        style.setFont(font);

        return style;
    }


    /**
     * @param workbook
     * @return
     * @description: 生成一个用于内容的style
     * @author: xch
     * @date: 2018/5/23 9:39
     */
    public static XSSFCellStyle getContentStyle(XSSFWorkbook workbook) {
        // 生成并设置另一个样式(用于内容)
        XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
        //style.setFillForegroundColor(new XSSFColor(Color.YELLOW));
        //style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);
        style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        // 生成另一个字体
        XSSFFont font = (XSSFFont) workbook.createFont();
        font.setBoldweight(XSSFFont.BOLDWEIGHT_NORMAL);
        // 把字体应用到当前的样式
        style.setFont(font);

        return style;
    }
}

如何使用

方法1:generateXlsxWorkbook(String title, LinkedHashMap propertyHeaderMap, Collection dataSet)

1、第一个参数为excel的title名字
2、第二个参数选择LinkedHashMap的原因在于内部维持了一个双向链表,可以保持顺序;map的键 必须和实体类的属性名称一致
值为导出excel的表头名称
3、第三个参数为导出数据的集合

 Map<String, Object> temp = new HashMap();
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("folderName", "订单号");
        map.put("customerName", "客户名");
        map.put("housingAddress", "客户地址");
        map.put("fileNumber", "文件数");
        map.put("createName", "创建人");
        map.put("createTime", "创建时间");

        XSSFWorkbook ex = ExcelUtil.generateXlsxWorkbook("文档中心", map, fileFolderList);

方法2:generateXlsxWorkbook(String title, LinkedHashMap propertyHeaderMap, Collection dataSet, Map map)

一些特别的业务有很多种状态,数据库查询返回的都是int型的数字,每一个数字代表不同的状态,这时候就需要第四个参数了:将返回状态的int型数字作为下标来将状态转为需要导出的内容

        Map<String, Object> temp = new HashMap();
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("po.orderNumber", "订单编号");
        map.put("name", "销售");
        map.put("area", "门店");
        map.put("customerName", "客户");
        map.put("customerPhone", "客户电话");
        map.put("price", "已收金额");
        map.put("po.pactPrices", "订单金额");
        map.put("po.billType", "状态");
        map.put("po.startTime", "进场时间");
        map.put("po.endTime", "出场时间");
        map.put("po.createTime", "录入时间");
        map.put("po.updateTime", "更新时间");

        String[] billType = {"已取消", "正常", "草稿", "正在等待删除审核", "正在生产审核的"};
        Map<String, Object[]> types = new LinkedHashMap<>();
        types.put("po.billType", billType);
      
            XSSFWorkbook ex = ExcelUtilDTO.generateXlsxWorkbook("取消订单列表", map, podList, types);
            String path = ServletActionContext.getServletContext().getRealPath("/") + "excel";
            String fileName = "取消订单报表" + UUID.randomUUID().toString() + ".xlsx";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdir();
            }
            OutputStream out = new FileOutputStream(file.getPath() + File.separator + fileName);
            BufferedOutputStream bos = new BufferedOutputStream(out);
            ex.write(bos);

你可能感兴趣的:(java)