使用freemarker模板导出复杂word文档

一、创建模板

1、将word文档另存为xml格式文件。

在这里插入图片描述

2、格式化xml文件

找一个可以格式化xml文件的在线网站,用记事本或者notepad之类的软件,复制文件内容去格式化,然后把格式化好的内容覆盖到原xml文件中。
在这里插入图片描述
在这里插入图片描述

3、将xml文件后缀改为ftl,然后修改部分文件内容为可供程序填充的模板

在这里插入图片描述

4、修改ftl模板文件

打开ftl文件,修改<w:t></w:t>标签内的内容
在这里插入图片描述
如果有需要循环的需求,如果word中需要生成一个表格,则在<w:tr></w:tr>标签外增加标签<#list 。。。></#list>
在这里插入图片描述
在这里插入图片描述

二、引入依赖

		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.27-incubating</version>
		</dependency>

三、代码

1、定义模板对象

package com.entity;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: yiwenli
 * @Description: 恶劣天气导出word模板对象
 * @Date: 2022/4/11
 */
@Data
public class BadWeatherWordTemplate {
    /**
     * 恶劣天气主要影响地区
     */
    private String areaList;

    /**
     * 地区总的线路跳闸情况
     */
    AreaLinePowerOutageDetail totalLinePowerOutageDetail = new AreaLinePowerOutageDetail();

    /**
     * 地区110kV及以下线路跳闸及非计停明细
     */
    List<AreaLinePowerOutageDetail> areaLinePowerOutageDetailList = new ArrayList<>();

}

2、FreeMarker模板转换工具类

package com.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @Author: yiwenli
 * @Description: FreeMarker模板转换工具
 * @Date: 2022/4/12
 */
@Service
public class TemplateParseUtil {

    @Autowired
    private Configuration config;

    /**
     * 解析模板,将模板数据放入后生成目标文件
     *
     * @param templateDirPath  模板目录地址
     * @param templateFileName 模板名称
     * @param outFilePathName  输出的文件路径 包含名称
     * @param dataMap          模板数据参数
     */
    public File parse(String templateDirPath, String templateFileName, String outFilePathName, Map<String,Object> dataMap) {
        File outFile = new File(outFilePathName);
        try(Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8))) {
            config.setDirectoryForTemplateLoading(new File(templateDirPath));
            // 文件名,并且设置编码
            Template template = config.getTemplate(templateFileName, "UTF-8");
            if(template != null) {
                template.process(dataMap, out);
            }
            out.flush();
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
        return outFile;
    }

    /**
     * 下载文件
     *
     * @param outFile             源文件
     * @param fileName            下载后的文件名
     * @param deleteSource        是否删除源文件
     * @param responseContentType 内容类型
     */
    public boolean download(File outFile, String fileName, Boolean deleteSource, String responseContentType, HttpServletResponse response) {
        try (ServletOutputStream outputStream = response.getOutputStream();
             InputStream input = new FileInputStream(outFile)) {
            byte[] bytes = new byte[input.available()];
            int read = input.read(bytes);
            if (read > 0) {
                response.setContentType(responseContentType);
                response.setCharacterEncoding("UTF-8");
                fileName = URLEncoder.encode(fileName, "UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
                outputStream.write(bytes);
                outputStream.flush();
            }
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if(deleteSource) {
                outFile.delete();
            }
        }
    }
}

