天天看点

利用Freemarker模板生成doc或者docx文档(转载整理)

可以直接看主要代码实现

doc作为模板文件生成指定格式的doc文件

实现逻辑

1、把作为模板的doc文件另存为xml文件

利用Freemarker模板生成doc或者docx文档(转载整理)

2、凡是需要填充的数据用${xxxx}替代

3、利用Template类将数据填充到模板并生成文件

代码:

/**
 * 将数据以特定模板格式输出到word文档(目前仅支持输出doc文件,只能通过代码修改文字内容)
 * @param data 输入模板数据
 * @param templatePath 模板存放路径
 * @param templateName 模板名称(XXX.xml,由doc/docx文档转换而成)
 * @param exFilePath 输出文件路径
 * @param exFileName 输出文件名称(XXX.doc)
 * @return
 */
public static boolean createDoc(Map<String,Object> data,String templatePath,String templateName,String exFilePath,String exFileName) {
	boolean result = false;
	Writer out = null;
	URL basePath = WordUtils.class.getClassLoader().getResource("");//获取类文件所在根目录,注意是编译后的class文件目录
    try {
    	Configuration configuration = new Configuration();
    	configuration.setDefaultEncoding("UTF-8");
    	configuration.setDirectoryForTemplateLoading(new File(basePath.getPath() + templatePath));
    	Template t = configuration.getTemplate(templateName); //获取模板文件
        File file = new File(basePath.getPath() + exFilePath);//生成生成文件所在目录
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    	File outFile = new File(basePath.getPath() + exFilePath + separator + exFileName); //导出文件生成
    	out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
    	t.process(data, out); //将填充数据填入模板文件并输出到目标文件 
    	result = true;
	} catch (Exception e) {
		e.printStackTrace();
	} finally{
		try {
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	return result;
}
           

docx作为模板文件生成自定义格式的doc/docx文件

实现逻辑

1、把doc/docx文档修改为ZIP格式(直接修改后缀)

2、取出

word/document.xml(主要内容)

[Content_Types].xml、\word_rels\document.xml.rels(图片配置)

word/header1.xml(页眉)

……

3、根据需要替换的内容修改以上文件,具体见替换文件说明

4、以zip文件的形式处理模板文件(doc/docx) ,遍历该zip,将zip内除了media目录下的文件(图片另外处理)和替换文件(步骤3内文件)的每个文件输出到指定文件(doc/docx,以zip流的形式输入)

String xmlDocumentXmlRelsComment = FreeMarkUtils.getFreemarkerContent(dataMap, xmlDocumentXmlRels, templatePath);
ByteArrayInputStream documentXmlRelsInput = new ByteArrayInputStream(xmlDocumentXmlRelsComment.getBytes());//替换的xml

ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream("D:/workplace/springBootWorkplace/myDemo/target/classes/templates/out.docx"));
ZipFile zipFile = new ZipFile("D:/workplace/springBootWorkplace/myDemo/target/classes/templates/docTemplates.docx");//以zip文件的形式处理docx文件
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();//遍历zip文件内的所有文件
int len = -1;
byte[] buffer = new byte[1024];
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();//以枚举方式获取文件
InputStream is = zipFile.getInputStream(next);//用于文件输出
zipout.putNextEntry(new ZipEntry(next.getName()));//开始写入,设置文件名称
  if (documentXmlRelsInput != null) {
      while ((len = documentXmlRelsInput.read(buffer)) != -1) {
         zipout.write(buffer, 0, len);
documentXmlRelsInput.close();
}else{
  while ((len = is.read(buffer)) != -1) {
  	zipout.write(buffer, 0, len);
  }
}
is.close();
}
zipout.close();
zipFile.close();
           

5、将替换文件和图片文件(word/media)以zip流形式输入到指定文件

6、关闭流

word转换zip后替换文件说明

1、\word\document.xml

用来存在word文档的主要数据信息

2、\word_rels\document.xml.rels

用来存在word文档的主要数据配置 包括图片的指向

<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>
rId7:唯一标识,image1.jpeg:图片名称
           

与对应的document.xml

<wp:docPr id="2" name="图片 2" descr="D:\阿里工作\装修\装修\北欧1\1.jpg"/>
           

id:唯一标识,name:标识,descr:图片路径

<a:blip r:embed="rId7">
           

r:embed对应document.xml.rels的Id

<w:p w:rsidR="00EC2516" w:rsidRPr="00EC2516" w:rsidRDefault="00EC2516" w:rsidP="00EC2516">
  <w:r w:rsidRPr="00EC2516">
    <w:rPr>
      <w:noProof/>
    </w:rPr>
    <w:drawing>
      <wp:inline distT="0" distB="0" distL="0" distR="0">
        <wp:extent cx="5274310" cy="7024797"/>
        <wp:effectExtent l="0" t="0" r="2540" b="5080"/>
        <wp:docPr id="2" name="图片 2" descr="D:\阿里工作\装修\装修\北欧1\1.jpg"/>
        <wp:cNvGraphicFramePr>
          <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"></a:graphicFrameLocks>
        </wp:cNvGraphicFramePr>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
            <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
              <pic:nvPicPr>
                <pic:cNvPr id="0" name="Picture 2" descr="D:\阿里工作\装修\装修\北欧1\1.jpg"/>
                <pic:cNvPicPr>
                  <a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
                </pic:cNvPicPr>
              </pic:nvPicPr>
              <pic:blipFill>
                <a:blip r:embed="rId7">
                  <a:extLst>
                    <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
                      <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"></a14:useLocalDpi>
                    </a:ext>
                  </a:extLst>
                </a:blip>
                <a:srcRect/>
                <a:stretch>
                  <a:fillRect/>
                </a:stretch>
              </pic:blipFill>
              <pic:spPr bwMode="auto">
                <a:xfrm>
                  <a:off x="0" y="0"/>
                  <a:ext cx="5274310" cy="7024797"/>
                </a:xfrm>
                <a:prstGeom prst="rect">
                  <a:avLst/>
                </a:prstGeom>
                <a:noFill/>
                <a:ln>
                  <a:noFill/>
                </a:ln>
              </pic:spPr>
            </pic:pic>
          </a:graphicData>
        </a:graphic>
      </wp:inline>
    </w:drawing>
  </w:r>
</w:p>
           

3、\word\header1.xml

用来配置docx文档的页眉文件

页眉:Word文档模板测试ymdhis

<w:p w:rsidR="00DF53B8" w:rsidRDefault="00DF53B8" w:rsidP="00DF53B8">
    <w:pPr>
      <w:pStyle w:val="a3"/>
    </w:pPr>
    <w:r>
      <w:t>Word</w:t>
    </w:r>
    <w:r>
      <w:t>文档模板测试</w:t>
    </w:r>
    <w:r w:rsidR="00CC7E39">
      <w:t>ymdhis</w:t>
    </w:r>
  </w:p>
           

4、[Content_Types].xml

用来配置 docx文档中所插入图片的类型 如 png、jpeg、jpg等

,XX的格式要与插入文件的格式一致,每种类别加一条记录

<Default Extension="jpeg" ContentType="image/jpeg"/>
           

代码

pom.xml

<dependency>  
    <groupId>org.freemarker</groupId>  
    <artifactId>freemarker</artifactId>  
    <version>2.3.23</version>  
</dependency>  
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.1</version>
</dependency>
           
/**
 * 获取当前日期的字符串(毫秒) 如
 * @return
 */
public static String getCurrentTime_yyyyMMddHHmmssSSS(){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    return sdf.format(new Date());
}
           
/**
     * 将模板填充完数据以字符串形式输出
     * @param dataMap   参数
     * @param templateName  模板名称
     * @param temp_path  模板路径 classes下的路径 如果  classes/templates  传入 /templates即可
     * @return
     */
    public static String getFreemarkerContent(Map dataMap, String templateName, String temp_path) {
        String result = "";
        try {
            //创建配置实例
            Configuration configuration = new Configuration();

            //设置编码
            configuration.setDefaultEncoding("UTF-8");

            //ftl模板文件统一放至 com.lun.template 包下面
//            configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/"));
            configuration.setClassForTemplateLoading(FreeMarkUtils.class, temp_path);
            //获取模板
            Template template = configuration.getTemplate(templateName);

            StringWriter swriter = new StringWriter();
            //将填充数据填入模板文件并输出到目标文件/流
            template.process(dataMap, swriter);
            result = swriter.toString();


        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
           
/**
     * 将模板填充完数据以流形式输出
     * @param dataMap   参数
     * @param templateName  模板名称
     * @param tempPath  模板路径 classes下的路径 如果  classes/templates  传入 /templates即可
     * @return
     */
    public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName, String tempPath) {
        ByteArrayInputStream in = null;

        try {
            //创建配置实例
            Configuration configuration = new Configuration();

            //设置编码
            configuration.setDefaultEncoding("UTF-8");

            //ftl模板文件统一放至 com.lun.template 包下面
//            configuration.setDirectoryForTemplateLoading(new File("D:/idea_workspace/alarm/alarm/src/main/resources/template/"));
            configuration.setClassForTemplateLoading(FreeMarkUtils.class, tempPath);
            //获取模板
            Template template = configuration.getTemplate(templateName);

            StringWriter swriter = new StringWriter();
            //生成文件
            template.process(dataMap, swriter);
            //String result = swriter.toString();
            in = new ByteArrayInputStream(swriter.toString().getBytes());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return in;
    }
           

**

主要代码实现

**

import org.dom4j.Document;
    import org.dom4j.DocumentHelper;
    import org.dom4j.Element;
    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import java.io.*;
    import java.net.URL;
    import java.util.*;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    import java.util.zip.ZipOutputStream;
    
    /**
     * 注意该方法所在工程是springboot结构,模板放置于\src\main\resources\templates\下,其他工程结构要将读取路径对应修改
     * frameMark:${title}
     * @author Administrator
     *
     */
    public class WordUtils {
    
        private final static String separator = File.separator;
        private final static String suffix_docx = "docx";
        private final static String suffix_doc = "doc";
    
    	/**
    	 * 将数据以特定模板格式输出到word文档(目前仅支持输出doc文件,只能通过代码修改文字内容)
    	 * @param data 输入模板数据
    	 * @param templatePath 模板存放路径
    	 * @param templateName 模板名称(XXX.xml,由doc/docx文档转换而成)
    	 * @param exFilePath 输出文件路径
    	 * @param exFileName 输出文件名称(XXX.doc)
    	 * @return
    	 */
    	public static boolean createDoc(Map<String,Object> data,String templatePath,String templateName,String exFilePath,String exFileName) {
    		boolean result = false;
    		Writer out = null;
    		URL basePath = WordUtils.class.getClassLoader().getResource("");//获取类文件所在根目录,注意是编译后的class文件目录
            try {
            	Configuration configuration = new Configuration();
            	configuration.setDefaultEncoding("UTF-8");
            	configuration.setDirectoryForTemplateLoading(new File(basePath.getPath() + templatePath));
            	Template t = configuration.getTemplate(templateName); //获取模板文件
                File file = new File(basePath.getPath() + exFilePath);//生成生成文件所在目录
                if (!file.exists() && !file.isDirectory()) {
                    file.mkdirs();
                }
            	File outFile = new File(basePath.getPath() + exFilePath + separator + exFileName); //导出文件生成
            	out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            	t.process(data, out); //将填充数据填入模板文件并输出到目标文件 
            	result = true;
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally{
    			try {
    				out.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		
    		return result;
    	}
        
        /**
         * 以docx为模板生成doc/docx文件
         * 模板文件的配置文件由docx转换成zip获取,docx文档生成工具类  (改变后缀名即可)
         * 在使用制作模板的过程中如果模板中有图片那就保留图片,修改[Content_Types].xml和document.xml.rels文档,如果模板中没有图片 则不需要设置[Content_Types].xml和document.xml.rels
         * 由于word模板的个性化 所以 每次做模板都要重新覆盖原来的模板
         * @param dataMap				参数数据
         * @param docxTemplateFile		docx模主板名称(注意模板文件只能为docx,doc不能被作为zip读取)
         * @param xmlDocument			docx中document.xml模板文件  用来存放word文档的主要数据信息
         * @param xmlDocumentXmlRels	docx中document.xml.rels 模板文件  用来存放word文档的主要数据配置 包括图片的指向
         * @param xmlContentTypes		docx中 [Content_Types].xml 模板文件 用来配置 docx文档中所插入图片的类型 如 png、jpeg、jpg等
         * @param xmlHeader				docx中 header1.xml 模板文件 用来配置docx文档的页眉文件
         * @param templatePath			模板存放路径 如 /templates/
         * @param outputFileTempPath	所生成的docx文件的临时路径文件夹 如果 temp/20180914051811/
         * @param outputFileName		所生成的docx文件名称  如  xxx.docx  或  xxx.doc
         * @throws Exception
         */
        public static void createDocx(Map<String, Object> dataMap, String docxTemplateFile, String xmlDocument, String xmlDocumentXmlRels,
                                      String xmlContentTypes, String xmlHeader, String templatePath,
                                      String outputFileTempPath, String outputFileName) throws Exception {
    
            URL basePath = WordUtils.class.getClassLoader().getResource("");//获取类文件所在根目录,注意是编译后的class文件目录
            String realTemplatePath = basePath.getPath() + templatePath;
            //临时文件产出的路径
            String outputPath = basePath.getPath() + outputFileTempPath;
            try {
    
    
                //================================获取 document.xml.rels 输入流================================
                String xmlDocumentXmlRelsComment = FreeMarkUtils.getFreemarkerContent(dataMap, xmlDocumentXmlRels, templatePath);
                ByteArrayInputStream documentXmlRelsInput = new ByteArrayInputStream(xmlDocumentXmlRelsComment.getBytes());
    
                //================================获取 header1.xml 输入流================================
                ByteArrayInputStream headerInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlHeader, templatePath);
    
                //================================获取 [Content_Types].xml 输入流================================
                ByteArrayInputStream contentTypesInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlContentTypes, templatePath);
    
    
                //读取 document.xml.rels  文件 并获取rId 与 图片的关系 (如果没有图片 此文件不用编辑直接读取就行了)
                Document document = DocumentHelper.parseText(xmlDocumentXmlRelsComment);
                Element rootElt = document.getRootElement(); // 获取根节点
                Iterator iter = rootElt.elementIterator();// 获取根节点下的子节点head
                List<Map<String, String>> picList = (List<Map<String, String>>) dataMap.get("picList");
    
                // 遍历Relationships节点,获取Target类型为media的节点(该节点由frameMark生成),将其Id值映射到picList的子项,对应rId
                while (iter.hasNext()) {
                    Element recordEle = (Element) iter.next();
                    String id = recordEle.attribute("Id").getData().toString();
                    String target = recordEle.attribute("Target").getData().toString();
                    if (target.indexOf("media") == 0) {
                        for (Map<String, String> picMap : picList) {
                            if (target.endsWith(picMap.get("name"))) {
                                picMap.put("rId", id);
                            }
                        }
                    }
                }
                dataMap.put("picList", picList);//覆盖原来的picList,主要为了关联 document.xml.rels内的图片配置声明;
    
                //================================获取 document.xml 输入流================================
                ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlDocument, templatePath);
    
    
                File docxFile = new File(realTemplatePath + separator + docxTemplateFile);
                if (!docxFile.exists()) {
                    docxFile.createNewFile();
                }
    
                ZipFile zipFile = new ZipFile(docxFile);//模板文件只能为docx类型,doc类型不能被作为zip读取
                Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();//用于遍历压缩文件内的每个文件
                File tempPath = new File(outputPath);
                //如果输出目标文件夹不存在,则创建
                if (!tempPath.exists()) {
                    tempPath.mkdirs();
                }
                ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(outputPath + outputFileName));
    
    
                //================================覆盖文档-begin================================
                //逻辑说明:将模板文件(doc/docx)以zip形式处理,遍历该zip,将zip内除了media目录下的文件(图片另外处理)的每个文件输入到指定文件(doc/docx,以zip形式输入),其中[Content_Types].xml、document.xml.rels、word/document.xml、word/header1.xml用frameMark生成的文件替代
                int len = -1;
                byte[] buffer = new byte[1024];
                while (zipEntrys.hasMoreElements()) {
                    ZipEntry next = zipEntrys.nextElement();//以枚举方式获取文件
                    InputStream is = zipFile.getInputStream(next);
                    if (next.toString().indexOf("media") < 0) {
                        // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
                        zipout.putNextEntry(new ZipEntry(next.getName()));//开始写入,设置文件名称
    //                    System.out.println("next.getName()>>>" + next.getName() + "  next.isDirectory()>>>" + next.isDirectory());
                        //写入图片配置类型
                        if (next.getName().equals("[Content_Types].xml")) {
                            if (contentTypesInput != null) {
                                while ((len = contentTypesInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                contentTypesInput.close();
                            }
    
                        } else if (next.getName().indexOf("document.xml.rels") > 0) {
                            //写入填充数据后的主数据配置信息
                            if (documentXmlRelsInput != null) {
                                while ((len = documentXmlRelsInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                documentXmlRelsInput.close();
                            }
                        } else if ("word/document.xml".equals(next.getName())) {
                            //写入填充数据后的主数据信息
                            if (documentInput != null) {
                                while ((len = documentInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                documentInput.close();
                            }
    
                        } else if ("word/header1.xml".equals(next.getName())) {
                            //写入填充数据后的页眉信息
                            if (headerInput != null) {
                                while ((len = headerInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                headerInput.close();
                            }
    
                        } else {//其余文件直接输出到导出文件
                            while ((len = is.read(buffer)) != -1) {
                                zipout.write(buffer, 0, len);
                            }
                            is.close();
                        }
    
                    }
    
                }
    
                //------------------写入新图片-start------------------
                len = -1;
                if (picList != null && !picList.isEmpty()) {
                    for (Map<String, String> pic : picList) {
                        ZipEntry next = new ZipEntry("word" + separator + "media" + separator + pic.get("name"));
                        zipout.putNextEntry(new ZipEntry(next.toString()));
                        InputStream in = new FileInputStream(pic.get("path"));
                        while ((len = in.read(buffer)) != -1) {
                            zipout.write(buffer, 0, len);
                        }
                        in.close();
                    }
                }
    
    
                //------------------写入新图片-over------------------
                //================================覆盖文档-end================================
                zipout.close();
                zipFile.close();
            } catch (Exception e) {
                e.printStackTrace();
                throw new Exception("生成word文件失败!");
            }
    
        }
    
        public static void main(String[] args) {
    
        	//============================================createDocx(docx模板测试)-begin============================================
        	String timeStr1 = DateUtils.getCurrentTime_yyyyMMddHHmmssSSS();
            String templatePath1 = separator + "templates" + separator;
            String outputFileTempPath1 = "temp" + separator + "doc" + separator + timeStr1 + separator;
            String outputFileName1 = timeStr1 + "."+suffix_doc;
        	
    		Map<String,Object> dataMap1 = new HashMap<String,Object>();
            dataMap1.put("name", "王大壮"); 
            dataMap1.put("age", "30"); 
            dataMap1.put("phone", "18450098635"); 
            dataMap1.put("mailbox", "12345678911");
            System.out.println(createDoc(dataMap1, templatePath1, "docTemplates.xml", outputFileTempPath1,outputFileName1));
          //============================================createDocx(docx模板测试)-end============================================
        	
        	//============================================createDocx(docx模板测试)-begin============================================
            URL basePath = WordUtils.class.getClassLoader().getResource("");
            String picPath = basePath.getPath() + separator + "templates" + separator;
            ;
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("ymdhis", DateUtils.getCurrentTime_yyyyMMddHHmmss());
            List<String> listTile = new ArrayList<>();
            listTile.add("这是第一个标题");
            listTile.add("这是第二个标题");
            listTile.add("这是第三个标题");
            dataMap.put("listTitle", listTile);
    
            List<String> picTypes = new ArrayList<>();
            picTypes.add("jpg");
            dataMap.put("picTypes", picTypes);
    
            List<Map<String, String>> picList = new ArrayList<>();
    
            Map<String, String> picMap = new HashMap<>();
            // 要按顺序
            picMap.put("path", picPath + "pic1.jpg");
            picMap.put("name", "pic1.jpg");
            picList.add(picMap);
    
            picMap = new HashMap<>();
            picMap.put("path", picPath + "pic2.jpg");
            picMap.put("name", "pic2.jpg");
            picList.add(picMap);
    
            picMap = new HashMap<>();
            picMap.put("path", picPath + "pic3.jpg");
            picMap.put("name", "pic3.jpg");
            picList.add(picMap);
            dataMap.put("picList", picList);
            List<Map<String, Object>> listTaleData = new ArrayList<>();
            Map<String, Object> map = new HashMap<>();
            map.put("name", "小明");
            map.put("age", "11");
            map.put("sex", "男");
            map.put("grade", "五年级");
            listTaleData.add(map);
    
            map = new HashMap<>();
            map.put("name", "小红");
            map.put("age", "12");
            map.put("sex", "女");
            map.put("grade", "六年级");
            listTaleData.add(map);
    
            map = new HashMap<>();
            map.put("name", "小花");
            map.put("age", "13");
            map.put("sex", "女");
            map.put("grade", "七年级");
            listTaleData.add(map);
            dataMap.put("listTaleData", listTaleData);
    
            dataMap.put("summary", "总结总结总结!");
            
    
            String timeStr = DateUtils.getCurrentTime_yyyyMMddHHmmssSSS();
            String docxTemplateFile = "docxTemplates.docx";
            String xmlDocument = "document.xml";
            String xmlDocumentXmlRels = "document.xml.rels";
            String xmlContentTypes = "[Content_Types].xml";
            String xmlHeader = "header1.xml";//可以用来修改页眉的一些信息
            String templatePath = separator + "templates" + separator;
            String outputFileTempPath = "temp" + separator + "docx" + separator + timeStr + separator;
            String outputFileName = timeStr + "."+suffix_docx;
            String outputFileName2 = timeStr + "."+suffix_doc;
    
            try {
                createDocx(dataMap, docxTemplateFile, xmlDocument, xmlDocumentXmlRels, xmlContentTypes,
                        xmlHeader, templatePath, outputFileTempPath, outputFileName);
                createDocx(dataMap, docxTemplateFile, xmlDocument, xmlDocumentXmlRels, xmlContentTypes,
                        xmlHeader, templatePath, outputFileTempPath, outputFileName2);
            } catch (Exception e) {
                e.printStackTrace();
            }
          //============================================createDocx(docx模板测试)-end============================================
        }
    
    
    }
           

模板所在目录

利用Freemarker模板生成doc或者docx文档(转载整理)

模板文件

链接: https://pan.baidu.com/s/1ocavyv7wfB_bvptO3Ten3w 提取码: fgwp

参考:https://blog.csdn.net/fenfenguai/article/details/78731331