springMVC和FreeMarker简单方式导出excel

本文介绍如何利用Spring MVC和FreeMarker框架通过输出HTML格式的XLS文件实现Excel导出功能。该方法适用于仅需导出数据而不涉及复杂Excel格式化的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般Java操作excel文件比较流行的是apache poi包。

因为我们只是导出数据,不需要读取正规的excel文件,所以我们可以通过输出html格式的xls文件来简单实现导出excel。

环境使用的springMVC,展示使用的是FreeMarker

Action

        @RequestMapping(value="export")
	public String sfnExport(HttpServletRequest request,HttpServletResponse response){
		String export_type = request.getParameter("export_type");
		request.setAttribute("export_type", export_type);
		
		Map<String,Integer> mapYearMonth =  setYearMonth(request);
		
		List<ProjSatisfaction> dataFrom = projSatisfactionService.findProjects(mapYearMonth.get("year"), mapYearMonth.get("month"), false);
		List<ProjSatisfaction> dataTo = projSatisfactionService.findProjects(mapYearMonth.get("year"), mapYearMonth.get("month"), true);
		
		request.setAttribute("dataFromList", dataFrom);
		request.setAttribute("dataToList", dataTo);
		// 获取统计信息
		request.setAttribute("sum", projSatisfactionService.getStatistics(mapYearMonth.get("year"), mapYearMonth.get("month")));
		
		// 导出xls类型的html文件
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String export_date = sdf.format(new Date());
		request.setAttribute("export_date", export_date);
		String fileName = mapYearMonth.get("year")+"年"+ mapYearMonth.get("month")+"月服务评价统计_"+export_date+".xls";
		response.setContentType("application/x-download");
		response.setCharacterEncoding("UTF-8");
		response.addHeader("Content-Disposition", "attachment;filename=" + StringHelper.convertTitle(fileName));
		return "/sfn/export";
	}
ftl

<html xmlns:v="urn:schemas-microsoft-com:vml"
	xmlns:o="urn:schemas-microsoft-com:office:office"
	xmlns:x="urn:schemas-microsoft-com:office:excel"
	xmlns="http://www.w3.org/TR/REC-html40">
<html>
<head>
<title>导出服务评价结果</title>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Excel.Sheet" />

<style>
body {
	font-family: "微软雅黑 宋体";
	font-size: 14px;
}

table {
	border: 0.5pt solid #888;
}

table td,table th {
	border: 0.5pt solid #888;
}

.align_center {
	text-align: center;
}
.noborder{
	border:none;
}
</style>

</head>

<body>
	<table id="table_main" >
		<col width="39"  style='mso-width-source:userset;mso-width-alt:1300;'/>
   		<col width="300"  style='mso-width-source:userset;mso-width-alt:6000;'/>
   		<col width="112"  style='mso-width-source:userset;mso-width-alt:6000;'/>
   		<col width="67"  style='mso-width-source:userset;mso-width-alt:2500;'/>
   		<col width="39" style='mso-width-source:userset;mso-width-alt:1300;'/>
   		<col width="53" style='mso-width-source:userset;mso-width-alt:1696;'/>
   		<col width="72" style='mso-width-source:userset;mso-width-alt:2304;'/>
		<!-- 1st line -->
		<tr>
			<td class="align_center" colspan="7">
				<h3>服务评价结果</h3>
			</td>
		</tr>
		<tr>
			<td class="align_center" colspan="3">
				数据时间:${select_year}年${select_month}月
			</td>
			<td class="align_center" colspan="4">
				导出时间:${export_date}
			</td>
		</tr>

		<!-- 2nd line -->
		<tr>
			<td class="align_center" colspan="7">
				<h4>统计信息</h4>
			</td>
		</tr>
		<tr>
			<th>总数</th>
			<th>未审核项目数</th>
			<th>已审核项目数</th>
			<th style="color:#FF00FF;">非常满意</th>
			<th style="color:#0000FF;">满意</th>
			<th style="color:#008000;">一般</th>
			<th style="color:#FF0000;">不满意</th>
		</tr>
		<tr>
			<td class="align_center">${sum["all"]}</td>
			<td class="align_center">${sum["normal"]}</td>
			<td class="align_center">${sum["approve"]}</td>
			<td class="align_center" style="color:#FF00FF;">${sum["level1"]}</td>
			<td class="align_center" style="color:#0000FF;">${sum["level2"]}</td>
			<td class="align_center" style="color:#008000;">${sum["level3"]}</td>
			<td class="align_center" style="color:#FF0000;">${sum["level4"]}</td>
		</tr>
		<!-- 3rd line -->
		<tr>
			<td class="align_center" colspan="7">
				<h4>未审核项目评价 <#if export_type="_3_4_"> (一般与不满意) </#if></h4></td>
		</tr>
		<tr>
			<th>编号</th>
			<th>未审核项目编码</th>
			<th>未审核项目名称</th>
			<th>审核结果</th>
			<td colspan="3" class="noborder"></td>
		</tr>
		<#assign index = 1> 
		<#list dataFromList as data>
		<#if data.assesslevel == 1>
			<#assign levelColor="#FF00FF">
		<#elseif data.assesslevel == 2>
			<#assign levelColor="#0000FF">
		<#elseif data.assesslevel == 3>
			<#assign levelColor="#008000">
		<#elseif data.assesslevel == 4>
			<#assign levelColor="#FF0000">
		</#if> 
		<#if export_type == "all" || export_type?contains(data.assesslevel+"")>
		<tr>
			<td x:num>${index}</td>
			<td x:str>${data.projectId}</td>
			<td x:str>${data.projectName}</td>
			<td class="align_center" style="color:${levelColor};" x:str>${data.assessResult}</td>
			<td colspan="3" class="noborder"></td>
		</tr>
		<#assign index=index+1> 
		</#if> 
		</#list>
		
		<!-- 4th line -->
		<tr class="align_center">
			<td colspan="7">
				<h4>已审核项目评价 <#if export_type="_3_4_"> (一般与不满意) </#if></h4>
			</td>
		</tr>
		<tr>
			<th>编号</th>
			<th>已审核项目编码</th>
			<th>已审核项目名称</th>
			<th>审核结果</th>
			<td colspan="3" class="noborder"></td>
		</tr>
		<#assign index = 1> 
		<#list dataToList as data>
		<#if data.assesslevel == 1>
			<#assign levelColor="#FF00FF">
		<#elseif data.assesslevel == 2>
			<#assign levelColor="#0000FF">
		<#elseif data.assesslevel == 3>
			<#assign levelColor="#008000">
		<#elseif data.assesslevel == 4>
			<#assign levelColor="#FF0000">
		</#if>  
		<#if export_type == "all" || export_type?contains(data.assesslevel+"")>
		<tr>
			<td x:num>${index}</td>
			<td x:str>${data.projectId}</td>
			<td x:str>${data.projectName}</td>
			<td class="align_center" style="color:${levelColor};" x:str>${data.assessResult}</td>
			<td colspan="3" class="noborder"></td>
		</tr>
		<#assign index=index+1> 
		</#if> 
		</#list>
	</table>
