一、pom
<!-- freemarker-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
二、类
实体类
package com.ruoyi.quartz.domain.entity;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.quartz.util.data.ErrEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import com.ruoyi.common.annotation.Excel;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* 模拟测点的实时数据对象 simulation_measurepoint_date
*
* @author eleven
* @date 2022-11-28
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimulationMeasurepointData extends BaseEntity
{
/** $column.columnComment */
private Integer id;
/** 测点信息ID */
@Excel(name = "测点信息ID")
private Integer measurepointid;
/**测点名称*/
private String measuringpointname;
/**抽采单元名称*/
private String unitname;
/** 所属抽采单元ID */
@Excel(name = "所属抽采单元ID")
private Integer drainageunitid;
/**所属工作面名称*/
private String workingfacename;
/** 所属工作面ID */
@Excel(name = "所属工作面ID")
private Integer workfaceid;
/** 混合流量 */
@Excel(name = "混合流量")
private Double mixtureflow;
/** 纯流量 */
@Excel(name = "纯流量")
private Double pureflow;
/** 温度 */
@Excel(name = "温度")
private Double temperature;
/** 甲烷浓度 */
@Excel(name = "甲烷浓度")
private Double ch4concentration;
/** 一氧化碳浓度 */
@Excel(name = "一氧化碳浓度")
private Double coconcentration;
/** 抽采负压 */
@Excel(name = "抽采负压")
private Double negativepressure;
/** 二氧化碳浓度 */
@Excel(name = "二氧化碳浓度")
private Double co2concentration;
/** 累计抽采混合流量 */
@Excel(name = "累计抽采混合流量")
private Long totalmixtureflow;
/** 累计抽采纯量 */
@Excel(name = "累计抽采纯量")
private Long totalpureflow;
/** 乙烯浓度 */
@Excel(name = "乙烯浓度")
private Double ethene;
/** 乙炔浓度 */
@Excel(name = "乙炔浓度")
private Double ethyne;
/** 氧气浓度 */
@Excel(name = "氧气浓度")
private Double oconcentration;
/**时间*/
private Date date;
/**数据错误(超限字段合集)*/
private List<String> errfield;
/**数据异常的字段合集*/
private List<ErrEntity> exceptionfield;
}
实体类Vo
package com.ruoyi.quartz.domain.entity;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.quartz.util.data.ErrEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimulationMeasurepointDataVo extends BaseEntity {
/** 测点信息ID */
@Excel(name = "测点信息ID")
private Integer measurepointid;
/**测点名称*/
private String measuringpointname;
/**抽采单元名称*/
private String unitname;
/** 所属抽采单元ID */
@Excel(name = "所属抽采单元ID")
private Integer drainageunitid;
/**所属工作面名称*/
private String workingfacename;
/** 所属工作面ID */
@Excel(name = "所属工作面ID")
private Integer workfaceid;
/** 混合流量 */
@Excel(name = "混合流量")
private Double mixtureflow;
/** 纯流量 */
@Excel(name = "纯流量")
private Double pureflow;
/** 温度 */
@Excel(name = "温度")
private Double temperature;
/** 甲烷浓度 */
@Excel(name = "甲烷浓度")
private Double ch4concentration;
/** 一氧化碳浓度 */
@Excel(name = "一氧化碳浓度")
private Double coconcentration;
/** 抽采负压 */
@Excel(name = "抽采负压")
private Double negativepressure;
/** 二氧化碳浓度 */
@Excel(name = "二氧化碳浓度")
private Double co2concentration;
/** 累计抽采混合流量 */
@Excel(name = "累计抽采混合流量")
private Long totalmixtureflow;
/** 累计抽采纯量 */
@Excel(name = "累计抽采纯量")
private Long totalpureflow;
/** 乙烯浓度 */
@Excel(name = "乙烯浓度")
private Double ethene;
/** 乙炔浓度 */
@Excel(name = "乙炔浓度")
private Double ethyne;
/** 氧气浓度 */
@Excel(name = "氧气浓度")
private Double oconcentration;
public SimulationMeasurepointDataVo(SimulationMeasurepointData smd, HashMap<String, ArrayList<SysDictData>> dictmap){
this.measuringpointname=smd.getMeasuringpointname();
this.unitname=smd.getUnitname();
this.workingfacename=smd.getWorkingfacename();
this.mixtureflow=smd.getMixtureflow();
this.pureflow=smd.getPureflow();
this.temperature=smd.getTemperature();
this.ch4concentration=smd.getCh4concentration();
this.coconcentration=smd.getCoconcentration();
this.negativepressure=smd.getNegativepressure();
this.co2concentration=smd.getCo2concentration();
this.totalmixtureflow=smd.getTotalmixtureflow();
this.totalpureflow=smd.getTotalpureflow();
this.ethene=smd.getEthene();
this.ethyne=smd.getEthyne();
this.oconcentration=smd.getOconcentration();
}
}
mapper.xml文件
<sql id="selectSimulationMeasurepointDateVo">
/*select id, measure_pointid, drainageunitid, workfaceid, mixtureflow, pureflow, temperature, ch4concentration, coconcentration, negativepressure from simulation_measurepoint_date*/
SELECT m.measuring_point_name,d.unit_name,w.working_face_name,s.*
from simulation_measurepoint_date s
LEFT JOIN t_measuring_point m ON s.measure_pointid=m.id
LEFT JOIN t_drainage_unit d ON s.drainageunitid=d.id
LEFT JOIN t_working_face w ON s.workfaceid=w.id
</sql>
<select id="selectSimulationMeasurepointDateList" parameterType="com.ruoyi.quartz.domain.entity.SimulationMeasurepointData" resultMap="SimulationMeasurepointDateResult">
<include refid="selectSimulationMeasurepointDateVo"/>
<where>
<if test="id!=null">and s.id=#{id}</if>
<if test="measurepointid != null "> and s.measure_pointid = #{measurepointid}</if>
<if test="drainageunitid != null "> and s.drainageunitid = #{drainageunitid}</if>
<if test="workfaceid != null "> and s.workfaceid = #{workfaceid}</if>
<if test="mixtureflow != null "> and s.mixtureflow = #{mixtureflow}</if>
<if test="pureflow != null "> and s.pureflow = #{pureflow}</if>
<if test="temperature != null "> and s.temperature = #{temperature}</if>
<if test="ch4concentration != null "> and s.ch4concentration = #{ch4concentration}</if>
<if test="coconcentration != null "> and s.coconcentration = #{coconcentration}</if>
<if test="negativepressure != null "> and s.negativepressure = #{negativepressure}</if>
<if test="totalmixtureflow != null "> and s.totalmixtureflow = #{totalmixtureflow}</if>
<if test="totalpureflow != null "> and s.totalpureflow = #{totalpureflow}</if>
</where>
</select>
mapper.java文件
/**
* 查询模拟测点的实时数据列表
*
* @param simulationMeasurepointDate 模拟测点的实时数据
* @return 模拟测点的实时数据集合
*/
public List<SimulationMeasurepointData> selectSimulationMeasurepointDateList(SimulationMeasurepointData simulationMeasurepointDate);
service.java文件
/**
* 查询模拟测点的实时数据列表
*
* @param simulationMeasurepointDate 模拟测点的实时数据
* @return 模拟测点的实时数据集合
*/
public List<SimulationMeasurepointData> selectSimulationMeasurepointDateList(SimulationMeasurepointData simulationMeasurepointDate);
serviceImpl.java文件
/**
* 查询模拟测点的实时数据列表
*
* @param simulationMeasurepointDate 模拟测点的实时数据
* @return 模拟测点的实时数据
*/
@Override
public List<SimulationMeasurepointData> selectSimulationMeasurepointDateList(SimulationMeasurepointData simulationMeasurepointDate)
{
return simulationMeasurepointDateMapper.selectSimulationMeasurepointDateList(simulationMeasurepointDate);
}
WordUnit.java 文件
package com.ruoyi.quartz.util;
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();
}
}
}
controller.java文件
@GetMapping("getList")
public List<SimulationMeasurepointData> getList(){
return this.simulationMeasurepointDateService.getList();
}
@PostMapping("exportWord")
public void exportword(HttpServletResponse resp, HttpServletRequest req,@RequestBody SimulationMeasurepointData simulationMeasurepointDate){
//获取列表
List<SimulationMeasurepointData> list=this.simulationMeasurepointDateService.selectSimulationMeasurepointDateList(simulationMeasurepointDate);
//获取字典
HashMap<String, ArrayList<SysDictData>> dictData=iSysDictDataService.getAllDictDataMap();
//生成结果集
Map<String, Object> dataMap = new HashMap<String,Object>();
ArrayList<SimulationMeasurepointDataVo> resultList=new ArrayList<SimulationMeasurepointDataVo>();
for(SimulationMeasurepointData s:list){
resultList.add(new SimulationMeasurepointDataVo(s,dictData));
}
dataMap.put("schemeList",list);
//设置生成文件存储路径
String directory="/schemeList";
WordUtil.CheckDownloadPath(directory);
//生成文件
WordUtil.CreateWord(resp,req,dataMap,"ruoyi-quartz\\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");
}
获取全部字典方法:
xml
<sql id="selectDictDataVo">
select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark
from sys_dict_data
</sql>
<select id="selectAllDictData" resultMap="SysDictDataResult">
<include refid="selectDictDataVo"></include>
</select>
serviceImpl.java文件
/**
* 查询全部的字典数据并生成Map字典方便查阅
* @return 以dict_type为key的map数据集
*/
@Override
public HashMap<String, ArrayList<SysDictData>> getAllDictDataMap() {
List<SysDictData> sysDictDataList = dictDataMapper.selectAllDictData();
HashMap<String, ArrayList<SysDictData>> resultMap = new HashMap<String, ArrayList<SysDictData>>();
for (SysDictData d:sysDictDataList) {
ArrayList<SysDictData> list;
if(resultMap.get(d.getDictType())!=null){
list=resultMap.get(d.getDictType());
}else{
list = new ArrayList<SysDictData>();
}
list.add(d);
resultMap.put(d.getDictType(),list);
}
return resultMap;
}
三、模板文件
1、初始的word文件
2、word文件转xml
注意:用window的office打开(不要用WPS),打开,另存为HTML文件,保存类型:筛选过的网页:
3、 然后使用系统自带的记事本打开:删除head标签部分
4、另存为,修改后缀为ftl,编码方式选择UTF-8:
5、如果${}形式的占位符中的内容被分隔开了,我们需要手动删除掉中间内容。
将所有表格数据处理好后折叠,在外部包裹如下代码:
<#list schemeList as scheme>
</#list>
注意:
①schemeList要与controller代码中保持一致
②as是给schemeList起别名的作用
③scheme就是smdlist的别名,这样在xml中就可以用scheme.
④为避免The following has evaluated to null or missing错误,错误为变量的值为空导致的,将文件中的变量${scheme.temperature}改为${scheme.temperature!""}即可
全部完成后将文件另存为ftl格式即可。
最后将word、xml、ftl三个文件放入项目如图位置。其中ftl文件是真正的模板文件,其余两个文件是中间文件,没有实际作用。