参考:https://my.oschina.net/u/3737136/blog/2958421?tdsourcetag=s_pcqq_aiomsg
具体思路
1.创建一个docx文档模板,其中的英文是根据自己需要填充的内容。
2.把docx文档修改为ZIP格式(修改.docx后缀名为.zip),然后把zip解压到当前目录
3.修改word目录下document.xml文档,把如下原来是time改为${time},改好后放入项目中,用于后边内容填充。【有时候一个单词可能会被拆分,自己要做相应的调整】
<#list minuteList as minute></#list> 可用于循环填充,相当于 for (Minute minte:minuteList),示列如下:
<#list minuteList as minute>
<w:p w14:paraId="3BB7AF6B" w14:textId="2AD2E958" w:rsidR="00D80192" w:rsidRDefault="00C4552D" w:rsidP="00E47882">
<w:pPr>
<w:pStyle w:val="a6"/>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="2"/>
</w:numPr>
<w:ind w:firstLineChars="0"/>
</w:pPr>
<w:proofErr w:type="spellStart"/>
<w:r w:rsidRPr="00C4552D">
<w:t>${minute.meeting_decision_content}</w:t>
</w:r>
<w:proofErr w:type="spellEnd"/>
<w:r>
<w:t xml:space="preserve"> </w:t>
</w:r>
<w:bookmarkStart w:id="0" w:name="_GoBack"/>
<w:bookmarkEnd w:id="0"/>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>交由</w:t>
</w:r>
<w:proofErr w:type="spellStart"/>
<w:r w:rsidRPr="00C4552D">
<w:t>${minute.meeting_decision_executor} </w:t>
</w:r>
<w:proofErr w:type="spellEnd"/>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>负责,在</w:t>
</w:r>
<w:proofErr w:type="spellStart"/>
<w:r w:rsidRPr="00C4552D">
<w:t>${minute.meeting_decision_deadline} </w:t>
</w:r>
<w:proofErr w:type="spellEnd"/>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>前完成。</w:t>
</w:r>
</w:p>
</#list>
---------下边思路在代码中实现------------
4..把内容填充到document.xml里
5.在输入docx文档的时候把填充过内容的的 document.xml用流的方式写入zip(详见下面代码)。
6.输出docx文档
docx模板修改成zip格式后的信息如下(因为word文档本身就是ZIP格式实现的)
注:【在文档里边加入图片须进行rels文档的相关操作,我这里没用到,如有需要可以查看上边的参考链接】
---------代码部分------------
pom中导入依赖:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
项目结构:【箭头指向才是用到的,其他部分的测试目前没有删】
FreeMarkUtils类
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.util.Map;
public class FreeMarkUtils {
private static Logger logger = LoggerFactory.getLogger(FreeMarkUtils.class);
public static Configuration getConfiguration(){
//创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
//设置编码
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(FreeMarkUtils.class, "/templates/wordTemplates");//换成自己对应的目录
return configuration;
}
/**
* 获取模板字符串输入流
* @param dataMap 参数
* @param templateName 模板名称
* @return
*/
public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName) {
ByteArrayInputStream in = null;
try {
//获取模板
Template template = getConfiguration().getTemplate(templateName);
StringWriter swriter = new StringWriter();
//生成文件
template.process(dataMap, swriter);
in = new ByteArrayInputStream(swriter.toString().getBytes("utf-8"));//这里一定要设置utf-8编码 否则导出的word中中文会是乱码
} catch (Exception e) {
logger.error("模板生成错误!");
}
return in;
}
}
FreemarkerTest类
import com.example.meeting.util.FreeMarkUtils;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public class FreemarkerTest {
private static String document="document.xml";
//outputStream 输出流可以自己定义 浏览器或者文件输出流
public static void createDocx(Map dataMap, OutputStream outputStream) {
ZipOutputStream zipout = null;
try {
/*//图片配置文件模板
ByteArrayInputStream documentXmlRelsInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentXmlRels);*/
//内容模板
ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, document);
//最初设计的模板
//File docxFile = new File(WordUtils.class.getClassLoader().getResource(template).getPath());
File docxFile = new File("xxxx\\会议纪要.zip");//换成自己的zip路径
if (!docxFile.exists()) {
docxFile.createNewFile();
}
ZipFile zipFile = new ZipFile(docxFile);
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
zipout = new ZipOutputStream(outputStream);
//开始覆盖文档------------------
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) {
zipout.putNextEntry(new ZipEntry(next.getName()));
if ("word/document.xml".equals(next.getName())) {//如果是word/document.xml由我们输入
if (documentInput != null) {
while ((len = documentInput.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
documentInput.close();
}
} else {
while ((len = is.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
is.close();
}
}
}
} catch (Exception e) {
System.out.println("word导出失败:"+e.getStackTrace());
//logger.error();
}finally {
if(zipout!=null){
try {
zipout.close();
} catch (IOException e) {
System.out.println("io异常");
}
}
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
System.out.println("io异常");
}
}
}
}
public static void main(String arg[]){
Map dataMap=new HashMap();
ArrayList minuteList=new ArrayList();
MinuteTest minuteTest1=new MinuteTest();
minuteTest1.setMeeting_decision_content("决策1");
minuteTest1.setMeeting_decision_executor("执行者1");
minuteTest1.setMeeting_decision_deadline("截至日期1");
minuteList.add(minuteTest1);
MinuteTest minuteTest2=new MinuteTest();
minuteTest2.setMeeting_decision_content("决策2");
minuteTest2.setMeeting_decision_executor("执行者2");
minuteTest2.setMeeting_decision_deadline("截至日期2");
minuteList.add(minuteTest2);
dataMap.put("meeting_name", "如何使象牙山发展得更加美好");
dataMap.put("time", "2019-09-15 15:30");
dataMap.put("site", "会议室212");
dataMap.put("organizer", "张三");
dataMap.put("department", "策划部");
dataMap.put("attendee", "谢大脚、谢广坤、刘能");
dataMap.put("meeting_content", "关于象牙山发展中的每个人的义务");
dataMap.put("recorder", "王五");
dataMap.put("checker", "大老板");
dataMap.put("minuteList",minuteList);
//指定输出docx路径
File outFile = new File("xxx\\test.docx") ;
try {
createDocx(dataMap,new FileOutputStream(outFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
MinuteTest实体类
public class MinuteTest {
private String meeting_decision_content;
private String meeting_decision_executor;
private String meeting_decision_deadline;
public String getMeeting_decision_content() {
return meeting_decision_content;
}
public void setMeeting_decision_content(String meeting_decision_content) {
this.meeting_decision_content = meeting_decision_content;
}
public String getMeeting_decision_executor() {
return meeting_decision_executor;
}
public void setMeeting_decision_executor(String meeting_decision_executor) {
this.meeting_decision_executor = meeting_decision_executor;
}
public String getMeeting_decision_deadline() {
return meeting_decision_deadline;
}
public void setMeeting_decision_deadline(String meeting_decision_deadline) {
this.meeting_decision_deadline = meeting_decision_deadline;
}
}
在FreemarkerTest中运行后结果:
来源:oschina
链接:https://my.oschina.net/u/4286896/blog/4327675