package com.report.word;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* 传入数据为HashMap对象,对象中的Key代表word模板中要替换的字段,Value代表用来替换的值。
* 1. word模板中所有要替换的字段(即HashMap中的Key)以特殊字符开头和结尾,如:$code$、$date$……以免执行错误的替换。
* 2. 所有要替换为图片的字段,Key以$image_开头,Value为图片的全路径或链接。
* 3. 在标签处插入内容,Key为标签名,以Bookmark_开头,假如内容为图片以Bookmark_image_开头
* 4. 要替换表格中的数据时,HashMap中的Key格式为“$tableN@R”,其中:N代表word模板中的第N张表格,
R代表从表格的第R行开始替换;Value为ArrayList对象,ArrayList中包含的对象统一为String[],一条String[]代
表一行数据,ArrayList中第一条记录为特殊记录,记录的是表格中要替换的列号,如:要替换第一列、第三列、
第五列的数据,则第一条记录为String[3] {"1","3","5"}
*
*/
public class Map2Word {
private boolean saveOnExit;
/**
* word文档
*/
private Dispatch doc = null;
/**
* word运行程序对象s
*/
private ActiveXComponent word;
/**
* 所有word文档
*/
private Dispatch documents;
private boolean isword = true;
public static Map2Word getInstance() {
return new Map2Word();
}
/**
* 构造函数
*/
private Map2Word() {
if (word == null) {
try {
word = new ActiveXComponent("Word.Application");
} catch (Exception e) {
word = new ActiveXComponent("wps.Application");
isword = false;
}
word.setProperty("Visible", new Variant(false));
}
if (documents == null) {
documents = word.getProperty("Documents").toDispatch();
}
saveOnExit = false;
}
/**
* 设置参数:退出时是否保存
*
* @param saveOnExit
* boolean true-退出时保存文件,false-退出时不保存文件
*/
public void setSaveOnExit(boolean saveOnExit) {
this.saveOnExit = saveOnExit;
}
/**
* 得到参数:退出时是否保存
*
* @return boolean true-退出时保存文件,false-退出时不保存文件
*/
public boolean getSaveOnExit() {
return saveOnExit;
}
/**
* 打开文件
*
* @param inputDoc
* String 要打开的文件,全路径
* @return Dispatch 打开的文件
*/
public Dispatch open(String inputDoc) {
return Dispatch.call(documents, "Open", inputDoc).toDispatch();
}
/**
* 选定内容
*
* @return Dispatch 选定的范围或插入点
*/
public Dispatch select() {
return word.getProperty("Selection").toDispatch();
}
/**
* 把选定内容或插入点向上移动
*
* @param selection
* Dispatch 要移动的内容
* @param count
* int 移动的距离
*/
public void moveUp(Dispatch selection, int count) {
for (int i = 0; i < count; i++) {
Dispatch.call(selection, "MoveUp");
}
}
/**
* 把选定内容或插入点向下移动
*
* @param selection
* Dispatch 要移动的内容
* @param count
* int 移动的距离
*/
public void moveDown(Dispatch selection, int count) {
for (int i = 0; i < count; i++) {
Dispatch.call(selection, "MoveDown");
}
}
/**
* 把选定内容或插入点向左移动
*
* @param selection
* Dispatch 要移动的内容
* @param count
* int 移动的距离
*/
public void moveLeft(Dispatch selection, int count) {
for (int i = 0; i < count; i++) {
Dispatch.call(selection, "MoveLeft");
}
}
/**
* 把选定内容或插入点向右移动
*
* @param selection
* Dispatch 要移动的内容
* @param count
* int 移动的距离
*/
public void moveRight(Dispatch selection, int count) {
for (int i = 0; i < count; i++) {
Dispatch.call(selection, "MoveRight");
}
}
/**
* 把插入点移动到文件首位置
*
* @param selection
* Dispatch 插入点
*/
public void moveStart(Dispatch selection) {
Dispatch.call(selection, "HomeKey", new Variant(6));
}
/**
* 从选定内容或插入点开始查找文本
*
* @param selection
* Dispatch 选定内容
* @param toFindText
* String 要查找的文本
* @return boolean true-查找到并选中该文本,false-未查找到文本
*/
public boolean find(Dispatch selection, String toFindText) {
// 从selection所在位置开始查询
Dispatch find = word.call(selection, "Find").toDispatch();
// 设置要查找的内容
Dispatch.put(find, "Text", toFindText);
// 向前查找
Dispatch.put(find, "Forward", "True");
// 设置格式
Dispatch.put(find, "Format", "True");
// 大小写匹配
Dispatch.put(find, "MatchCase", "True");
// 全字匹配
Dispatch.put(find, "MatchWholeWord", "True");
// 查找并选中
return Dispatch.call(find, "Execute").getBoolean();
}
/**
* 全局替换
*
* @param selection
* Dispatch 选定内容或起始插入点
* @param oldText
* String 要替换的文本
* @param newText
* String 替换为文本
*/
public void replaceAll(Dispatch selection, String oldText, Object replaceObj) {
// 移动到文件开头
moveStart(selection);
if (oldText.startsWith(WordConst.KEY_TABLE) && replaceObj instanceof ArrayList) {
replaceTable(selection, oldText, (ArrayList) replaceObj);
} else {
String newText = (String) replaceObj;
if (newText == null) {
newText = "";
}
if (oldText.startsWith(WordConst.KEY_IMAGE) && !newText.trim().equals("")) {
while (find(selection, oldText)) {
replaceImage(selection, newText);
Dispatch.call(selection, "MoveRight");
}
} else if (oldText.startsWith(WordConst.KEY_BOOKMARK) && !newText.trim().equals("")) {
replaceBookMark(oldText, newText);
} else {
while (find(selection, oldText)) {
replace(selection, newText);
Dispatch.call(selection, "MoveRight");
}
}
}
}
/**
* 全局替换(不替换图片)
*
* @param selection
* Dispatch 选定内容或起始插入点
* @param oldText
* String 要替换的文本
* @param newText
* String 替换为文本
*/
public void replaceNoImage(Dispatch selection, String oldText, Object replaceObj) {
// 移动到文件开头
moveStart(selection);
if (oldText.startsWith(WordConst.KEY_TABLE) && replaceObj instanceof ArrayList) {
replaceTable(selection, oldText, (ArrayList) replaceObj);
} else {
String newText = (String) replaceObj;
if (newText == null) {
newText = "";
}
if (oldText.startsWith(WordConst.KEY_IMAGE) && !newText.trim().equals("")) {
//nothing to do
} else if (oldText.startsWith(WordConst.KEY_BOOKMARK) && !newText.trim().equals("")) {
replaceBookMark(oldText, newText);
} else {
while (find(selection, oldText)) {
replace(selection, newText);
Dispatch.call(selection, "MoveRight");
}
}
}
}
/**
* 选定书签名插入内容
*
* @param newText
* String 书签名
* @param newText
* String 插入内容
*/
public void replaceBookMark(String bookMarkKey, String info) {
Dispatch bookMarks = word.call(doc, "Bookmarks").toDispatch();
int bCount = Dispatch.get(bookMarks, "Count").getInt();
boolean bookMarkExist = word.call(bookMarks, "Exists", bookMarkKey).toBoolean();
if (bookMarkExist) {
Dispatch rangeItem = Dispatch.call(bookMarks, "Item", bookMarkKey)
.toDispatch();
Dispatch range = Dispatch.call(rangeItem, "Range").toDispatch();
if (bookMarkKey.startsWith(WordConst.KEY_BOOKMARK_IMAGE)
&& (info.startsWith("http://") || info.startsWith("https://"))) {
replaceImage(range, info);
Dispatch.call(bookMarks, "Add", bookMarkKey, range);
} else {
replace(range, info);
Dispatch.call(bookMarks, "Add", bookMarkKey, range);
}
}
}
/**
* 把选定内容替换为设定文本
*
* @param selection
* Dispatch 选定内容
* @param newText
* String 替换为文本
*/
public void replace(Dispatch selection, String newText) {
// 设置替换文本
Dispatch.call(selection, "Delete");
Dispatch.put(selection, "Text", newText);
}
/**
* 替换图片
*
* @param selection
* Dispatch 图片的插入点
* @param imagePath
* String 图片文件(全路径)
*/
public void replaceImage(Dispatch selection, String imagePath) {
Dispatch.call(selection, "Delete");
Dispatch.call(Dispatch.get(selection, "InLineShapes").toDispatch(),
"AddPicture", imagePath);
}
/**
* 替换表格
*
* @param selection
* Dispatch 插入点
* @param tableName
* String 表格名称,形如table$1@1、table$2@1...table$R@N,R代表从表格中的第N行开始填充,
* N代表word文件中的第N张表
* @param fields
* HashMap 表格中要替换的字段与数据的对应表
*/
public void replaceTable(Dispatch selection, String tableName,
ArrayList dataList) {
if (dataList.size() <= 1) {
return;
}
// 要填充的列
String[] cols = (String[]) dataList.get(0);
// 表格序号
String tbIndex = tableName.substring(
tableName.lastIndexOf(WordConst.KEY_TABLE) + WordConst.KEY_TABLE.length(),
tableName.lastIndexOf(WordConst.KEY_SPILT));
// 从第几行开始填充
int fromRow = Integer.parseInt(tableName.substring(tableName.lastIndexOf(WordConst.KEY_SPILT) + 1));
// 所有表格
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
// 要填充的表格
Dispatch table = Dispatch.call(tables, "Item", new Variant(tbIndex))
.toDispatch();
// 表格的所有行
Dispatch rows = Dispatch.get(table, "Rows").toDispatch();
// 填充表格
for (int i = 1; i < dataList.size(); i++) {
// 某一行数据
String[] datas = (String[]) dataList.get(i);
// 在表格中添加一行
if (Dispatch.get(rows, "Count").getInt() < fromRow + i - 1)
Dispatch.call(rows, "Add");
// 填充该行的相关列
for (int j = 0; j < datas.length; j++) {
// 得到单元格
Dispatch cell = Dispatch.call(table, "Cell",
Integer.toString(fromRow + i - 1), cols[j])
.toDispatch();
// 选中单元格
Dispatch.call(cell, "Select");
// 设置格式
Dispatch font = Dispatch.get(selection, "Font").toDispatch();
Dispatch.put(font, "Bold", "0");
Dispatch.put(font, "Italic", "0");
// 输入数据
Dispatch.put(selection, "Text", datas[j]);
}
}
}
/**
* 保存文件
*
* @param outputPath
* String 输出文件(包含路径)
*/
public void saveAsWord(String outputPath) {
if (isword) {
Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(),
"FileSaveAs", outputPath);
} else {
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {
outputPath, new Variant(0) }, new int[1]);
}
}
/**
* 保存文件
*
* @param outputPath
* String 输出文件(包含路径)
*/
public void saveAsHtml(String outputPath) {
/*
* new Variant(10)筛选过的网页
* new Variant(9) 单个文件网页
* new Variant(8) 另存为网页
* new Variant(7) 另存为txt格式
* new Variant(6) 另存为rtf格式
* new Variant(0) 另存为doc格式
*/
Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {
outputPath, new Variant(10) }, new int[1]);
}
/**
* 关闭文件
*
* @param document
* Dispatch 要关闭的文件
*/
public void close(Dispatch doc) {
Dispatch.call(doc, "Close", new Variant(saveOnExit));
word.invoke("Quit", new Variant[] {});
word = null;
}
/**
* 根据模板、数据生成word文件
*
* @param inputPath
* String 模板文件(包含路径)
* @param outPath
* String 输出文件(包含路径)
* @param data
* Map 数据包(包含要填充的字段、对应的数据)
* @throws Exception
*/
public void generateFile(String inputPath, String outPath, Map data) throws Exception {
String oldText;
Object newValue;
try {
if (doc == null) {
doc = open(inputPath);
}
Dispatch selection = select();
Iterator keys = data.keySet().iterator();
while (keys.hasNext()) {
oldText = (String) keys.next();
newValue = data.get(oldText);
if (outPath.endsWith(".html")) {
replaceNoImage(selection, oldText, newValue);
} else {
replaceAll(selection, oldText, newValue);
}
}
if (outPath.endsWith(".doc")) {
saveAsWord(outPath);
} else if (outPath.endsWith(".html")) {
saveAsHtml(outPath);
}
} catch (Exception e) {
throw e;
} finally {
if (doc != null) {
close(doc);
}
}
}
/**
* 执行VBA方法
* @param mothName 方法名
*/
public void invokeVBA(String mothName) {
Dispatch.call(word, "Run", new Variant(mothName));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) throws Exception {
Map data = new HashMap();
// 基本替换
data.put(WordConst.key("title"), "word模板生成word文档使用说明");
data.put(WordConst.key("reportdate"), "2014年01月14日");
// 表格固定方式
data.put(WordConst.key("table11"), "1");
data.put(WordConst.key("table12"), "张三");
data.put(WordConst.key("table13"), "男");
data.put(WordConst.key("table14"), "180cm");
data.put(WordConst.key("table21"), "2");
data.put(WordConst.key("table22"), "李四");
data.put(WordConst.key("table23"), "女");
data.put(WordConst.key("table24"), "170cm");
// 表格动态方式
List table1 = new ArrayList();
String[] fieldName1 = { "1", "2", "3", "4" };
table1.add(fieldName1);
String[] field11 = { "1", "张三", "男", "180cm" };
table1.add(field11);
String[] field21 = { "2", "李四", "女", "170cm" };
table1.add(field21);
String[] field31 = { "3", "李四", "女", "170cm" };
table1.add(field31);
data.put(WordConst.table(2, 2), table1);
// 图片
data.put(WordConst.image("test"), "http://news.baidu.com/z/resource/r/image/2014-01-16/9bbfbcafcb085927b47ab341c4272e81.jpg");
// 书签
data.put(WordConst.bookmark("test"), "书签1");
data.put(WordConst.bookmark_image("test"), "http://news.baidu.com/z/resource/r/image/2014-01-16/9bbfbcafcb085927b47ab341c4272e81.jpg");
Map2Word m2w = Map2Word.getInstance();
long time1 = System.currentTimeMillis();
m2w.generateFile("E:/template.doc", "E:/result.doc", data);
System.out.println("time cost : " + (System.currentTimeMillis() - time1));
}
}
package com.report.word;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class WordConst {
public static final String KEY_SIGN = "$";
public static final String KEY_SPILT = "@";
public static final String KEY_IMAGE = "$image_";
public static final String KEY_TABLE = "$table";
public static final String KEY_BOOKMARK = "Bookmark_";
public static final String KEY_BOOKMARK_IMAGE = "Bookmark_image_";
/**
* key转为$key$
* @param key
* @return
*/
public static String key(String key) {
return KEY_SIGN + key + KEY_SIGN;
}
/**
* key转为$image_key
* @param key
* @return
*/
public static String image(String key) {
return KEY_IMAGE + key;
}
/**
* 如果table=1,row=2,key转为$table1@2
* @param table word模板中第几个表格,从1开始
* @param row 表格第几行开始填充数据,从1开始
* @return
*/
public static String table(int table, int row) {
return KEY_TABLE + table + KEY_SPILT + row;
}
/**
* key转为Bookmark_key
* @param key
* @return
*/
public static String bookmark(String key) {
return KEY_BOOKMARK + key;
}
/**
* key转为Bookmark_image_key
* @param key
* @return
*/
public static String bookmark_image(String key) {
return KEY_BOOKMARK_IMAGE + key;
}
/**
* 自动对map中的key添加$,如$key$
* @param data 要生成的map
* @return 生成后的map
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Map generate(Map data) {
if (data == null || data.size() == 0) {
return data;
}
Map map = new HashMap();
Set temp = data.keySet();
for (Object key : temp) {
map.put(key((String)key), data.get(key));
}
return map;
}
}