概述
目录
一、简介
二、代码实现
三、总结
一、简介
最近项目中有个需求,需要根据后台配置的一些参数动态生成Excel导入模板,Excel表头是动态查询数据库获取的。下面具体看代码实现。
二、代码实现
(1). 控制层代码:
@ApiOperation(value = "下载测评项分数导入模板", notes = "下载测评项分数导入模板", httpMethod = "POST")
@ApiImplicitParams({ @ApiImplicitParam(paramType = "body", name = "request", value = "参数", required = true, dataType = "HttpServletRequest"),
@ApiImplicitParam(paramType = "body", name = "response", value = "参数", required = true, dataType = "HttpServletResponse"), })
@RequestMapping(value = "/exportDynamicExcelTemplate", method = RequestMethod.GET)
public void exportDynamicExcelTemplate(HttpServletRequest request, HttpServletResponse response) {
// 当前导入的环节ID
String cphjid = request.getParameter("cphjid");
// 1.创建Excel模板工作簿对象(动态组装表头、必填标识等)
XSSFWorkbook xssfWorkbook = hjcpxqService.createXSSFWorkbook(cphjid);
// 2.导出的Excel模板文件名称
DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
StringBuilder fileName = new StringBuilder("测评项分数导入模板表").append(dateFormat.format(new Date())).append(".xlsx");
// 3.清空response
response.reset();
// 4.设置response的Header
String excelFileName;
OutputStream os = null;
try {
// 需要指定文件名的编码方式为ISO-8859-1,否则会出现文件名中的中文字符丢失的问题
excelFileName = new String(fileName.toString().getBytes("gb2312"), "ISO-8859-1");
response.addHeader("Content-Disposition", "attachment;filename=" + excelFileName);
os = new BufferedOutputStream(response.getOutputStream());
// 5.设置消息头内容格式,并指定编码格式
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// 6.将Excel写入到输出流中
xssfWorkbook.write(os);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 7. 关闭文件流
try {
if (null != os) {
os.flush();
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里需要注意的地方:
【a】需要指定文件名的编码方式为ISO-8859-1,否则会出现文件名中的中文字符丢失的问题:
excelFileName = new String(fileName.toString().getBytes("gb2312"), "ISO-8859-1");
【b】注意这个是.xlsx后缀的Excel, .xls的是application/vnd.ms-excel,.xlsx的如下所示:
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
(2). 业务层代码:
@Override
public XSSFWorkbook createXSSFWorkbook(String cphjid) {
/**
* 1.动态组装Excel表头列标题
*/
// 根据环节ID查询环节对应的导入模板信息
List<Map<String, Object>> templateList = cpxMbdrbService.getImportTemplateByHjid(cphjid);
List<Map<String, Object>> titleHeaders = new ArrayList<>();
Map<String, Object> xhMap = new HashMap<>();
Map<String, Object> xmMap = new HashMap<>();
xhMap.put("TYPE", "FIXED");
xhMap.put("VALUE", EXCEL_HEADER_XH);
xmMap.put("TYPE", "FIXED");
xmMap.put("VALUE", EXCEL_HEADER_NAME);
titleHeaders.add(xmMap);
titleHeaders.add(xhMap);
if (CollectionUtils.isNotEmpty(templateList)) {
HashMap<String, Object> cpxmcMap = null;
for (Map<String, Object> map : templateList) {
// 测评项名称
String cpxmc = null != map.get("LABEL") ? map.get("LABEL").toString() : "";
cpxmcMap = new HashMap<>();
cpxmcMap.put("TYPE", "LABEL");
cpxmcMap.put("VALUE", cpxmc);
titleHeaders.add(cpxmcMap);
}
}
/**
* 2.设置Excel工作簿信息、Excel样式等
*/
// 创建一个工作簿(Excel的文档对象)
XSSFWorkbook xssfWorkbook = new XSSFWorkbook();
// 创建一个Sheet(Excel的表单)
XSSFSheet xssfSheet = xssfWorkbook.createSheet("测评项分数导入模板表");
// 创建Excel表头(rowNum:0表示表头),从0开始
XSSFRow xssfRow = xssfSheet.createRow(1);
// 设置缺省列高
xssfSheet.setDefaultRowHeightInPoints(25);
// 设置行的高度
xssfRow.setHeightInPoints(25);
// 格子单元样式
XSSFCellStyle xssfCellStyle = xssfWorkbook.createCellStyle();
XSSFFont xssfFont = xssfWorkbook.createFont();
// 设置字体加粗
xssfFont.setBold(true);
// 设置“等线”字体
xssfFont.setFontName("等线");
// 设置字体大小(14号)
xssfFont.setFontHeightInPoints((short) 14);
xssfCellStyle.setFont(xssfFont);
// 设置水平居中
xssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
// 设置垂直居中
xssfCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置表格默认列宽度为15个字节
xssfSheet.setDefaultColumnWidth((short) 16);
/**
* 3.Excel第一行: 合并单元格可以说明导入注意事项等
*/
// 在sheet里创建第一行,参数为行索引(excel的行)
XSSFRow firstRow = xssfSheet.createRow(0);
firstRow.setHeightInPoints(90);
// 创建单元格(excel的单元格,参数为列索引)
XSSFCell firstCell = firstRow.createCell(0);
// 合并单元格, 参数依次表示起始行(0),截至行(0),起始列(0), 截至列(titleHeaders.size() - 1)
xssfSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, titleHeaders.size() - 1));
// 设置单元格内容
firstCell.setCellValue("测评项分数导入提示:n 1.红色字体代表必填项;n 2.分数必须按照指定格式填写;n 3.线下导入可能会覆盖线上测评的分数;");
CellStyle firstRowCellStyle = xssfWorkbook.createCellStyle();
// 左对齐
firstRowCellStyle.setAlignment(HorizontalAlignment.LEFT);
// 顶端对齐
firstRowCellStyle.setVerticalAlignment(VerticalAlignment.TOP);
// 强制单元格内容换行
// 必须加上setWrapText(true)才能强制换行
firstRowCellStyle.setWrapText(true);
XSSFFont tipFont = xssfWorkbook.createFont();
// 设置“华文楷体”字体
tipFont.setFontName("华文楷体");
tipFont.setColor(IndexedColors.RED.getIndex());
// 设置字体大小
tipFont.setFontHeightInPoints((short) 14);
firstRowCellStyle.setFont(tipFont);
firstCell.setCellStyle(firstRowCellStyle);
/**
* 4.Excel表头、内容
*/
XSSFFont contentFont = xssfWorkbook.createFont();
XSSFCellStyle contentCellStyle;
// Excel模板表头相关信息设置 导出的Excel的标题列
for (int i = 0; i < titleHeaders.size(); i++) {
Map<String, Object> titleHeader = titleHeaders.get(i);
XSSFCell cell = xssfRow.createCell(i);
String type = titleHeader.get("TYPE").toString();
String value = titleHeader.get("VALUE").toString();
String realText = value;
if (value.length() > 7) {
realText = value.substring(0, 7) + "...";
}
XSSFRichTextString text = new XSSFRichTextString(realText);
cell.setCellValue(text);
// 设置批注 (对表头超长的时候,设置一些提示信息)
Sheet sheet = cell.getSheet();
Drawing p = sheet.createDrawingPatriarch();
XSSFClientAnchor an = new XSSFClientAnchor(0, 0, 0, 0, 3, 0, 5, 5);
Comment comment = p.createCellComment(an);
XSSFRichTextString rtf = new XSSFRichTextString(value);
Font commentFormatter = sheet.getWorkbook().createFont();
rtf.applyFont(commentFormatter);
comment.setString(rtf);
cell.setCellComment(comment);
switch (type) {
case "FIXED":
// 设置字体样式等
contentCellStyle = this.buildContentCellStyle(contentFont, xssfWorkbook);
cell.setCellStyle(contentCellStyle);
break;
case "LABEL":
cell.setCellStyle(xssfCellStyle);
break;
default:
break;
}
}
return xssfWorkbook;
}
/**
* 组装Excel必填项的一些样式
*/
private XSSFCellStyle buildContentCellStyle(XSSFFont contentFont, XSSFWorkbook xssfWorkbook) {
XSSFCellStyle contentCellStyle = xssfWorkbook.createCellStyle();
// 粗体
contentFont.setBold(true);
// 字体颜色
contentFont.setColor(IndexedColors.RED.getIndex());
contentFont.setFontName("等线");
// 设置字体大小
contentFont.setFontHeightInPoints((short) 14);
contentCellStyle.setFont(contentFont);
// 水平居中
contentCellStyle.setAlignment(HorizontalAlignment.CENTER);
// 垂直居中
contentCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
// 设置图案样式
contentCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// 设置图案颜色
contentCellStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
return contentCellStyle;
}
以上代码有几点主要注意的地方:
【a】注意excel表格头部如果出现超长,可以参照我这里的处理方式,当然可能还有更好的方式,大家都可以尝试一下;
【b】注意excel文档一般都有一些提示语,注意在excel中强制换行的使用方法;
【c】注意可以为excel表头设置一些必填的标识等等;
(3). 运行结果如下:
前端调用方式:
<a href={`api/sm-comprehensive-evaluation/evaluationMng/exportDynamicExcelTemplate?cphjid=${this.props.cphjid}`} target={'_blank'}>
由于笔者使用的是react,所以支持上面的语法。
后端动态excel表头配置:
表头内容超出单元格的宽度时的一种处理方法,对表头内容进行截取,使用省略号代替,然后创建一个批注,鼠标悬停上去会提示表头的全部内容.
三、总结
以上就是关于POI操作Excel动态生成导入模板的示例,需要注意的地方就是.xls和.xlsx两种格式的excel的contentType不一致,必须要设置对,使用的Excel API相关对象也不一致,笔者踩过这个坑,在这里提醒一下,避免大家再次踩这个坑,本文只是笔者的一些学习总结和见解,大家如果需要相关的需求可以参考下,如果有更好的用法欢迎大家提出来,共同学习共同进步!
最后
以上就是仁爱短靴为你收集整理的POI动态下载Excel模板案例的全部内容,希望文章能够帮你解决POI动态下载Excel模板案例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复