SpringMVC在内存中直接生成Excel让用户在浏览器中直接下载使用

1. 如何查询出数据库的SCHEMA, 这里贴出核心的SQL语句

SELECT COLUMN_NAME AS field, COLUMN_COMMENT AS comment
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = ?



由于注释有的会很长, 全部取出来作为excel的一格, 会很不好, 其实我们只是需要重要的意思, 所以, 这里前提条件就是将注释用分隔符分开

例如: name=>名称: 用户昵称, 这里我就可以用":"来分割, 只取出"名称"来. 所以, 一件方便的事情是需要很多的约定的, 尤其是团队合作中.

为了拿到一张表的字段名, 和注释, 就提取了一个公用的类:

/**
 * Created with antnest-platform
 * User: Vernon.Chen
 * Date: 2015/3/16
 * Time: 17:03
 */
@Service
public class QuerySchema {

    @Resource
    private JdbcTemplate jdbcTemplate;

    public List<Map<String, Object>> getSchemaByTableName(String tableName) {
        if (StringUtils.isBlank(tableName)) {
            return null;
        }
        List<Map<String, Object>> schema = new ArrayList<Map<String, Object>>();
        StringBuilder sqlSB = new StringBuilder();
        sqlSB.append(" SELECT COLUMN_NAME AS field, COLUMN_COMMENT AS comment ");
        sqlSB.append(" FROM INFORMATION_SCHEMA.COLUMNS ");
        sqlSB.append(" WHERE table_name = ? ");
        schema = jdbcTemplate.queryForList(sqlSB.toString(), new Object[]{tableName});
        if (schema != null && schema.size() > 0) {
            for (Map<String, Object> map : schema) {
                String comment = (String) map.get("comment");
                if (StringUtils.isNotBlank(comment) && comment.indexOf(":") > -1) {
                    map.put("comment", comment.substring(0, comment.indexOf(":")));
                }
            }
        }
        return schema;
    }

}



这返回的结果就是一List, 里面每一个Map都是一个{"field":"XXX","comment":"XXX"}.

下面就是如何生成Excel呢? 也是比较总要的一步. 生成Excel我所知道jar包有2个, 一个是jxl.jar, 还有一个就是项目中用到的poi.

<dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>${poi.version}</version>
            </dependency>



这里我的版本是: 
<poi.version>3.10-FINAL</poi.version>

然后开看一个组装Excel的代码. 由于不需要将生成的文件持久化到本地, 所以直接返回byte[]就好.

@Override
    public byte[] selectExcel() throws Exception {
        ByteArrayOutputStream out = null;
        try {
            HSSFWorkbook workbook = new HSSFWorkbook();
            generateExcelForAs(cellMapper.selectExcel(), workbook);
            out = new ByteArrayOutputStream();
            HSSFWorkbook hssWb = (HSSFWorkbook) workbook;
            hssWb.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return out.toByteArray();
    }



迭代生成每一行
private void generateExcelForAs(List<Map<String, Object>> list, HSSFWorkbook workbook) {
        if (list == null || list.size() == 0) {
            return ;
        }
        List<Map<String, Object>> title = querySchema.getSchemaByTableName("t_cell");
        int excelRow = 0;
        try {
            HSSFSheet sheet = workbook.createSheet();
            for (int i = 0; i < list.size(); i++) {
                if (i == 0) {
                    Map<String, Object> first = list.get(0);
                    // 添加标题
                    int column = 0;
                    HSSFRow row = sheet.createRow(excelRow);
                    for (Map<String, Object> map : title) {
                        row.createCell(column).setCellValue(map.get("comment").toString());
                        column++;
                    }
                    excelRow++;
                    column = 0;
                    // 还需添加第1行的数据, 从0开始
                    row = sheet.createRow(excelRow);
                    for (Map<String, Object> map : title) {
                        if (!first.containsKey(map.get("field"))) {
                            column++;
                        } else {
                            String value = first.get(map.get("field")) == null ? "" : first.get(map.get("field")).toString();
                            row.createCell(column).setCellValue(value);
                            column++;
                        }
                    }
                    excelRow++;
                } else {
                    HSSFRow row = sheet.createRow(excelRow);
                    Map<String, Object> rowMap = list.get(i);
                    int column = 0;
                    for (Map<String, Object> map : title) {
                        if (!rowMap.containsKey(map.get("field"))) {
                            column++;
                        } else {
                            String value = rowMap.get(map.get("field")) == null ? "" : rowMap.get(map.get("field")).toString();
                            row.createCell(column).setCellValue(value);
                            column++;
                        }
                    }
                    excelRow++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



代码比较挫, 效率也低, 没办法, 因为需要按照指定的顺序生成. 也许有更好的办法, 我现在只是要按时完成需求.

这里就返回了想要的byte[].

最后一步就是在Response里返回流了.

@RequestMapping(value = "/xxx")
    public void cell(HttpServletResponse response) throws Exception {
        byte[] bytes = cellService.selectExcel();
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment;filename=" + UUIDUtil.getUUID() + ".xls");
        response.setContentLength(bytes.length);
        response.getOutputStream().write(bytes);
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }



这里注意的就是: 
response.setContentType("application/x-msdownload"); 
response.setHeader("Content-Disposition", "attachment;filename=" + UUIDUtil.getUUID() + ".xls");
一个是告诉浏览器需要下载, 下面一个就是告诉流程器下载是的文件名字. 这里我用的UUID. 

至此, 就完全OK了



    

转载于:https://my.oschina.net/vernon/blog/389039

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值