3、模板数据写入,模板生成后下载

 /**
     * 恶劣天气导出 Word文档
     *
     * @param startTime 查询开始时间
     * @param endTime   查询结束时间
     * @param loginUser 登录用户
     */
    public void badWeatherExportWord(String startTime, String endTime, LoginUser loginUser, HttpServletResponse response) {

        // 用户ID
        String userId = loginUser.getId();
        // 所属调度机构ID
        String orgId = loginUser.getOrgId();
        // 查询模板数据并封装
        BadWeatherWordTemplate badWeatherWordTemplate = getBadWeatherDataForWord(startTime, endTime, orgId);

        // 模板名称
        String templateFileName = "恶劣天气影响电网运行情况模板.ftl";
        // 输出文件路径
        String outFilePathName = Constant.TEMPLATE_DIR_PATH + "恶劣天气影响电网运行情况模板" + userId + System.currentTimeMillis() + ".doc";
        // 模板数据
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("badWeatherWordTemplate", badWeatherWordTemplate);
        // 文件名称
        String fileName = badWeatherWordTemplate.getTitleDateStr() + "恶劣天气影响电网运行情况[1].doc";

        // 解析模板,将模板数据放入后生成目标文件
        File outFile = templateParseUtil.parse(Constant.TEMPLATE_DIR_PATH, templateFileName, outFilePathName, dataMap);

        // 下载文件
        templateParseUtil.download(outFile, fileName, true, "application/x-www-form-urlencoded", response);
    }

4、前端方法调用

function badWeatherExportSubmit() {
  let url = `${config.url}/operate/badWeatherExport`
  let form = $('<form></form>').attr('action', url).attr('method', 'post');
  form.append($('<input>').attr('type', 'hidden').attr('name', 'loginUserJson').attr('value', JSON.stringify(loginUser)));
  form.append($('<input>').attr('type', 'hidden').attr('name', 'startTime').attr('value', $('#startTime').val()));
  form.append($('<input>').attr('type', 'hidden').attr('name', 'endTime').attr('value', $('#endTime').val()));
  form.append($('<input>').attr('type', 'hidden').attr('name', 'type').attr('value', type));
  form.appendTo('body').submit();
  form.remove();
}

参考 FreeMarker中文官方参考手册

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Web应用中,有时需要按照固定的模板将数据导出Word,如流程审批单,在流程处理完成后将处理过程按照流程单的要求导出,有时程序中需要实现生成标准Word文档,要求能够打印,并且保持页面样式不变,常见的方案有POI、iText、JACOB、JSP几种方式,POI读取Word文档比较适合、对于生成文档样式比较难控制,iText操作Excel还可以,对Word的操作功能有限,JACOB操作Word实现复杂,并且无法将服务部署到Linux平台,要求安装office,对于实现固定格式的报表实现困难,对于JSP直接输出方式样式控制难。 Word从2003开始支持XML格式,用XML+Freemarder还做就很简单了,大致的思路是先用office2003或者2007编辑好 word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。经测试这样方式生成的word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。具体实现过程如下: 1、 首先用office【版本要2003以上,以下的不支持xml格式】编辑文档的样式,将需要动态填充的内容使用Freemarker标签替换:Word文档样式如下: 2、 将Word文档另存为XML格式,将后缀名“xml”修改为“ftl” 3、 使用Freemarker填充内容,代码如下: [java] view plaincopyprint? 1. package com.test.freemarker.report; 2. 3. 4. 5. import java.io.BufferedWriter; 6. 7. import java.io.File; 8. 9. import java.io.FileOutputStream; 10. 11. import java.io.IOException; 12. 13. import java.io.OutputStreamWriter; 14. 15. import java.io.Writer; 16. 17. import java.util.HashMap; 18. 19. import java.util.Map; 20. 21. 22. 23. import freemarker.template.Configuration; 24. 25. import freemarker.template.Template; 26. 27. import freemarker.template.TemplateException; 28. 29. 30. 31. public class DocumentHandler { 32. 33. private Configuration configuration = null; 34. 35. 36. 37. public DocumentHandler() { 38. 39. configuration = new Configuration(); 40. 41. configuration.setDefaultEncoding("utf-8"); 42. 43. } 44. 45. 46. 47. public void createDoc() { 48. 49. // 要填入模本的数据文件 50. 51. Map dataMap = new HashMap(); 52. 53. getData(dataMap); 54. 55. // 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载, 56. 57. // 这里我们的模板是放在com.havenliu.document.template包下面 58. 59.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值