springboot+freemarker implements export word template

freemarker

  • FreeMarker is a template engine: that is, a general-purpose tool for generating output text (HTML web pages, emails, configuration files, source code, etc.) based on templates and data to be changed. It is not intended for end users, but a Java class library, a component that programmers can embed in the products they develop.
  • FreeMarker is free and released under the Apache License version 2.0. Its template is written as FreeMarker Template Language (FTL), which is a simple and dedicated language. It is necessary to prepare data to be displayed in real programming language, such as database query and business operation, and then the template displays the prepared data. In the template, it is mainly used for how to display the data, but outside the template, focus on what data to display

Project configuration:

		<!--添加freeMarker-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.20</version>
        </dependency>
#配置freemarker配置
#模板存放路径(默认地址为classpath:/templates/)
spring.freemarker.template-loader-path=classpath:/templates
#模板后缀
spring.freemarker.suffix= .ftl
#编码
spring.freemarker.charset= utf-8
#RequestContext属性的名称(默认为-)
spring.freemarker.request-context-attribute= request

Note: The default template file here is in the templates folder under resources (the default path template file must be placed under resources, when the program loads the template file, freemarker provides many ways to get the template file, you can find out by yourself )

The next step we have to do is to prepare our word template and then convert the template to an xml file. We need to define our placeholders in the word template, using ${string}. Just define "string" according to your own preferences.

The process is as follows:

word document:
insert image description here
Then save our word document as an xml document.
insert image description here
Change the suffix of our xml document to ftl, and then open our ftl file with software that can open ftl files. Here we have a couple of caveats.
First, defined placeholders may be separated. It's like this:
insert image description here
what we need to do is to delete the redundant part. In the picture, I defined ${userName}. So I deleted the redundant part and changed it to ${userName}.

Second, what we need to pay attention to is that we need to add the freeMarker tag ourselves in our table part. Use custom tags between table codes. The defined parameters must be consistent with the ones we defined in the method, otherwise the value cannot be obtained.

Table start:
insert image description here
Note: <w:tr></w:tr> represents a row where a loop is needed, add a freemarker loop statement in front of that line, use the c tag language similar to jsp, remember to find the corresponding < Add </#list> after /w:tr> (this is the freemarker statement)
Freemarker Chinese online manual instruction reference link: http://freemarker.foofun.cn/ref_directives.html

The following is the function implementation:
tool class

package com.newdo.base;

import freemarker.template.Configuration;
import freemarker.template.Template;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;

public class WordUtil {
    
    

    /**
     * 生成word文件
     * @param dataMap word中需要展示的动态数据,用map集合来保存
     * @param templateName word模板名称,例如:test.ftl
     * @param filePath 文件生成的目标路径,例如:D:/wordFile/
     * @param fileName 生成的文件名称,例如:test.doc
     */
    @SuppressWarnings("unchecked")
    public static void createWord(HttpServletRequest request, HttpServletResponse response, Map dataMap, String templateName, String filePath, String fileName){
    
    
        try {
    
    
            //创建配置实例
            Configuration configuration = new Configuration();
            //设置编码
            configuration.setDefaultEncoding("UTF-8");
            //ftl模板文件 取模板文件存放地址
            configuration.setClassForTemplateLoading(WordUtil.class,"/templates");
            //获取模板
            Template template = configuration.getTemplate(templateName);
            //输出文件
            File outFile = new File(filePath+File.separator+fileName);
            //如果输出目标文件夹不存在,则创建
            if (!outFile.getParentFile().exists()){
    
    
                outFile.getParentFile().mkdirs();
            }
            //检测是否存在 存在删除
            if (outFile.exists()) {
    
    
                outFile.delete();
            }
            //将模板和数据模型合并生成文件
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
            //生成文件 实际这里已经将文件生成在指定位置
            template.process(dataMap, out);
            
			//以下操作是将文件下载
            File file = new File(filePath + "\\" + fileName);
            InputStream fin = new FileInputStream(file);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式,处理该文件名  ps:docx格式office可能存在打不开等问题
            fileName = URLEncoder.encode(fileName, "utf-8");
            response.setHeader("Content-Disposition","attachment;filename="+fileName);
            ServletOutputStream out2 = response.getOutputStream();
            byte[] buffer = new byte[512];
            int bytesToRead = -1;
            // 通过循环将读入的Word文件的内容输出到浏览器中
            while ((bytesToRead = fin.read(buffer)) != -1) {
    
    
                out2.write(buffer, 0, bytesToRead);
            }

            //关闭流
            out.flush();
            out.close();

            fin.close();
            out2.close();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }
}

file storage address
insert image description here

method call

public static void main(String[] args) {
    
    
         /** 用于组装word页面需要的数据 */
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("name","测试");
        dataMap.put("date","2023-03-09");
        dataMap.put("content","测试内容");
        List<Object> datas = new ArrayList<>();
        for(int i=0;i<10;i++){
    
    
            Data data = new Data();
            data.put("title","标题" + i);
            data.put("content","内容" + i);
            data.put("another","作者" + i);
            datas.add(data);
        }
        dataMap.put("listInfo",datas);
        String filePath = "";
        if (IsWhatSystem.whatSystem()) {
    
    
            //文件路径
            filePath = "D:/doc_f/";
        }else {
    
    
            filePath = "/doc_f/";
        }
        //文件唯一名称
        String fileOnlyName = "生成Word文档.doc";
        /** 生成word  数据包装,模板名,文件生成路径,生成的文件名*/
        WordUtil.createWord(dataMap, "dacyjl.ftl", filePath, fileOnlyName);
    }

In addition, the table columns in the template can also be merged, so I won’t say more here, and it will be mentioned in the reference link below.
Reference link for this article:
https://www.cnblogs.com/h-java/p/10026850.html

Cell merge reference link
https://blog.csdn.net/weixin_43667830/article/details/106936546
https://blog.csdn.net/weixin_43165220/article/details/119537190

Guess you like

Origin blog.csdn.net/Strive279/article/details/129422526