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、[email protected]$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; } }