admin管理员组文章数量:1644032
目录
- freemarker生成word文件并导出
- 一、环境准备
- 二、编写代码
- 1.实体类
- 2.mapper.xml文件
- 3.mapper.java文件
- 4.Service.java
- 5.ServiceImpl.java
- 6.wordUtil工具类(重点)
- 7.controller文件(重点)
- 8.前端文件
- 三、处理模板文件
- 1.填好最初的word文件
- 2.word文件转xml文件
- 3.利用xml文件生成ftl模板文件
freemarker生成word文件并导出
根据前端选择的表格数据生成word表格文档。要对若依字典数据进行处理,使导出的是字典标签(如:合格、不合格),而不是字典值(0,1)。同时实现下载好生成的word文件后,自动删除存储的生成文件,避免冗余。
一、环境准备
(1)JDK1.8
(2)SpringBoot2.3.7.RELEASE
(3)Freemarker 2.3.28
主要是导入freemarker
<!-- freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
二、编写代码
1.实体类
在下图位置创建一个实体类,内容是需要导出的数据和对应的get,set方法。同时在其中做好对字典数据的处理。
代码如下:
package com.ruoyi.system.domain.TempEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.system.domain.DataApparatus;
import com.ruoyi.system.domain.vo.DataApparatusCheckSchemeVo;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
public class TempDataApparatusCheckScheme extends BaseEntity {
/** 检/校参量 */
@Excel(name = "检/校参量")
private String checkParameter;
/** 检/校范围 */
@Excel(name = "检/校范围")
private String checkRange;
/** 检/校依据 */
@Excel(name = "检/校依据")
private String checkBasis;
/** 检定单位 */
@Excel(name = "检定单位")
private String checkUnit;
/** 备注 */
@Excel(name = "备注")
private String rmk;
/** 检/校结果 */
@Excel(name = "检/校结果")
private String checkResult;
/** 仪器设备名称 */
@Excel(name = "仪器设备名称")
private String apparatusName;
/** 实验室编号(字典) */
@Excel(name = "实验室编号(字典)")
private String labId;
/** 仪器设备型号 */
@Excel(name = "仪器设备型号")
private String apparatusModel;
/** 出厂编号 */
@Excel(name = "出厂编号")
private String factoryNum;
/** 使用部门(字典) */
@Excel(name = "使用部门(字典)")
private String userDepartment;
/** 检/校周期 */
@Excel(name = "检/校周期")
private String checkCycle;
public String getCheckParameter() {
return checkParameter;
}
public void setCheckParameter(String checkParameter) {
this.checkParameter = checkParameter;
}
public String getCheckRange() {
return checkRange;
}
public void setCheckRange(String checkRange) {
this.checkRange = checkRange;
}
public String getCheckBasis() {
return checkBasis;
}
public void setCheckBasis(String checkBasis) {
this.checkBasis = checkBasis;
}
public String getCheckUnit() {
return checkUnit;
}
public void setCheckUnit(String checkUnit) {
this.checkUnit = checkUnit;
}
public String getRmk() {
return rmk;
}
public void setRmk(String rmk) {
this.rmk = rmk;
}
public String getCheckResult() {
return checkResult;
}
public void setCheckResult(String checkResult) {
this.checkResult = checkResult;
}
public String getApparatusName() {
return apparatusName;
}
public void setApparatusName(String apparatusName) {
this.apparatusName = apparatusName;
}
public String getLabId() {
return labId;
}
public void setLabId(String labId) {
this.labId = labId;
}
public String getApparatusModel() {
return apparatusModel;
}
public void setApparatusModel(String apparatusModel) {
this.apparatusModel = apparatusModel;
}
public String getFactoryNum() {
return factoryNum;
}
public void setFactoryNum(String factoryNum) {
this.factoryNum = factoryNum;
}
public String getUserDepartment() {
return userDepartment;
}
public void setUserDepartment(String userDepartment) {
this.userDepartment = userDepartment;
}
public String getCheckCycle() {
return checkCycle;
}
public void setCheckCycle(String checkCycle) {
this.checkCycle = checkCycle;
}
public TempDataApparatusCheckScheme(DataApparatusCheckSchemeVo s, HashMap<String, ArrayList<SysDictData>> dictmap){
this.labId = s.getLabId();
this.apparatusName = s.getApparatusName();
this.apparatusModel = s.getApparatusModel();
this.factoryNum = s.getFactoryNum();
this.userDepartment = s.getUserDepartment();
this.checkCycle = s.getCheckCycle();
this.checkParameter = s.getCheckParameter();
this.checkRange = s.getCheckRange();
this.checkBasis = s.getCheckBasis();
this.checkUnit = s.getCheckUnit();
this.rmk = s.getRmk();
//check result
for( SysDictData dictData:dictmap.get("check_result")){
if(dictData.getDictValue().equals(s.getCheckResult())){
this.checkResult =dictData.getDictLabel();
break;
}
}
}
public String toString() {
return "TempDataApparatusCheckScheme{" +
"labId=" + labId +
", apparatusName='" + apparatusName + '\'' +
", apparatusModel='" + apparatusModel + '\'' +
", factoryNum='" + factoryNum + '\'' +
", userDepartment='" + userDepartment + '\'' +
", checkCycle='" + checkCycle + '\'' +
", checkParameter='" + checkParameter + '\'' +
", checkRange='" + checkRange + '\'' +
", checkBasis='" + checkBasis + '\'' +
", checkUnit='" + checkUnit + '\'' +
", checkResult='" + checkResult + '\'' +
", rmk='" + rmk + '\'' +
'}';
}
}
2.mapper.xml文件
修改mapper.xml文件。增加根据前端传来的数组查询数据的方法。
<!-- 根据ID数组 查询所有的检校信息 -->
<select id="selectDataApparatusCheckSchemeByIds" parameterType="Long" resultMap="DataApparatusCheckSchemeVoResult">
<include refid="selectDataApparatusCheckSchemeVo" />
where data_apparatus_check_scheme.id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</select>
3.mapper.java文件
/**
* 根据ID数组查询仪器设备校准方案列表
* @param ids 仪器设备校准方案主键集合
* @return 仪器设备校准方案列表集合
*/
public List<DataApparatusCheckSchemeVo> selectDataApparatusCheckSchemeByIds(Long[] ids);
4.Service.java
/**
* 根据ID数组查询仪器校准方案列表
* @param ids 仪器设备检校方案主键集合
* @return 仪器设备校准方案集合
*/
public List<DataApparatusCheckSchemeVo> selectDataApparatusCheckSchemeByIds(Long[] ids);
5.ServiceImpl.java
/**
* 根据ID数组查询仪器设备校准方案列表
* @param ids
* @return
*/
@Override
public List<DataApparatusCheckSchemeVo> selectDataApparatusCheckSchemeByIds(Long[] ids) {
return dataApparatusCheckSchemeMapper.selectDataApparatusCheckSchemeByIds(ids);
}
6.wordUtil工具类(重点)
在下图所示位置建立wordUtil工具类,用于生成word文档以及其他相关操作
代码如下:
package com.ruoyi.common.utils.file;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Version;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;
/**
* @ClassName WordUtil
* @Description 使用Freemarker生成Word文档工具类
* @Author ruoyi
* @Date 2022/6/15 10:06
**/
public class WordUtil {
/**
* 使用Freemarker自动生成Word文档
* @param dataMap 保存Word文档中所需要的数据
* @param templatePath 模板文件的绝对路径
* @param templateFile 模板文件的名称
* @param generateFile 生成文件的路径+名称
* @throws Exception
*/
/** 原版生成word方法 */
public static void generateWord(Map<String, Object> dataMap, String templatePath,String templateFile, String generateFile) {
// 设置FreeMarker的版本
Configuration configuration = new Configuration(new Version("2.3.28"));
// 设置Freemarker的编码格式
configuration.setDefaultEncoding("UTF-8");
Writer out = null;
try{
// 设置FreeMarker生成Word文档所需要的模板的路径
configuration.setDirectoryForTemplateLoading(new File(templatePath));
// 设置FreeMarker生成Word文档所需要的模板名称
Template t = configuration.getTemplate(templateFile, "UTF-8");
// 创建一个Word文档的输出流
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(generateFile)), "UTF-8"));
//FreeMarker使用Word模板和数据生成Word文档
t.process(dataMap, out);
} catch (Exception e) {
e.printStackTrace();
}
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 新的生成word方法 */
public static void CreateWord(HttpServletResponse resp, HttpServletRequest req,Map<String, Object> dataMap, String templatePath,String templateFile, String generateFile) {
// 设置FreeMarker的版本
Configuration configuration = new Configuration(new Version("2.3.28"));
// 设置Freemarker的编码格式
configuration.setDefaultEncoding("UTF-8");
String str = DateUtils.dateTimeNow() + ".doc";
Writer out = null;
try{
// 设置FreeMarker生成Word文档所需要的模板的路径
configuration.setDirectoryForTemplateLoading(new File(templatePath));
// 设置FreeMarker生成Word文档所需要的模板名称
Template t = configuration.getTemplate(templateFile, "UTF-8");
// 创建一个Word文档的输出流
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(generateFile)), "UTF-8"));
//FreeMarker使用Word模板和数据生成Word文档
t.process(dataMap, out);
//下载生成好的Word文档
downloadFile(generateFile,str,resp,req);
} catch (Exception e) {
e.printStackTrace();
}
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/********************************************/
/**
* 下载文件
* @param path 文件的位置
* @param fileName 自定义下载文件的名称
* @param resp http响应
* @param req http请求
*/
public static void downloadFile(String path, String fileName, HttpServletResponse resp, HttpServletRequest req){
System.out.println("开始下载到本地");
try {
File file = new File(path);
/**
* 中文乱码解决
*/
String type = req.getHeader("User-Agent").toLowerCase();
if(type.indexOf("firefox")>0 || type.indexOf("chrome")>0){
/**
* 谷歌或火狐
*/
fileName = new String(fileName.getBytes("utf-8"), "iso8859-1");
}else{
/**
* IE
*/
fileName = URLEncoder.encode(fileName, "utf-8");
}
// 设置响应的头部信息
resp.setHeader("content-disposition", "attachment;filename=" + fileName);
// 设置响应内容的类型
resp.setContentType(getFileContentType(fileName)+"; charset= utf-8");
// 设置响应内容的长度
resp.setContentLength((int) file.length());
// 输出
outStream(new FileInputStream(file), resp.getOutputStream());
} catch (Exception e) {
System.out.println("执行downloadFile发生了异常:" + e.getMessage());
}
}
/**
* 文件的内容类型
*/
private static String getFileContentType(String name){
String result = "";
String fileType = name.toLowerCase();
if (fileType.endsWith(".png")) {
result = "image/png";
} else if (fileType.endsWith(".gif")) {
result = "image/gif";
} else if (fileType.endsWith(".jpg") || fileType.endsWith(".jpeg")) {
result = "image/jpeg";
} else if(fileType.endsWith(".svg")){
result = "image/svg+xml";
}else if (fileType.endsWith(".doc")) {
result = "application/msword";
} else if (fileType.endsWith(".xls")) {
result = "application/x-excel";
} else if (fileType.endsWith(".zip")) {
result = "application/zip";
} else if (fileType.endsWith(".pdf")) {
result = "application/pdf";
} else {
result = "application/octet-stream";
}
return result;
}
/**
* 基础字节数组输出
*/
private static void outStream(InputStream is, OutputStream os) {
try {
byte[] buffer = new byte[10240];
int length = -1;
while ((length = is.read(buffer)) != -1) {
os.write(buffer, 0, length);
os.flush();
}
} catch (Exception e) {
System.out.println("执行 outStream 发生了异常:" + e.getMessage());
} finally {
try {
os.close();
} catch (IOException e) {
}
try {
is.close();
} catch (IOException e) {
}
}
}
/**
* 检查存储生成文件的路径是否存在,如果不存在则新建路径.
* @param directory the directory name, like '\dir-name'
*/
public static void CheckDownloadPath(String directory){
File path=new File(RuoYiConfig.getDownloadPath()+directory);
if(!path.exists()){
path.mkdirs();
}
}
}
7.controller文件(重点)
在controller中调用工具类生成word
/**
* 导出仪器校准方案列表
*/
@PreAuthorize("@ss.hasPermi('system:scheme:export')")
@Log(title = "仪器校准方案", businessType = BusinessType.EXPORT)
@PostMapping("/export/{ids}")
public void export(HttpServletResponse resp, HttpServletRequest req, @PathVariable Long[] ids)
{
//获取仪器设备检校列表
List<DataApparatusCheckSchemeVo> list = dataApparatusCheckSchemeService.selectDataApparatusCheckSchemeByIds(ids)
//获取字典
HashMap<String, ArrayList<SysDictData>> dictData = dictDataService.getAllDictDataMap();
//生成结果集
Map<String, Object> dataMap = new HashMap<String,Object>();
ArrayList<TempDataApparatusCheckScheme> resultList=new ArrayList<TempDataApparatusCheckScheme>();
for (DataApparatusCheckSchemeVo s:list){
resultList.add(new TempDataApparatusCheckScheme(s,dictData));
}
dataMap.put("schemeList",resultList);
//设置生成文件存储路径
String directory="/schemeList";
WordUtil.CheckDownloadPath(directory);
//生成文件
WordUtil.CreateWord(resp,req,dataMap,"ruoyi-system\\src\\main\\resources\\template\\dataApparatusCheckScheme","BKJC-CX-007-2.ftl"
, RuoYiConfig.getDownloadPath()+directory+"/BKJC-CX-007-2.doc");
//下载后删除生成文件
FileUtils.deleteFile(RuoYiConfig.getDownloadPath()+directory+"/BKJC-CX-007-2.doc");
}
http://t.csdn/iZpPv中描述了获取全部若依全部字典的方法
8.前端文件
js文件
// 导出仪器校准方案
export function exportScheme(ids){
return request({
url:'/system/scheme/export/' + ids,
method: 'post'
})
}
index.vue
/** 导出按钮操作 */
handleExport() {
let schemeNum=this.ids.length;
if(schemeNum<1){
this.$message.error('未选择需要导出的设备仪器检校信息,请勾选需要导出的设备仪器检校信息!');
}
else{
exportScheme(this.ids).then(response =>{
let data = new Blob([response], { type: 'application/msword,charset=utf-8' });
let fileDate = new Date();
let fileYear = fileDate.getFullYear();
let fileMonth = (fileDate.getMonth()+1).toString().padStart(2,'0');
let fileDay = fileDate.getDate().toString().padStart(2,'0');
var fileHour = fileDate.getHours().toString().padStart(2,'0')
var fileMin = fileDate.getMinutes().toString().padStart(2,'0')
if (typeof window.chrome !== 'undefined') {undefined
// chrome
const link = document.createElement('a');
link.href = window.URL.createObjectURL(data);
link.download = fileYear+fileMonth+fileDay+fileHour+fileMin+"仪器设备检校表";
link.click();
} else if (typeof window.navigator.msSaveBlob !== 'undefined') {undefine
// IE
const blob = new Blob([data], {type: 'application/force-download'});
window.navigator.msSaveBlob(blob, "BKJC-CX-007-2");
} else {undefined
// Firefox
const file = new File([data], "BKJC-CX-007-2", {type: 'application/force-download'});
window.open(URL.createObjectURL(file));
}
})
}
三、处理模板文件
1.填好最初的word文件
2.word文件转xml文件
3.利用xml文件生成ftl模板文件
将保存好的xml文件用vsCode打开,vsCode安装XML Tools插件用于格式化xml文件。
xml文件格式化后,找到如下图的表格数据
如果${}形式的占位符中的内容被分隔开了,我们需要手动删除掉中间内容。
将所有表格数据处理好后折叠,在外部包裹如下代码:
<#list schemeList as scheme>
</#list>
完成后如下所示:
注意
①schemeList要与controller代码中保持一致
②as是给schemeList起别名的作用
③scheme就是userList的别名,这样在xml中就可以用scheme.
全部完成后将文件另存为ftl格式即可。
最后将word、xml、ftl三个文件放入项目如图位置。其中ftl文件是真正的模板文件,其余两个文件是中间文件,没有实际作用。
本文标签: 文件SpringBoot若依wordFreemarker
版权声明:本文标题:若依 springboot 使用freemarker生成word文件,并导出下载 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729381382a1199146.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论