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了
时间: 2024-11-05 21:54:01