您的位置:首页 > 编程语言 > Java开发

Java使用freemark生成word

2016-06-12 15:00 411 查看
一、做web项目的开发,难免需要跟各种文档打交道,像excel、word等,前阵子工作中就遇到需要导出word文档,上网找了一些资料,在word导出这方便有很多的工具可以使用,jacob、poi、java2word、itext,最后选定了用itext来导出word,网上一些资料说itext导出word功能太简单,不过通过使用之后,封装工具类,使用起来也挺方便的,导出的word文档看起来也不错,总体来说达到要求,但是在某些细节方面很难达到一致,比如:字体、行距、字体间距、首行缩进等。

二、鉴于itext导出的word有一些小问题,需要另找其他的方式,通过一个同事的知道了可用freemark模板来导出word,其效果能与要求的demo word文档达到惊人的一致,而且使用也很方面。总的来说就是制作模板(动态的数据用占位符${string}表示),用真实数据代理模板中的占位符,最后生成word。下面看例子:

1、制作模板

先用office word做一个模板word文档,${usrName}、${nowDate}占位符



2、用office word将模板word另存为xml



如有勾选仅保存数据(D),后面会有一个确认选择框,点击保持WordML(K)



3、讲xml文件的后缀改为.ftl

4、编辑.ftl文件

a、用${string}替换需要动态生成的数据,这一步我们在制作模板的时候就已经编写好了,这里不需要再编辑,需要主意的是在装换成xml文件的时候,占位符可能会被分成多个,如上面的${userName}可能会被分开成${userNam和e},这时需要把e}合到${userNam标签里面,并删除掉e}相关的标签。

b、表格循环用标签<#list table1 
as object> </#list>(类似for (String[] object:
table1 ){}),详细语法请百度搜索。

首先介绍几个标签,<w:tbl>表格标签类似HTML的<table>,<w:tr>类似HTML的<tr>。<w:tc></w:tc>每一个单元格,下面以表1为例子:

通过关键搜索找到表1的<w:tbl>,在<w:tbl>会有一些子标签,<w:tblPr></w:tblPr>定义表格的一些格式,<w:tblGrid></w:tblGrid>每一列的长度,我们不需要去修改标签的任何内容和格式,因为在制作模板的时候,我们已经设计好了。

<w:tbl>的子标签还有<w:tr></w:tr>,表示每一行的数据,我们所要做的是找到第二个<w:tr>(第一个是表格标题,固定的,不需要循环),然后删除掉第二个后面的<w:tr>,接下来将第二个<w:tr>包裹在我们的循环标签<#list table1 
as object> </#list>内就行。





再接下来取出数据填充。依次找到<w:tr>、<w:tc>、<w:p>、<w:r&g
4000
t;、<w:t>(由于设计模板的时候,第四列里面的数据为空的,生成XML的时候是没有<w:r></w:r>和<w:t></w:t>,需要我们自己添加,建议设计模板的时候不要留空数据,避免这种情况出现),填充<w:t>1</w:t>(<w:t>广州</w:t>
|| <w:t>37390379</w:t>等)里面的数据,即将<w:t>1</w:t>改为<w:t>${object[0]}</w:t>,object数组对象(<#list table1 
as object> </#list>中的object),0下标,很容易理解。



依照次方法修改其他的表格标签,至此模板已写完,接下来是编程部分。

三、程序

相对来说,程序比较简单!



package test.word;

import java.awt.Desktop;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

public class Test {

/**
* 获取数据
* @return
* @throws Exception
*/
private static Map<String, Object> getData() throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("userName", "admin");//对应模板中的${userName}
map.put("nowDate", new Date().toString());//对应模板中的${nowDate}
List<String[]> tablt1 = new ArrayList<String[]>();
tablt1.add(new String[]{"1","广州","838973","--"});
tablt1.add(new String[]{"2","佛山","115542","--"});
tablt1.add(new String[]{"3","合计","955845","--"});
map.put("table1", tablt1);//<#list table1 as object></#list>
//其他数据
return map;
}
public static void main(String[] args) throws Exception {
createWord(getData(), "test.ftl", "F:/test/", "test"+System.currentTimeMillis()+".doc");
}

/**
*
* @param dataMap 数据
* @param templateName 模板名称
* @param filePath 保存文件路劲
* @param fileName 保存文件名
*/
public static void createWord(Map<?, ?> dataMap, String templateName,
String filePath, String fileName) {
try {
Configuration configuration = new Configuration();

configuration.setDefaultEncoding("UTF-8");

// ftl模板文件统一放至 test.ftl包下面
configuration.setClassForTemplateLoading(Test.class, "/test/word/");

// 获取模板
Template template = configuration.getTemplate(templateName);

File outFile = new File(filePath + File.separator + fileName);
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}

// 将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFile), "UTF-8"));
// 生成文件
template.process(dataMap, out);

out.flush();
out.close();
Desktop desktop = Desktop.getDesktop();
desktop.open(new File(filePath + File.separator + fileName));
} catch (Exception e) {
e.printStackTrace();
}
}
}


导出结果:



与原始文档对比,可以看到用户名、日期和表1已经被替换过啦:



源码:http://download.csdn.net/detail/op635915376/9547101
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java word freemark