背景:业务业务,纯粹业务需要,导出pdf或者word尝试了很多方法,决定还是freemarker比较舒适,接下来讲一下操作步骤。
1、maven引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>2、确定word模板并占位符标识
蓝色标识框 可以直接用freemarker指令标识上,例如 ${data.name}。如果不用freemarker,也可以如图对象属性名称标识,利于后期xml修改。
黄色标识框 最好列一行数据,list语法循环生成的word<w:tcW w:w="1681" w:type="dxa"/>,第一列是1681,第二列就变了,很好奇没找到答案,然后写算法。
3、模板转存成 .xml 格式
4、修改后缀为.ftl
5、freemarker指令
参考中文官方手册: freemarker.foofun.cn/ref_directi…
每行5个算法
<#list risks as risk>
<#-- 判断第一个生成 w:tr 标签 -->
<#if risk_index%5 == 0>
<w:tr>
<#-- 判断不是第四个但是已经后面没有数据 /w:tr 结尾标签 -->
<#if risk_index == (risks?size-1) && risk_index%5!=4>
</w:tr>
</#if>
<#-- 判断第四个生成 /w:tr 结尾标签 -->
<#if risk_index%5 == 4>
</w:tr>
</#if>
</#list>判断选中
<w:tc>
<#-- 判断选择方框对勾 begin -->
<#if risk.selected==1>
<#-- 选择 -->
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312"/>
<w:b/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:sym w:font="Wingdings 2" w:char="0052"/>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312"/>
<w:b/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:t xml:space="preserve"> </w:t>
</w:r>
<#-- 未选□ -->
<#else>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312"/>
<w:b/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<w:t xml:space="preserve">□ </w:t>
</w:r>
</#if>
<#-- 判断选择方框对勾 end -->
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:ascii="仿宋_GB2312"/>
<w:sz w:val="18"/>
<w:szCs w:val="18"/>
</w:rPr>
<#-- 循环取出名称 -->
<w:t>${risk.riskName}</w:t>
</w:r>
</w:p>
</w:tc>6、WordUtil导出方法exportWord
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.Writer;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class IwmWordUtil {
@SuppressWarnings("deprecation")
private static Configuration configuration = new Configuration();
/**
*
* @param entity 占位符需要的freemarker数据
* @param template_src 模板文件路径 (注意:文件路径,例如:/a.ftl)
* @param downFileName 输出文件名称
* @param out_src 输出文件夹路径(注意:文件夹路径,例如:/file/,如果是需要响应到页面下载,则需要自己写一个response流响应到页面)
*/
public static void exportWord(Object entity, String template_src, String downFileName, String out_src) {
configuration.setDefaultEncoding("UTF-8");
configuration.setClassicCompatible(true);
try {
String str = readFile(new File(template_src));
Template t = new Template("name", new StringReader(str), configuration);
File outFile = new File(out_src);
if (!outFile.exists()) {
outFile.mkdirs();
}
File tmpFile = File.createTempFile(downFileName, ".doc", outFile);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tmpFile), "UTF-8"));
t.process(entity, out);
out.flush();
out.close();
System.err.println("生成word成功,文件名: " + tmpFile.getName());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取文件
*
* @param file
* @return
* @throws IOException
*/
public static String readFile(File file) throws IOException {
// 文件很长的话建议使用StringBuffer
StringBuffer FileContent = new StringBuffer();
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
fis = new FileInputStream(file);
isr = new InputStreamReader(fis, "UTF-8");
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
FileContent.append(line);
FileContent.append("\r\n"); // 补上换行符
}
} catch (Exception e) {
e.printStackTrace();
throw new IOException(e.getMessage());
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (isr != null) {
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return FileContent.toString();
}
}