实习接到的第一个任务是“Word文档自动化”,即对现有需求文档做标记处理,而后由客户填写文档,公司收回文档后利用java对标记处进行读写操作,我需要做的就是将word文档内的可操作对象转化为java文件,而后程序员只操作java文件即可。具体过程比较复杂,还用到了JET自动生成模版,这里不做赘述,就讲讲使用Jacob处理读写Word文档的方法。 当然要先标注标签,与此文无关,此处略。
Jacob 是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁。使用Jacob自带的DLL动态链接库,并通过JNI的方式实现了在Java平台上对COM程序的调用。
1. 安装Jacob 使用Jacob首先需要安装Jacob的动态链接库jacob.dll,该文件可以放置于以下三个位置中的任意一个: (1) 工程根目录 (2) %JAVA_HOME%\bin中 (3) System32文件夹中 推荐放在工程根目录中。 其次,需要的Jar包为:java2word.jar 其中已经包含了Jacob的Jar包,不需要也不可以再添加jacob.jar 在进行文档转换中,根据转换中使用到的方法,我们对jacob的方法进行了封装,生成了WordManager类,以便在使用时方便调用: 1 package model; 2 3 import com.jacob.activeX.ActiveXComponent; 4 import com.jacob.com.Dispatch; 5 import com.jacob.com.Variant; 6 7 public class WordManager { 8 // word文档 9 private Dispatch doc; 10 11 // word运行程序对象 12 private ActiveXComponent word; 13 14 // 所有word文档集合 15 private Dispatch documents; 16 17 // 选定的范围或插入点 18 private Dispatch selection; 19 20 private boolean saveOnExit = true; 21 22 /** */ 23 /** 24 * 25 * @param visible 26 * 为true表示word应用程序可见 27 */ 28 public WordManager(boolean visible) { 29 if (word == null) { 30 word = new ActiveXComponent("Word.Application"); 31 word.setProperty("Visible", new Variant(visible)); 32 } 33 if (documents == null) 34 documents = word.getProperty("Documents").toDispatch(); 35 } 36 37 /** */ 38 /** 39 * 设置退出时参数 40 * 41 * @param saveOnExit 42 * boolean true-退出时保存文件,false-退出时不保存文件 43 */ 44 public void setSaveOnExit(boolean saveOnExit) { 45 this.saveOnExit = saveOnExit; 46 } 47 48 /** */ 49 /** 50 * 打开一个已存在的文档 51 * 52 * @param docPath 53 */ 54 public void openDocument(String docPath) { 55 closeDocument(); 56 doc = Dispatch.call(documents, "Open", docPath).toDispatch(); 57 selection = Dispatch.get(word, "Selection").toDispatch(); 58 } 59 60 /************************************** 书签操作 *************************************/ 61 /** */ 62 /** 63 * 获取书签个数 64 * 65 */ 66 public int getLabelCount() { 67 Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch(); 68 int labelCount = Dispatch.get(bookMarks, "Count").getInt(); // 书签数 69 return labelCount; 70 } 71 72 /** */ 73 /** 74 * 获取书签标题 75 * 76 * @param labelIndex 77 */ 78 public String getLabelName(int labelIndex) { 79 Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch(); 80 Dispatch rangeItem = Dispatch.call(bookMarks, "Item", labelIndex) 81 .toDispatch(); 82 String labelName = Dispatch.call(rangeItem, "Name").toString(); 83 return labelName; 84 } 85 86 /** */ 87 /** 88 * 获取书签内容 89 * 90 * @param labelName 91 */ 92 public String getLabelValue(String labelName) { 93 String rawLabelValue = getRawLabelValue(labelName); 94 String labelValue = rawLabelValue.replaceAll("", ""); 95 // 如果含有抬头 96 if (labelName.startsWith("head_")) { 97 labelValue = rawLabelValue 98 .substring(rawLabelValue.indexOf(":") + 1).replaceAll(" ", 99 ""); 100 } 101 // 如果含有头尾 102 if (labelName.startsWith("full_")) { 103 labelValue = rawLabelValue.substring(1, rawLabelValue.length() - 1) 104 .replaceAll(" ", ""); 105 } 106 if(labelName.startsWith("t_")){ 107 labelValue=rawLabelValue.substring(0, rawLabelValue.length()-2); 108 } 109 return labelValue; 110 } 111 112 /** */ 113 /** 114 * 获取书签原始内容 115 * 116 * @param labelName 117 */ 118 public String getRawLabelValue(String labelName) { 119 Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch(); 120 Dispatch rangeItem = Dispatch.call(bookMarks, "Item", labelName) 121 .toDispatch(); 122 Dispatch range = Dispatch.call(rangeItem, "Range").toDispatch(); 123 String rawLabelValue = Dispatch.get(range, "Text").toString(); 124 return rawLabelValue; 125 } 126 127 /** */ 128 /** 129 * 设置书签内容 130 * 131 * @param labelName 132 * @param labelValue 133 */ 134 public void setLabelValue(String labelName, String labelValue) { 135 String rawLabelValue= getRawLabelValue(labelName); 136 String toFindString = getLabelValue(labelName); 137 System.out.println(toFindString); 138 Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch(); 139 Dispatch rangeItem = Dispatch.call(bookMarks, "Item", labelName) 140 .toDispatch(); 141 Dispatch range = Dispatch.call(rangeItem, "Range").toDispatch(); 142 Dispatch.call(range, "Select"); 143 //如果是表格内的标签 144 if (labelName.startsWith("t_")) { 145 Dispatch.put(selection, "Text", new Variant(labelValue)); 146 } 147 //如果是表格外的标签 148 else { 149 if (toFindString == null || toFindString.equals("")) { 150 int rawLen=rawLabelValue.length(); 151 if (labelName.startsWith("head_")) { 152 rawLen=rawLabelValue.substring(rawLabelValue.indexOf(":")).length(); 153 } 154 if (labelName.startsWith("full_")) { 155 rawLen=rawLabelValue.length()-2; 156 } 157 for (int i = 1; i <= rawLen; i++) { 158 toFindString += " "; 159 } 160 } 161 replaceText(toFindString, labelValue); 162 } 163 164 } 165 166 /** */ 167 /** 168 * 把选定选定内容设定为替换文本 169 * 170 * @param toFindText 171 * 查找字符串 172 * @param newText 173 * 要替换的内容 174 * @return 175 */ 176 public boolean replaceText(String toFindString, String newString) { 177 if (!find(toFindString)) { 178 System.out.println(toFindString); 179 return false; 180 } 181 find(toFindString); 182 Dispatch.put(selection, "Text", newString); 183 return true; 184 } 185 186 /************************************** 表操作 ***************************************/ 187 /** */ 188 /** 189 * 获取表格行数 190 * 191 * @param tableIndex 192 * word文档中的第N张表(从1开始) 193 */ 194 public int getRowCount(int tableIndex) { 195 // 所有表格 196 Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 197 // 要填充的表格 198 Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)) 199 .toDispatch(); 200 // 表格的所有行 201 Dispatch rows = Dispatch.get(table, "Rows").toDispatch(); 202 203 return Dispatch.get(rows, "Count").getInt(); 204 } 205 206 /** */ 207 /** 208 * 获取表格某一行的列数 209 * 210 * @param tableIndex 211 * @param rowIndex 212 */ 213 public int getRowColumnCount(int tableIndex, int rowIndex) { 214 // 所有表格 215 Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 216 // 要填充的表格 217 Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)) 218 .toDispatch(); 219 // 表格的所有行 220 Dispatch rows = Dispatch.get(table, "Rows").toDispatch(); 221 // 所需行 222 Dispatch row = Dispatch.call(rows, "Item", new Variant(rowIndex)) 223 .toDispatch(); 224 // 表格数 225 Dispatch cells = Dispatch.get(row, "Cells").toDispatch(); 226 return Dispatch.get(cells, "Count").getInt(); 227 } 228 229 /** */ 230 /** 231 * 获取指定的单元格的数据 232 * 233 * @param tableIndex 234 * @param cellRowIdx 235 * @param cellColIdx 236 */ 237 public String getCellValue(int tableIndex, int cellRowIdx, int cellColIdx) { 238 // 所有表格 239 Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 240 // 要获取的表格 241 Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)) 242 .toDispatch(); 243 Dispatch cell = Dispatch.call(table, "Cell", new Variant(cellRowIdx), 244 new Variant(cellColIdx)).toDispatch(); 245 Dispatch range = Dispatch.get(cell, "Range").toDispatch(); 246 247 String cellValue = Dispatch.get(range, "Text").toString() 248 .replaceAll("", "").trim(); 249 250 return cellValue; 251 } 252 253 /** */ 254 /** 255 * 在指定的单元格里填写数据 256 * 257 * @param tableIndex 258 * @param cellRowIdx 259 * @param cellColIdx 260 * @param cellValue 261 */ 262 public void setCellValue(int tableIndex, int cellRowIdx, int cellColIdx, 263 String cellValue) { 264 // 所有表格 265 Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 266 // 要填充的表格 267 Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)) 268 .toDispatch(); 269 Dispatch cell = Dispatch.call(table, "Cell", new Variant(cellRowIdx), 270 new Variant(cellColIdx)).toDispatch(); 271 Dispatch.call(cell, "Select"); 272 Dispatch.put(selection, "Text", cellValue); 273 } 274 275 /** */ 276 /** 277 * 增加一行 278 * 279 * @param tableIndex 280 * word文档中的第N张表(从1开始) 281 */ 282 public void addRow(int tableIndex) { 283 Dispatch tables = Dispatch.get(doc, "Tables").toDispatch(); 284 // 要填充的表格 285 Dispatch table = Dispatch.call(tables, "Item", new Variant(tableIndex)) 286 .toDispatch(); 287 // 表格的所有行 288 Dispatch rows = Dispatch.get(table, "Rows").toDispatch(); 289 Dispatch.call(rows, "Add"); 290 } 291 292 /** */ 293 /** 294 * 从选定内容或插入点开始查找文本 295 * 296 * @param toFindText 297 * 要查找的文本 298 * @return boolean true-查找到并选中该文本,false-未查找到文本 299 */ 300 public boolean find(String toFindString) { 301 if (toFindString == null || toFindString.equals("")) 302 return false; 303 // 从selection所在位置开始查询 304 Dispatch find = Dispatch.call(selection, "Find").toDispatch(); 305 // 设置要查找的内容 306 Dispatch.put(find, "Text", toFindString); 307 // 向前查找 308 Dispatch.put(find, "Forward", "True"); 309 // 设置格式 310 Dispatch.put(find, "Format", "True"); 311 // 大小写匹配 312 Dispatch.put(find, "MatchCase", "True"); 313 // 全字匹配 314 Dispatch.put(find, "MatchWholeWord", "True"); 315 // 查找并选中 316 return Dispatch.call(find, "Execute").getBoolean(); 317 } 318 319 /** */ 320 /** 321 * 文件保存或另存为 322 * 323 * @param savePath 324 * 保存或另存为路径 325 */ 326 public void save(String savePath) { 327 Dispatch.call( 328 (Dispatch) Dispatch.call(word, "WordBasic").getDispatch(), 329 "FileSaveAs", savePath); 330 } 331 332 /** */ 333 /** 334 * 关闭当前word文档 335 * 336 */ 337 public void closeDocument() { 338 if (doc != null) { 339 Dispatch.call(doc, "Save"); 340 Dispatch.call(doc, "Close", new Variant(saveOnExit)); 341 doc = null; 342 } 343 } 344 345 /** */ 346 /** 347 * 关闭全部应用 348 * 349 */ 350 public void close() { 351 closeDocument(); 352 if (word != null) { 353 Dispatch.call(word, "Quit"); 354 word = null; 355 } 356 selection = null; 357 documents = null; 358 } 359 360 /** */ 361 /** 362 * 打印当前word文档 363 * 364 */ 365 public void printFile() { 366 if (doc != null) { 367 Dispatch.call(doc, "PrintOut"); 368 } 369 } 370 371 } 定义自己的存储结构:Word.java,Table.java
调用函数即可存入类中: 1 //生成一个WordManager对象,并且设置显示Word程序 2 WordManager wm=new WordManager(false); 3 //打开文件 4 wm.openDocument(path); 5 //创建word对象 6 Word word=new Word(); 7 word.setFilePath(path); 8 word.setClassName("WordJet"); 9 //创建表格列表 10 List<Table> tables=new ArrayList<Table>(); 11 //读取所有书签 12 List<String> labels=new ArrayList<String>(); 13 int labelCount=wm.getLabelCount(); 14 System.out.println(labelCount); 15 for(int i=1;i<=labelCount;i++){ 16 String labelName=wm.getLabelName(i); 17 //判断是否标题 18 if(labelName.equals("fileTitle")){ 19 word.setFileName(wm.getLabelValue(labelName)); 20 continue; 21 } 22 //判断是否表格 23 if(labelName.startsWith("table_")){ 24 int tableIndex=Integer.parseInt(labelName.substring(labelName.indexOf('F')+1)); 25 int rowIndex=Integer.parseInt(labelName.substring(labelName.indexOf('R')+1, labelName.indexOf('F'))); 26 Table table=new Table(); 27 table.setTableIndex(tableIndex); 28 table.setRowIndex(rowIndex); 29 table.setTableName(labelName); 30 table.setTypeName(labelName.substring(0, 1).toUpperCase()+labelName.substring(1)+"Jet"); 31 int rowColumnCount=wm.getRowColumnCount(tableIndex, rowIndex); 32 List<String> columns=new ArrayList<String>(); 33 for(int j=1;j<=rowColumnCount;j++){ 34 // columns.add(wm.getCellValue(tableIndex, rowIndex, j)); 35 columns.add("column"+j); 36 } 37 table.setTableColumn(columns); 38 tables.add(table); 39 continue; 40 } 41 labels.add(labelName); 42 } 43 //存储所有表格和书签 44 word.setLabel(labels); 45 word.setTable(tables); 46 //关闭程序和文件 47 wm.close(); 48 wm.closeDocument(); 根据以上存储即可通过JaxbTool生成XML文件,在通过创建JET模版即可生成对文档直接操作的java文件(如果不需要生成模版可省略这两步,直接调用WordManager类即可完成读写): 1 <%@ jet class="SeamActivity" imports="java.util.* word.model.*" package="template.one" %> 2 <% 3 Word word=(Word)argument; 4 String fileName=word.getFileName(); 5 String filePath=word.getFilePath(); 6 String className=word.getClassName(); 7 List<Table> tables=word.getTable(); 8 List<String> labels =word.getLabel(); 9 %> 10 package word.jet; 11 12 import java.util.ArrayList; 13 import java.util.List; 14 import word.model.*; 15 16 public class <%=className%> { 17 <%for(String label:labels){ 18 String getsetStr=label.substring(0,1).toUpperCase()+label.substring(1); 19 %> 20 private String <%=label%>; 21 22 public String get<%=getsetStr%>() { 23 return <%=label%>; 24 } 25 public void set<%=getsetStr%>(String <%=label%>) { 26 this.<%=label%> = <%=label%>; 27 } 28 <%}%> 29 30 <%for(Table table:tables){ 31 String typeName=table.getTypeName(); 32 String tableName=table.getTableName(); 33 String getsetStr=tableName.substring(0,1).toUpperCase()+tableName.substring(1); 34 %> 35 36 private List<<%=typeName%>> <%=tableName%> = new ArrayList<<%=typeName%>>(); 37 38 public List<<%=typeName%>> get<%=getsetStr%>() { 39 return <%=tableName%>; 40 } 41 42 public void set<%=getsetStr%>(List<<%=typeName%>> <%=tableName%>) { 43 this.<%=tableName%> =<%=tableName%>; 44 } 45 <%}%> 46 private String path; 47 48 public <%=className%>(String path) { 49 this.path = path; 50 } 51 52 public void getDataFromeFile() { 53 54 WordManager wm = new WordManager(false); 55 56 wm.openDocument(path); 57 58 <%for(String label:labels){ 59 String getsetStr=label.substring(0,1).toUpperCase()+label.substring(1); 60 %> 61 set<%=getsetStr%>(wm.getLabelValue("<%=label%>")); 62 <%}%> 63 64 <%for(Table table:tables){ 65 String typeName=table.getTypeName(); 66 String tableName=table.getTableName(); 67 String getsetStr=tableName.substring(0,1).toUpperCase()+tableName.substring(1); 68 List<String> columns =table.getTableColumn(); 69 %> 70 int rowIndex = Integer.parseInt("<%=tableName%>".substring("<%=tableName%>" 71 .indexOf('R') + 1,"<%=tableName%>".indexOf('F'))); 72 int tableIndex = Integer.parseInt("<%=tableName%>".substring("<%=tableName%>" 73 .indexOf('F') + 1)); 74 int tableRowCount = wm.getRowCount(tableIndex); 75 for (int i = rowIndex; i <= tableRowCount; i++) { 76 <%=typeName%> tableJet = new <%=typeName%>(); 77 <%for(String column:columns){ 78 String getsetStrs=column.substring(0,1).toUpperCase()+column.substring(1); 79 int num=Integer.parseInt(column.substring(6)); 80 %> 81 tableJet.set<%=getsetStrs%>(wm.getCellValue(tableIndex, i, <%=num%>)); 82 <%}%> 83 get<%=getsetStr%>().add(tableJet); 84 } 85 <%}%> 86 wm.close(); 87 wm.closeDocument(); 88 } 89 90 public void setDataToFile(){ 91 92 WordManager wm = new WordManager(false); 93 94 wm.openDocument(path); 95 96 <%for(String label:labels){ 97 String getsetStr=label.substring(0,1).toUpperCase()+label.substring(1); 98 %> 99 wm.setLabelValue("<%=label%>",get<%=getsetStr%>()); 100 <%}%> 101 <%for(Table table:tables){ 102 String typeName=table.getTypeName(); 103 String tableName=table.getTableName(); 104 List<String> columns =table.getTableColumn(); 105 %> 106 int rowIndex = Integer.parseInt("<%=tableName%>".substring("<%=tableName%>" 107 .indexOf('R') + 1,"<%=tableName%>".indexOf('F'))); 108 int tableIndex = Integer.parseInt("<%=tableName%>".substring("<%=tableName%>" 109 .indexOf('F') + 1)); 110 int tableRowCount = wm.getRowCount(tableIndex); 111 int rowCount = tableRowCount - rowIndex; 112 for (int i = 1; i <= rowCount; i++) { 113 <%for(String column:columns){ 114 String getsetStr=column.substring(0,1).toUpperCase()+column.substring(1); 115 int num=Integer.parseInt(column.substring(6)); 116 %> 117 wm.setCellValue(tableIndex, rowIndex + i, <%=num%>, <%=tableName%>.get(i) 118 .get<%=getsetStr%>()); 119 <%}%> 120 } 121 for (int i = rowCount + 1; i <= <%=tableName%>.size() - 1; i++) { 122 wm.addRow(tableIndex); 123 <%for(String column:columns){ 124 String getsetStr=column.substring(0,1).toUpperCase()+column.substring(1); 125 int num=Integer.parseInt(column.substring(6)); 126 %> 127 wm.setCellValue(tableIndex, rowIndex + i, <%=num%>, <%=tableName%>.get(i) 128 .get<%=getsetStr%>()); 129 <%}%> 130 } 131 <%}%> 132 wm.close(); 133 wm.closeDocument(); 134 } 135 public static void main(String[] args) { 136 <%=className%> wordJet = new WordJet("<%=filePath%>"); 137 wordJet.getDataFromeFile(); 138 <%for(String label:labels){ 139 String getsetStr=label.substring(0,1).toUpperCase()+label.substring(1); 140 %> 141 System.out.println("<%=label%> "+wordJet.get<%=getsetStr%>()); 142 <%}%> 143 144 <%for(Table table:tables){ 145 String typeName=table.getTypeName(); 146 String tableName=table.getTableName(); 147 String getsetStr=tableName.substring(0,1).toUpperCase()+tableName.substring(1); 148 %> 149 for(<%=typeName%> tJet:wordJet.get<%=getsetStr%>()){ 150 System.out.println(tJet.toString()); 151 } 152 <%}%> 153 154 wordJet.setDataToFile(); 155 } 156 157 } |
|
来自: 三十的狼 > 《java操作word》