轉自:http://www.blogjava.net/lonsy/archive/2009/01/09/250713.htmlhtml
Jacob項目的官方地址: Http://sourceforge.net/projects/jacob-project/
官方介紹:
JACOB is a JAVA-COM Bridge that allows you to call COM Automation components from Java. It uses JNI to make native calls to the COM libraries. JACOB runs on x86 and x64 environments supporting 32 bit and 64 bit JVMs
它是一個使用jni來調用com組件及其庫文件的工具。這裏僅介紹處理word文檔。
首先要部署其dll文件。jacob-1.14.3-x86.dll 或 jacob-1.14.3-x64.dll,下載的文件解壓後便可看到。我是直接將dll文件放在windows\system32目錄下的,方便,固然也有其餘作法。
其次,就是把其jar文件路徑加入Windows路徑中。
接着就能夠在你的Java程序中調用了。我總結下大概有下面幾個階段:
1. 初始化相關參數,代碼以下:java
// 打開Word應用程序
ActiveXComponent app = new ActiveXComponent("Word.Application");
// 設置word不可見
app.setProperty("Visible", new Variant(false));
// 打開word文件
Dispatch word = app.getProperty("Documents").toDispatch();
Dispatch doc = Dispatch.invoke(word, "Open", Dispatch.Method, new Object[] {"File Name", new Variant(false), new Variant(false) }, new int[1]).toDispatch();
//獲取指針
Dispatch cursor = app.getProperty("Selection").toDispatch();
如上,咱們打開了一個名爲File Name的word文件,你可能會以爲最後那句看起來很繁瑣,是的,有更好的代替方式,以下:windows
Dispatch doc = Dispatch.call(word, "Open", new Variant(false), new Variant(false)).toDisptach();
這正是Jacob給咱們提供的兩種調用方式。
2. 處理word文檔,若是你先前有VBA相關開發經驗,那就簡單了。沒有的也沒事,打開office程序目錄下的2052\VBAWD10.chm,這裏有Word的對象模型的全部記錄。
接着講述下Jacob中兩種最經常使用的類型:
Variant:這是一種可變的類型,用於Jacob中幾乎全部函數的返回值,並可轉換爲其餘任何類型,包括Java基本類型。固然,應該按須要與規則來。
Dispatch:Object represents MS level dispatch object. Each instance of this points at some data structure on the MS windows side.就是說能夠表明全部對象模型。
有所瞭解後咱們來看對模型的處理方式。
當咱們得到一個模型後,如前面打開的doc文檔,均已轉換成一個Dispatch對象。只有轉換後才能讀取、設置其屬性,或者調用其方法,以下:
app
//獲取其屬性,表格的集合
Dispatch tables = Dispatch.get(doc, "Tables").toDispatch();
//調用方法取得其中的第一張表格
Dispatch table = Dispatch.call(this.tables, "Item", new Variant(0)).toDispatch();
//修改此表格第一行第一列的單元格
Dispatch cell = Dispatch.call(table,"Cell", Integer.toString(1), Integer.toString(1)).toDispatch();
Dispatch.call(cell, "Select");
Dispatch.put(cursor, "Text", "New String");
這就是簡單的處理,更多的仍是多瞭解瞭解對象模型吧
3. 關閉文檔及進程
ide
//關閉文檔且不保存
Dispatch.call(doc, "Close", new Variant(false));
//退出進程對象
app.invoke("Quit", new Variant[] {});
更多請參看下載文件中的API幫助文檔..
下面是我寫的類,用於封裝其功能。(注意,這個類並無涉及多個word文檔線程的處理)函數
import com.jacob.com.*; import com.jacob.activeX.*; /** * * @author Lonsy */ public class WordHandle { //運行時的Word程序 private ActiveXComponent app; //word對象 private Dispatch words; //當前的word文檔 private Dispatch doc; //當前光標位置 private Dispatch cursor; //當前文檔是否只讀 private boolean readOnly; //當前文檔中全部表格 private Dispatch tables; //當前所在表格 private Dispatch table; private int count; public WordHandle() { this.app = new ActiveXComponent("Word.Application"); this.app.setProperty("Visible", new Variant(false)); // 設置word不可見 words = this.app.getProperty("Documents").toDispatch(); this.doc = null; this.cursor = null; this.readOnly = true; this.count = 0; } /** * 打開word文件 * @param fileName 文件名,使用絕對路徑 * @param readOnly 是否只讀 * @return * @throws java.lang.Exception */ public boolean open(String fileName, boolean readOnly) throws Exception { if (doc != null) { System.out.println("當前文件未關閉"); return false; } this.doc = Dispatch.invoke(this.words, "Open", Dispatch.Method, new Object[] {fileName, new Variant(false), new Variant(readOnly)}, new int[1]).toDispatch(); this.cursor = app.getProperty("Selection").toDispatch(); this.tables = Dispatch.get(this.doc,"Tables").toDispatch(); this.readOnly = readOnly; this.count = Dispatch.get(Dispatch.get(this.doc, "Words").toDispatch(), "Count").getInt() - 1; System.out.println("打開文件" + fileName + (readOnly ? " ReadOnly" : " Writable")); return true; } /** * 創建新的Word文件 * @return * @throws java.lang.Exception */ public boolean newFile() throws Exception { if (doc != null) { System.out.println("當前文件未關閉"); return false; } this.doc = Dispatch.call(this.words, "Add").toDispatch(); this.readOnly = false; this.cursor = app.getProperty("Selection").toDispatch(); this.tables = Dispatch.get(this.doc,"Tables").toDispatch(); System.out.println("新建word文檔"); return true; } /** * 關閉當前文件,並不保存 * @return */ public boolean close() { String fileName = null; if (this.doc != null) { try { fileName = Dispatch.get(this.doc, "Name").getString(); Dispatch.call(this.doc, "Close", new Variant(false)); } catch (Exception e) { e.printStackTrace(); } finally { this.doc = null; } } System.out.println("關閉文件 " + fileName); return true; } /** * 退出 * @return */ public boolean quit() { try { this.app.invoke("Quit", new Variant[] {}); } catch (Exception e) { e.printStackTrace(); } System.out.println("退出word"); return true; } /** * 另存爲 * @param fileName 目標文件名,爲絕對路徑 * @return */ public boolean saveAs(String fileName) throws Exception { if (this.doc == null) { System.out.println("當前無文件"); return false; } else { Dispatch.call(this.doc, "SaveAs", fileName); System.out.println("另存爲" + fileName); return true; } } /** * 保存 * @return */ public boolean save() throws Exception { if (this.doc == null) { System.out.println("當前無文檔,沒法保存"); return false; } else { if (this.readOnly) { System.out.println("只讀文檔,保存失敗"); return false; } Dispatch.call(this.doc, "Save"); System.out.println("保存完成"); return true; } } /** * 將光標或選定內容向右移動 * @param step * @return */ public boolean moveRight(int steps) throws Exception { //int start = Dispatch.get(this.cursor, "Start").getInt(); //Dispatch.put(this.cursor, "Start", start + steps); for (int i=0; i<steps; i++) { Dispatch.call(cursor, "MoveRight"); } return true; } /** * 將光標或選定內容向左移動 * @param step * @return */ public boolean moveLeft(int steps) throws Exception { for (int i=0; i<steps; i++) { Dispatch.call(cursor, "MoveLeft"); } return true; } /** * 從當前位置起查找指定內容,並將光標移到相應位置上 * @param str * @return 光標位置,未找到則爲0 * @throws java.lang.Exception */ public int search(String str) throws Exception { // 從cursor所在位置開始查詢 Dispatch find = Dispatch.call(this.cursor, "Find").toDispatch(); // 設置要查找的內容 Dispatch.put(find, "Text", str); // 向前查找 Dispatch.put(find, "Forward", "True"); // 設置格式 Dispatch.put(find, "Format", "True"); // 大小寫匹配 Dispatch.put(find, "MatchCase", "True"); // 全字匹配 Dispatch.put(find, "MatchWholeWord", "True"); // 查找 if (!Dispatch.call(find,"Execute").getBoolean()) return 0; else { return Dispatch.get(this.cursor, "Start").getInt(); } } /** * 從當前位置起查找指定內容,並只將光標開始處移到相應位置上 * @param str * @return 光標位置,未找到則爲0 * @throws java.lang.Exception */ public int searchOnly(String str) throws Exception { // 從cursor所在位置開始查詢 Dispatch find = Dispatch.call(this.cursor, "Find").toDispatch(); // 設置要查找的內容 Dispatch.put(find, "Text", str); // 向前查找 Dispatch.put(find, "Forward", "True"); // 大小寫匹配 Dispatch.put(find, "MatchCase", "True"); // 全字匹配 Dispatch.put(find, "MatchWholeWord", "True"); if (!Dispatch.call(find,"Execute").getBoolean()) return 0; else { int start = Dispatch.get(this.cursor, "Start").getInt(); Dispatch.put(this.cursor, "End", this.count); //System.out.println(start); return start; } } public String getBetween(int start, int end) throws Exception { Dispatch range = Dispatch.get(this.cursor, "Range").toDispatch(); Dispatch.call(range,"SetRange", start, end); return Dispatch.get(range, "Text").getString(); } public String getLineAfter(int start) throws Exception { Dispatch.put(this.cursor, "Start", start); int length = Dispatch.call(this.cursor, "EndKey").getInt() + start; return getBetween(start, length); } public String getLine(int position) throws Exception { Dispatch.put(this.cursor, "Start", position); Dispatch.call(this.cursor, "SelectRow"); int start = Dispatch.get(this.cursor, "Start").getInt(); int end = Dispatch.get(this.cursor, "End").getInt(); return getBetween(start, start + end); } public boolean gotoPage(int index) throws Exception { Dispatch.invoke(this.cursor, "Goto", Dispatch.Method, new Object[] {1, 2, String.valueOf(index)}, new int[1]); //Dispatch.call(this.cursor, "GoTo", "wdGoToLine", "wdGoToNext", String.valueOf(index), null); return true; } public int getCurrentCursor() throws Exception { return Dispatch.get(this.cursor, "Start").getInt(); } public boolean setCursorMode() throws Exception { Dispatch.put(this.cursor, "End", Dispatch.get(this.cursor, "Start").getInt()); return true; } public boolean gotoHome() throws Exception { Dispatch.put(this.cursor, "Start", 0); return true; } /** * 在光標後指定便宜插入字符串,並將光標移到新位置 * @param str * @return * @throws java.lang.Exception */ public boolean insert(int steps, String str) throws Exception { int start = Dispatch.get(this.cursor, "Start").getInt() + steps; Dispatch.put(this.cursor, "Start", start); Dispatch.call(this.cursor, "InsertBefore", str); this.getCount(); Dispatch.put(this.cursor, "Start", start + str.length()); //System.out.println(Dispatch.get(this.cursor, "Start").getInt() + " " + (Dispatch.get(this.cursor, "Start").getInt()+Dispatch.get(this.cursor, "End").getInt())); return true; } /** * 用指定的字符串替代當前選定的內容 * @param str * @return * @throws java.lang.Exception */ public boolean replace(String str) throws Exception { Dispatch.put(this.cursor, "Text", str); return true; } /** * 獲取當前文檔中的表格數 * @return * @throws java.lang.Exception */ public int getTableNum() throws Exception { return Dispatch.get(this.tables, "Count").getInt(); } /** * 設定當前工做表格 * @param index * @return * @throws java.lang.Exception */ public boolean setCurrentTable(int index) throws Exception { this.table = Dispatch.call(this.tables, "Item", new Variant(index)).toDispatch(); Dispatch.call(this.table, "Select"); return true; } /** * 獲取指定單元格的內容 * @param row * @param col * @return * @throws java.lang.Exception */ public String getCell(int row, int col) throws Exception { Dispatch cell = Dispatch.call(table, "Cell", Integer.toString(row), Integer.toString(col)).toDispatch(); Dispatch.call(cell,"Select"); String tmp = Dispatch.get(this.cursor, "Text").getString(); //System.out.println(".." + tmp); if (tmp.length() > 2) { return tmp.substring(0, tmp.length() - 2); } else return ""; } /** * 用指定的字符串代替當前表格中指定的單元格 * @param row * @param col * @param str * @return * @throws java.lang.Exception */ public boolean replaceCell(int row, int col, String str) throws Exception { Dispatch cell = Dispatch.call(table,"Cell", Integer.toString(row), Integer.toString(col)).toDispatch(); Dispatch.call(cell, "Select"); Dispatch.put(this.cursor, "Text", str); return true; } }