该方法借助freemarker的JAR包即可。
参考:
所需工具:
步骤:
1、在word中编辑好模版样式,设置好占位符,注意图片最好先黏上去
2、在word中,文件-另存为-XML格式
3、使用工具格式化上图的XML文件
a.在表格数据的TR中加入 和#list>
b.将XML文件中图片的BASE64转换为相应的占位符
4、在Eclipse中新建文件teample-pic.ftl,将XML的数据粘贴进去
5、使用工具类WordUtil.java生成word文件
代码:
package com.test;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import sun.misc.BASE64Encoder;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class WordUtil {
/**
* @param dataMap
* word中需要展示的动态数据,用map集合来保存
* @param templateName
* word模板名称,例如:teample.ftl
* @param filePath
* 文件生成的目标路径,例如:D:/
* @param fileName
* 生成的文件名称
*/
@SuppressWarnings("unchecked")
public static void createWord(Map dataMap, String templateName,
String filePath, String fileName) {
try {
// 创建配置实例
Configuration configuration = new Configuration();
// 设置编码
configuration.setDefaultEncoding("UTF-8");
// ftl模板文件
configuration.setClassForTemplateLoading(WordUtil.class,
"/com/test/");
// 获取模板
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();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将图片转换为BASE64为字符串
* @param filename
* @return
* @throws IOException
*/
public static String getImageString(String filename) throws IOException {
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(filename);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
throw e;
} finally {
if(in != null) in.close();
}
BASE64Encoder encoder = new BASE64Encoder();
return data != null ? encoder.encode(data) : "";
}
}
package com.test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestJava2Word {
public static void main(String[] args) throws IOException {
createWord();
//String BASE64 = WordUtil.getImageString("D://doc//friend.jpg");
//System.out.println(BASE64);
}
public static void createWord() {
Map dataMap = new HashMap();
/** 组装数据 */
dataMap.put("username","张三");
dataMap.put("address","深圳市南山区西丽镇");
dataMap.put("num", Math.floor(Math.random()*10));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日");
dataMap.put("date",sdf.format(new Date()));
dataMap.put("content","华语天王周杰伦在北京召开周杰伦战略发布会。在发布会上,推出时尚与专业结合的:引起了广泛的关注和讨论。现在终于正式与大家见面,天猫、官网同时上线,首卖期间还有好礼相赠!买就送,就是这么任性!");
List> newsList=new ArrayList>();
for(int i=1;i<=10;i++){
Map map=new HashMap();
map.put("name", "王"+i);
map.put("tel", "137"+i);
map.put("age", "年龄"+i);
map.put("address", System.currentTimeMillis());
newsList.add(map);
}
dataMap.put("myListData",newsList);
String myPic = "";
String myPic2 = "";
try {
myPic = WordUtil.getImageString("D://doc//ganen.jpg");
myPic2 = WordUtil.getImageString("D://doc//friend.jpg");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataMap.put("myPic", myPic);
dataMap.put("myPic2", myPic2);
//文件路径
String filePath= "D://doc";
//文件名称
String fileName = System.currentTimeMillis()+".doc";
/** 生成word */
WordUtil.createWord(dataMap, "teample-pic.ftl", filePath, fileName);
}
}
模版文件:
teample.ftl等见附件。
注意两个问题:
1、如果图片是网络图片时,getImageString() 方法中不可使用本地new FileInputStream处理图片,应该使用new URL()获取链接,然后openConnection(),最后connection.getInputStream()获取流
2、InputStream流转Byte[]时,使用new byte[in.available]可能会有问题,推荐使用IOUtils.toByteArray(in) 转换为byte数组。
在commons-io包中org.apache.commons.io.IOUtils类的toByteArray(InputStream input)已经有实现了,我们可以参考下思路,完成我们的方法,我们可以用类似下面的代码实现inputStream转化为byte[]数组
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}
下面是IOUtils中摘录出与toByteArray相关的方法
org.apache.commons.io.IOUtils.toByteArray
方法如下:
public static byte[] toByteArray(InputStream input)
throws IOException
{
ByteArrayOutputStream output = new ByteArrayOutputStream();
copy(input, output);
return output.toByteArray();
}
public static int copy(InputStream input, OutputStream output)
throws IOException
{
long count = copyLarge(input, output);
if (count > 2147483647L) {
return -1;
}
return (int)count;
}
public static long copyLarge(InputStream input, OutputStream output)
throws IOException
{
byte[] buffer = new byte[4096];
long count = 0L;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
。。。