</body>
</html>

主要分析一下ftl文件内容

1.要声明以下命名空间

<html xmlns:v="urn:schemas-microsoft-com:vml"
	xmlns:o="urn:schemas-microsoft-com:office:office"
	xmlns:x="urn:schemas-microsoft-com:office:excel"
	xmlns="http://www.w3.org/TR/REC-html40">

2.x:num 代表此格是数据类型,x:str代表此格式字符类型,这个很重要,如果你要显示的字符中都是数字,在不设置此字符的情况下,过长的内容会被excel显示成科学计数格式。

<td x:num>${index}</td>
<td x:str>${data.projectId}</td>
3. 最好不要多个表格嵌套,将多个表格统一为一个表,这样才能设置col,控制每一列的宽度。否则很多地方不可控制的换行不美观。width 和mso-width-alt 参数是1:32的比例,但我只发现设置mso-width-alt有用,所以下面有几组数据width和mso-width-alt对不上是因为我只更改了mso-width-alt参数。不知道width参数可能会在什么情况下有用,目前先保留了。

<col width="39"  style='mso-width-source:userset;mso-width-alt:1300;'/> 
<col width="300"  style='mso-width-source:userset;mso-width-alt:6000;'/>
<col width="112"  style='mso-width-source:userset;mso-width-alt:6000;'/>
<col width="67"  style='mso-width-source:userset;mso-width-alt:2500;'/>
<col width="39" style='mso-width-source:userset;mso-width-alt:1300;'/>
<col width="53" style='mso-width-source:userset;mso-width-alt:1696;'/>
<col width="72" style='mso-width-source:userset;mso-width-alt:2304;'/>

4.action中转换方法,保障中文文件名不会乱码

        public static String convertTitle(String title){
		String str = "";
		try {
			str = new String( title.replaceAll(" ", "_").getBytes("gb2312"), "ISO8859-1" );
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return str;
	}


SpringBoot_Freemarker生成Word_多个表格+两层嵌套循环; 步骤说明: 1.用Microsoft Office Word打开word原件;将文档中需要动态生成的内容,替换为属性名 ${name} 2.另存为,选择保存类型Word 2003 XML 文档(*.xml) 3.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容; 4. 文档生成后有时需要手动修改,查找第一步中设置的属性名,可能会产生类似${n.....ame}类似的样子,我们将将名字中间的标签删掉,恢复为${name} 5. word模板中有表格,需要循环的位置, 用 标签将第二对 标签(即除表头的w:tr标签后的一对)包围起来 同时表格内的属性例如${name},在这里需要修改为${user.name} (userList是集合在dataMap中的key, user是集合中的每个元素, 类似), 如图: PLUS:若表格之外还有嵌套的循环,也需要用,注意这里的标签不要某对其他标签交叉,不可以出现这种 6. 标识替换完之后,另存为.ftl后缀文件即可。 代码里是相对有一丢丢复杂的,两层嵌套循环; 总(dataMap) deptName 部门名 list(Table)表的集合 table1(map) table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table2 table-名字 ${map.table} tableName-中文名 ${map.tableName} columnCount-字段数 ${map.columnCount} recordCount-记录数 ${map.recordCount} listA-List--表格1 map.listA column Model属性——字段名 ${model.column} columnName Model属性——字段中文名 ${model.column} rate Model属性——字段占比 ${model.rate} nullValueCount Model属性——字段空值数 ${model.nullValueCount} listB-List--表格2 map.listB …… listC-List--表格3 map.listC …… table3 ……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值