基于SpringMVC+EasyPoi,采用Excel模板方式实现Excel在线预览和导出(2021版)

一、背景:某工厂需要查看指定年度的设备维护计划,一般需要把全年72个周,每个周做哪些维护工作排班排出以及工时统计出来,在正式生成维护工单之前,需要先确认下。维护计划大概是某一周要执行哪些维护项,大概长下面这个样子,根据客户提供的资料提取Excel模板。

由于需要展示全年大约72周的排班信息(导致Excel列数较多),且维护项大约有几百项(导致Excel行数较多),综合意见,PC端提供在线预览(实现简单确认)和下载两个功能,来满足客户正式生成设备维护工单前,设备维护计划确认工作。

二、思路:一般来说poi可以提供诸如excel、word等大部分功能,但由于较低层,且实现表头固定时,编码较多。因此本次采用EasyPoi的模板功能,即表头信息放置到模板中,通过程序提供业务数据然后通过EasyPoi渲染模板得到最后结果,本次开发重点利用EasyPoi以下功能:

  1. Excel模板功能,实现利用业务数据渲染EXCEL模板功能
  2. Excel的HTML预览,实现在线预览功能
  3. 提供easypoi view,提供更加符合SpringMVC风格的实现,实现EXCEL下载功能。

本次使用的Excel模具如下,可以看到需要准备的数据有四处:维护项列表、每周的起止时间、某一维护项在哪一周执行、某周工时累计。此四种数据都需要编写业务逻辑代码获取业务数据,不再本次展示当中

三、下面开始动手实战:

1、在pom.xml文件中引入如下配置,由于本次没有用到注解或其它功能,只需要引入下面两个依赖,依赖版本请结合你项目中spring版本进行选择:

<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-base</artifactId>
	<version>3.3.0</version>
</dependency>
<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-web</artifactId>
	<version>3.3.0</version>
</dependency>

2、在配置spring元素扫描时,追加对cn.afterturn.easypoi.view包的扫描。具体需要找到项目中context:component-scan 元素所在的配置文件,将cn.afterturn.easypoi.view追加到base-package值当中,注意:多个包之间用英文逗号分隔。

<context:component-scan base-package="cn.afterturn.easypoi.view"/>

3、编写RequestMapping方法,具体思路参见方法注释,通过path传递是在线预览还是下载,根据不同的action执行不同的处理。获取设备维护计划预览模板数据实现由于涉及业务就不做展示了,具体参照EasyPoi的模板部分说明即可:

/**
 * 
 * @param action 动作,onlinePreview(预览) download(下载)
 * @param yearly 年份
 * @param modelMap easypoi需要
 * @param request
 * @param response
 * @throws IOException
 */
@RequestMapping("/{action}")
public void confirmMaintenancePlan(@PathVariable("action") String action, @RequestParam("yearly") String yearly, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws IOException {
	// 一般Excel模板统一放置到某文件夹中,该文件夹路径通过配置参数统一获取
	TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "devMaintenancePlanPreviewTemplate.xlsx");
	templateExportParams.setColForEach(true);
	// 获取设备维护计划预览模板数据
	Map<String, Object> devMaintenancePlanPreviewTemplateData = deviceMaintenanceManager.generateDevMaintenancePlanPreviewTemplateData(yearly);
	if ("onlinePreview".equals(action)) {
		// 在线预览
		Workbook workbook = ExcelExportUtil.exportExcel(templateExportParams, devMaintenancePlanPreviewTemplateData);
		ExcelToHtmlParams excelToHtmlParams = new ExcelToHtmlParams(workbook);
		response.setHeader("Content-Type", "text/html;charset=utf-8");
		response.getOutputStream().write(ExcelXorHtmlUtil.excelToHtml(excelToHtmlParams).getBytes());
	} else {
		// 下载
		// 设置下载到本地的Excel文件名
		modelMap.put(TemplateExcelConstants.FILE_NAME, yearly + "年度设备维护计划");
		// 设置模板导出参数
		modelMap.put(TemplateExcelConstants.PARAMS, templateExportParams);
		// 设置模板需要的业务数据
		modelMap.put(TemplateExcelConstants.MAP_DATA, devMaintenancePlanPreviewTemplateData);
		// 固定格式
		PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
	}
}

4、前端调用示例代码如下,一般来说预览需要在新的tab页预览,下载的话在当前页执行就行,示例代码只保留调用Controller的逻辑,其它结合自己业务处理即可:

window.open('../devplanmain/' + vm.overviewParam.action + '?yearly=' + yearNum, vm.overviewParam.action == 'onlinePreview' ? '_blank' : '');

5、预览结果在文章开头处已做展示,下面直接展示下载的Excel部分内容:

注意:

  1. 实现过程中建议按照Excel模板渲染、Excel预览、Excel下载三步,一步步进行,不要混为一谈,一旦发生问题会发蒙。分开走的好处是缩小问题范围便于解决。
  2. 不要把Excel模板渲染看的多么高端,它只是把服务器端已处理完毕的数据,按照设定显示到对应位置,比如我上面的黑色圆点,这些圆点都是在服务端计算出来,然后已字符串的形式写好的,渲染只是原样输出。
  3. 不建议在Excel模板中使用Excel函数。比如上述的工时累计有人可能说利用公式结合生产/非生产*人次是可以计算出来的,但实际是在服务端计算好,拿到页面直接渲染的,并不是利用函数计算的。再比如上面的每周的起止时间以及每周都有哪些维护需要做,都是在服务器端就已经完成标识的。

以上,完了!

猜你喜欢

转载自blog.csdn.net/yu102655/article/details/112134069