美文网首页java学习之路
POI动态生成excel表格

POI动态生成excel表格

作者: 唯有努力不欺人丶 | 来源:发表于2021-07-29 16:48 被阅读0次

这个问题困扰我一年多了,其实怎么解决一直有思路,但是又懒得去写。正好最近有空,而且新公司也实现了这个方式。所以顺便整理一下。
首先说一下poi和easypoi。
关于这个生成的excel表头和数据问题,两年前我是用poi做的。当时一个导出对应一大串方法,几十个字段都挨个写,然后for循环遍历数据对象来往格子里set,虽然逻辑很简单但是代码着实麻烦。这也就算了,毕竟就写一次。
但是去年遇到那种往写好了的excel中间插字段,那工作量简直搞人心态。然后寻思狗群友推荐我easyPoi,其中有个实体对象对应excel的模式,虽然可能是我我之前的方法简单点,但是本质上改动较大,而且也不是那么方便,所以就没改。
后来第二版中表头用的数组,数据还是for循环填格子。当时想着反射填充数据,但是又懒得去实现,就一直到现在。
正好到了新公司发现公司的导出就是我想象中的亚子,所以简单讲一下:
这里是把想导出的表格作为一个map传参。map 的key是实体对象中的属性名。value是想要的对应的中文表头。然后处理的时候去遍历value去获取表头。接着遍历数据列表,一层一层每一个属性用反射获取填充。
完整代码如下:

public class ExcelUtil {
    /**
     * 反射获取数据中指定字段的值
     * @param clazz
     * @param obj
     * @param fieldName
     * @return
     */
    public static Object getMethodVal(Class<?> clazz, Object obj, String fieldName) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method getMethod = clazz.getMethod(getter);
            return getMethod.invoke(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 创建表头
     * @param workbook
     * @param headList
     */
    public static void createExcelHead(SXSSFWorkbook workbook, Map<String, String> headList) {
        Sheet sheet = workbook.createSheet();
        Row headRow = sheet.createRow(0);
        int cellNum = 0;
        for (Map.Entry<String, String> head : headList.entrySet()) {
            XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
            XSSFFont font = (XSSFFont) workbook.createFont();
            style.setFont(font);
            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            Cell cell = headRow.createCell(cellNum);
            cell.setCellStyle(style);
            cell.setCellValue(head.getValue());
            cellNum++;
        }
    }

    /**
     * 填充数据
     * @param workbook
     * @param headList
     * @param dataList
     * @param <T>
     */
    public static <T> void appendExcel(SXSSFWorkbook workbook, Map<String, String> headList, List<T> dataList) {
        Sheet sheet = workbook.getSheetAt(0);
        int lastRowNum = sheet.getLastRowNum() + 1;
        for (T t : dataList) {
            Row row = sheet.createRow(lastRowNum);
            int cellNum = 0;
            for (Map.Entry<String, String> head : headList.entrySet()) {
                Cell cell = row.createCell(cellNum);
                Object methodVal =getMethodVal(t.getClass(), t, head.getKey());
                if (methodVal == null) {
                    methodVal = "";
                }
                if (methodVal instanceof Integer) {
                    cell.setCellValue((Integer) methodVal);
                } else if (methodVal instanceof Date) {
                    String dateToStr = DateUtils.dateToStr((Date) methodVal, DateUtils.YYYY_MM_DD_HH_MM_SS);
                    cell.setCellValue(dateToStr);
                } else {
                    cell.setCellValue(methodVal.toString());
                }
                cellNum++;
            }
            lastRowNum++;
        }
    }

    public static <T> void createExcelNoPath(String excelName, Map<String, String> headList, List<T> dataList,
                                             HttpServletResponse response) {
        ByteArrayOutputStream baos = null;
        try {
            //超过1000行将刷新到磁盘
            SXSSFWorkbook wb = new SXSSFWorkbook(1000);
            //创建表格头
            createExcelHead(wb, headList);
            //创建数据
            appendExcel(wb, headList, dataList);
            baos = new ByteArrayOutputStream();
            wb.write(baos);
            baos.close();
            String fileName = excelName + "-" + DateUtils.dateToStr(new Date(), DateUtils.YYYYMMDDHHMMSS) + ".xlsx";

            String filepath = "D:\\" + fileName;
            File file = new File(filepath);
            if (file.exists()) {
                file.delete();
            }
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baos.toByteArray(), 0, baos.toByteArray().length);
            fos.flush();
            fos.close();

            response.setContentType("application/vnd.ms-excel");
            response.addHeader("Content-Disposition", "attachment;filename=" +
                    new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            response.getOutputStream().write(baos.toByteArray());
            response.getOutputStream().flush();
            response.getOutputStream().close();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                    response.getOutputStream().flush();
                    response.getOutputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

这里的四个参数一个是输出流就不说了,另外三个一个是导出文件的名字,headList是表头和属性的map,dataList是我们真正要填充的数据列表。整个方法就这样。
本篇笔记如果稍微帮到你了记得点个喜欢点个关注,也祝大家工作顺顺利利吧~!

相关文章

网友评论

    本文标题:POI动态生成excel表格

    本文链接:https://www.haomeiwen.com/subject/ooxfvltx.html