随笔 - 1,  文章 - 0,  评论 - 0,  阅读 - 1445

 平常项目中经常会需要导出excel

如果需要导出的列很多的话,可能要花费很长的时间

本文章通过jxl和poi实现根据数据库表字段及其注释动态生成excel模板,并导出表数据导excel

其实也可以只用jxl,具体可以根据本文稍作修改

【maven依赖】

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.17</version>
        </dependency>
         <dependency>
            <groupId>net.sf.jxls</groupId>
            <artifactId>jxls-core</artifactId>
            <version>1.0.3</version>
        </dependency>

首先通过sql查询出表的字段和注释,之后使用poi(也可以使用jxl)根据字段和注释创建excel,注释作为列标题,字段名可作为参数,用于最后导出数据

<select id="selectTableColumn" parameterType="java.util.Map" resultType="java.util.Map">

        show  full  columns  from  ${tableName};
</select>

查询结果 

编辑

 【controller】根据之前的sql查询出来一个map,然后通过POIUtil.createTemp()方法生成excel模板文件(方法在后面有)

然后将表数据查出来,本文中的方法gastrointestinalStromalService.selectList(params)根据id集合查询所需要导出的数据,这个替换成自己的查询语句就行,比如select * from tablename。

之后将查询出来的数据放入map中,并传入jxl的 transformer.transformXLS();方法。

 

    @RequestMapping("/excel")
    public void exportExcel(HttpServletResponse response, String ids) {

        FileInputStream fis = null;
        ServletOutputStream out = null;
        try {

            Map<String, Object> params = new HashMap<>();
            //设置数据库表名
            params.put("tableName", "gastrointestinal_stromal");
            String fileName = UUID.randomUUID() + ".xlsx";
            String path = filePath + "export" + File.separator + fileName;

            //根据数据库表生成excel模板
            POIUtil.createTemp(path, baseTableService.selectTableColumn(params));

            //根据id查询要导出的数据
            params.put("ids", ids.split(","));
            List<Map<String, Object>> formDatas = gastrointestinalStromalService.selectList(params);

            //添加导出参数
            Map<String, Object> cMap = new HashMap();
            cMap.put("vms", formDatas);

            //响应流设置
            String currntTime = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
            response.reset();
            response.setContentType("application" + File.separator + "vnd.ms-excel");   //下载文版类型
            String exportFileName = "导出" + currntTime;
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(exportFileName.getBytes("gb2312"), "ISO8859-1") + ".xlsx");

            //生成的临时导出文件
            File destFile = File.createTempFile(filePath + "export" + File.separator + UUID.randomUUID(), ".xlsx");

            //  开始转换。利用  transformer 转到Excel
            XLSTransformer transformer = new XLSTransformer();
            // 参数:srcFilePath:模板源文件    cMap:需要导出的数据   destFile.getAbsolutePath():下载的目标文件
            transformer.transformXLS(path, cMap, destFile.getAbsolutePath());

            //写入响应流
            fis = new FileInputStream(destFile);
            out = response.getOutputStream();
            byte[] bytes = new byte[512];
            int i = 0;
            while ((i = fis.read(bytes)) != -1) {

                out.write(bytes, 0, i);
            }

            //删除临时文件
            new File(path).delete();
            destFile.delete();
        } catch (Exception e) {

            logger.error("{}导出表单excel异常:{}", Constans.ERRO_LOG, e);
        } finally {

            //释放资源
            try {

                out.close();
            } catch (IOException e) {

                logger.error("{}导出表单excel异常:{}", Constans.ERRO_LOG, e);
            }
            try {

                fis.close();
            } catch (IOException e) {

                logger.error("{}导出表单excel异常:{}", Constans.ERRO_LOG, e);
            }
        }
    }

部分循环使用JDK8的新特性, AtomicInteger用于计数,线程安全,在foreach循环中不能使用a++进行计数

将comment字放到excel第一行中,并过滤掉没注释的字段

"<jx:forEach items = \"${vms}\" var=\"data\">"是excel模板的表达式,放到第二行,意思是遍历我们传入的vms参数,后面可以使用data.的方式获取数据

将字段名拼接成表达式 "${data."+stringObjectMap.get("Field")+"}"。放到第三行

最后对循环进行闭合"</jx:forEach>"。放最后一行

public static String createTemp(String path,List<Map<String,Object>> maps) throws IOException {

        // 1. 创建一个工作薄

        XSSFWorkbook workbook = new XSSFWorkbook();

        // 创建一个目录和文件名

        FileOutputStream out = new FileOutputStream(new File(path));

        // 2. 创建一个工作表

        XSSFSheet spreadsheet = workbook.createSheet("Sheet1");
        // 单元格样式

        XSSFCellStyle style5 = workbook.createCellStyle();

        style5.setAlignment(HorizontalAlignment.CENTER);

        style5.setBorderBottom(BorderStyle.THICK);

        style5.setBottomBorderColor(IndexedColors.BLACK.getIndex());

        style5.setBorderLeft(BorderStyle.THICK);

        style5.setLeftBorderColor(IndexedColors.BLACK.getIndex());

        style5.setBorderRight(BorderStyle.THICK);

        style5.setRightBorderColor(IndexedColors.BLACK.getIndex());

        style5.setBorderTop(BorderStyle.THICK);

        style5.setTopBorderColor(IndexedColors.BLACK.getIndex());

        // 3. 创建一行
        XSSFRow row = spreadsheet.createRow(0);
        XSSFRow row2 = spreadsheet.createRow(2);
        AtomicInteger cellid = new AtomicInteger(-1);
        AtomicInteger cellid2 = new AtomicInteger();
        maps.forEach(stringObjectMap -> {

            String comment = stringObjectMap.get("Comment") + "";
            if(StringUtils.isNotEmpty(comment)) {

                spreadsheet.setColumnWidth(cellid.getAndIncrement(), comment.getBytes().length*2*256);
                Cell cell = row.createCell(cellid.intValue());
                // 设置单元格的值
                cell.setCellValue(comment);

                // 设置单元格样式
                cell.setCellStyle(style5);
                Cell cell2 = row2.createCell(cellid2.getAndIncrement());
                cell2.setCellValue("${data."+stringObjectMap.get("Field")+"}");
            }
        });

        XSSFCellStyle style6 = workbook.createCellStyle();
        style6.setAlignment(HorizontalAlignment.CENTER);
        XSSFRow row1 = spreadsheet.createRow(1);
        Cell cell = row1.createCell(0);
        cell.setCellValue("<jx:forEach items = \"${vms}\" var=\"data\">");
        cell.setCellStyle(style6);
        CellRangeAddress region = new CellRangeAddress(1, 1, 0, cellid.intValue());
        spreadsheet.addMergedRegion(region);

        XSSFRow row3 = spreadsheet.createRow(3);
        Cell cell3 = row3.createCell(0);
        cell3.setCellValue("</jx:forEach>");

        // 输出
        workbook.write(out);
        out.close();
        return path;
    }

 

生成出来的excel模板 

编辑

之后按照controller中的方法将数据传入生成出来的excel模板,即可导出表数据

导出效果图 

编辑

转载请注明出处

posted on   JohnLjy  阅读(1445)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示