Java使用freeMarker动态生成复杂word
Java使⽤freeMarker动态⽣成复杂word 最近的⼀个项⽬需要根据业务,在服务器端根据数据动态⽣成word,包括填⼊数据、图⽚,根据内容控制表格的⾏数。所以就去⽹上搜索java操作word的第三⽅库。然后试了⼀下,感觉到很⿇烦,光是填⼊数据这个⼩⼩的功能,都⼗分难写。正当⼀筹莫展之际,看到了⽹上⼤佬的⽅法: 将word转成xml,再使⽤freeMark对xml⽂档操作,最后将xml转成word。最后⾃⼰看别⼈的⽂章实现了下,确实简单⽅便。
下⾯教⼤家如何实现:简单数据填充、插⼊图⽚、动态插⼊表格。
下⾯是我写好了的模板word:
我们现在要做的是,根据数据动态填写姓名、头像图⽚、成绩。
⼀、将word⽂件转成xml⽂件
不要直接改后缀名,不然打开全是乱码!在保存界⾯选择“另存为”,然后保存类型选择xml。
⼆、对xml⽂件进⾏处理
使⽤freemarker语法对xml⽂档进⾏处理,然后才能填充。freemarker功能强⼤,⼀些逻辑判断都是可以实现的,在此就只讲我们需要⽤到的语法。先将xml⽂件拷贝复制进idea中,然后使⽤idea的格式化功能,就能⽐较清晰的看到xml⽂档的结构。
1、⾸先,我们定位到“我叫⼩明”这⼀句:
将其替换:
2、替换图⽚。图⽚在xml中以base64的⽅式存储,当你看到⼀⼤段不知所云的字符时你就到了。
将字符替换为${image}
3、动态⽣成表格的操作。<w:tr></w:tr>代表word表格的⼀⾏。下⾯的xml对应word表格中的⼀⾏ “数学”  “97”。
<w:tr w:rsidR="00EB70DF" w:rsidTr="00EB70DF">
<w:tc>
<w:tcPr>
<w:tcW w:w="4148" w:type="dxa"/>
</w:tcPr>
<w:p w:rsidR="00EB70DF" w:rsidRDefault="00EB70DF" w:rsidP="00EB70DF">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>数学</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="4148" w:type="dxa"/>
</w:tcPr>
<w:p w:rsidR="00EB70DF" w:rsidRDefault="00EB70DF" w:rsidP="00EB70DF">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
抖音IP地址
<w:t>97</w:t>
西班牙vs哥斯达黎加
</w:r>
</w:p>
</w:tc>
</w:tr>
只需在这⼀段最外层,包上循环语句<#list grades as grade></#list>,然后将“数学”改为${urseName},“97” 改为${grade.score}。
<#list grades as grade> //添加
<w:tr w:rsidR="00EB70DF" w:rsidTr="00EB70DF">
<w:tc>
<w:tcPr>
<w:tcW w:w="4148" w:type="dxa"/>
</w:tcPr>
<w:p w:rsidR="00EB70DF" w:rsidRDefault="00EB70DF" w:rsidP="00EB70DF">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>${urseName}</w:t> //改为占位符
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="4148" w:type="dxa"/>
</w:tcPr>
<w:p w:rsidR="00EB70DF" w:rsidRDefault="00EB70DF" w:rsidP="00EB70DF">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>${grade.score}</w:t> //改为占位符
</w:r>
</w:p>
</w:tc>
</w:tr>
邮政储蓄个人网上银行</#list> //添加
⾄此,xml⽂件的处理完成。接下来进⼊代码编写阶段。
三、代码编写
⾸先要导⼊freemarker的依赖包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
测试代码编写:
public class FMarker {
public static void main(String[] args) {
HashMap<String, Object> map = new HashMap<>();
DocumentHandler dh = new DocumentHandler();
DocumentHandler dh = new DocumentHandler();
Template t = dh.getTemplate();
Writer out = dh.getWriter();
List<Grade> grades = new ArrayList<>();
grades.add(new Grade("语⽂","70"));
grades.add(new Grade("英语","80"));
grades.add(new Grade("物理","90"));
/
/注意变量名要与xml中占位符保持⼀致
map.put("name","⼩红");
map.put("grades",grades);
map.put("image",dh.getImageStr());
word打开是乱码
}
}
class DocumentHandler {
private Configuration configuration = null;
public DocumentHandler() {
}
//将xml⽂件转成模板
public Template getTemplate() {
configuration.Class(),
"/com/test/word");
Template t = null;
try {
t = Template("l");//模板xml路径
t.setEncoding("utf-8");
} catch (IOException e) {
e.printStackTrace();
}
return t;
}
//获得输出流对象
public Writer getWriter() {
//填充后,新⽂件路径
File outFile = new File("D:\\ideacode\\uploadServlet\\src\\main\\java\\com\\test\\word\\newDoc1.doc");        Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFile), "utf-8"
));
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}
return out;
}
//转化⽣成word⽂件
public void createDoc(Template t, Map dataMap, Writer out) {
try {
t.process(dataMap, out);
out.close();
} catch (TemplateException | IOException e) {
e.printStackTrace();
}
}
//将图⽚转化成BASE64
public String getImageStr(){
//新图⽚路径
String imageFile = "D:\\ideacode\\uploadServlet\\src\\main\\java\\com\\test\\word\\newImage.jpg";
String imageFile = "D:\\ideacode\\uploadServlet\\src\\main\\java\\com\\test\\word\\newImage.jpg";        InputStream in = null;
byte[] data = null;
try{
in = new FileInputStream(imageFile);
data = new byte[in.available()];
in.close();梦见水是什么意思
}catch (IOException e){
e.printStackTrace();
}
BASE64Encoder base64Encoder = new BASE64Encoder();
de(data);
}
}
项⽬结构:
DocumentHanlder是核⼼操作类
2022法定节假日FMarker是来写测试函数的
Grade类就两个成员变量:courseName,score。我就不写出来了。
newDoc1.doc是⽣成的word⽂档
newImage是准备插⼊的图⽚
最终结果:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。