Java文件操作系列[3]——使用jacob操作word文檔


Java對word文檔的操作需要通過第三方組件實現,例如jacob、iText、POI和java2word等。
jacob組件的功能最強大,可以操作word,Excel等格式的文件。該組件調用的的是操作系統底層的dll文件。在使用Java操作word文件時,jacob組件是最常用的一個。

1.准備工作

  根據上面的描述,需要兩類文件、一個軟件:

  ①jacob.jar

  ②dll文件

  下載地址1:百度雲盤下載

  下載地址2:官方下載

  ③電腦上有Microsoft Office軟件(WPS、LibreOffice未經試驗)。

2.開始編程

 1 package com.myeclipse;  2 
 3 import com.jacob.activeX.ActiveXComponent;  4 import com.jacob.com.Dispatch;  5 import com.jacob.com.Variant;  6 
 7 /**
 8  * 使用jacob操作word文檔  9  * @author MrChen 10  * 11  */
12 public class JacobOperateDoc{ 13 
14     
15     private ActiveXComponent MSWordApp = null;    //聲明一個word對象
16     private Dispatch document = null; 17 
18 
19     /**
20  * 打開word文檔 21  * @param makeVisible 是否以可讀寫方式打開 22      */
23     public void  openWord( boolean makeVisible) { 24         if( MSWordApp == null ) { 25             MSWordApp = new ActiveXComponent("Word.Application"); 26  } 27         //設置visible
28         Dispatch.put(MSWordApp,"Visible",new Variant(makeVisible)); 29 
30  } 31     
32     /**
33  * 新建word文檔 34      */
35     public void createNewDocument() { 36         //獲取文檔集合
37         Dispatch documents = Dispatch.get(MSWordApp, "Documents").toDispatch(); 38         //調用add方法向文檔集合中添加一個新的Word文件
39         document = Dispatch.call(documents, "Add").toDispatch(); 40  } 41     
42     /**
43  * 向word中寫入字符串 44  * @param text 45      */
46     public void insertText(String txt) { 47         //獲取當前執行寫入的位置,如果是新word文件操作位置為文檔開始
48         Dispatch selection = Dispatch.get(MSWordApp, "Selection").toDispatch(); 49         //將字符串寫入
50         Dispatch.put(selection, "Text", txt); 51  } 52     
53     /**
54  * 另存為 55  * @param fileName 56      */
57     public void saveFileAs(String fileName) { 58         Dispatch.call(document, "SaveAs",fileName); 59  } 60     
61     /**
62  * 打印 63      */
64     public void printFile() { 65         //采用默認打印機打印
66         Dispatch.call(document, "PrintOut"); 67  } 68     
69     /**
70  * 關閉文檔 71  * @param type 72  * 0: 關閉文檔不改變保存信息 73  * -1: 關閉文檔改變保存信息 74  * -2: 關閉文檔提示是否保存改變信息,請求確認 75      */
76     public void closeDocument(Integer type) { 77         //如果關閉類型不正確,則默認為
78         if((type!=0 && type!=-1 && type != -2) || type == null){ 79             type = -2; 80  } 81         Dispatch.call(document, "Close", new Variant(type)); 82         document = null; 83  } 84     
85     /**
86  * 退出 87      */
88     public void closeWord() { 89         Dispatch.call(MSWordApp, "Quit"); 90         MSWordApp = null; 91         document = null; 92  } 93 }
JacobOperateDoc
 1 package com.myeclipse;  2 
 3 /**
 4  * 測試JacobOperateDoc類  5  * @author MrChen  6  *  7  */
 8 public class Test {  9 
10     /**
11  * @param args 12      */
13     public static void main(String[] args) { 14         System.out.println("start!"); 15         System.out.println(System.getProperty("java.library.path")); 16         JacobOperateDoc jac = new JacobOperateDoc(); 17         jac.openWord(true); 18  jac.createNewDocument(); 19         jac.insertText("helloworld!"); 20         jac.saveFileAs("D:\\hell.doc"); 21         try{ 22             jac.closeDocument(null); 23         }catch(NullPointerException e){ 24             //捕捉空指針異常,什么也不做
25  } 26  jac.closeWord(); 27         System.out.println("end!"); 28  } 29 
30 }
測試JacobOperateDoc類

3.遇見的問題及解決方案

  在研究jacob的過程中遇到了一些問題,導致筆者一度想放棄,但這種想法不過一秒而已。筆者一直堅持這樣的觀點:一件正確的事,既然開始了,就堅持到底,決不放棄!下面是對其中一些問題的摘錄。

  (1) 執行Test類,報錯Unsupported major.minor version 51.0

必要的資料:各JDK版本對應的錯誤編號如下:
  J2SE 8 = 52,
  J2SE 7 = 51,
  J2SE 6.0 = 50,
  J2SE 5.0 = 49,
  JDK 1.4 = 48,
  JDK 1.3 = 47,
  JDK 1.2 = 46,
  JDK 1.1 = 45。

    原因:通過搜尋到的JDK版本對應錯誤資料,可以得出結論:外部jar包使用jdk1.7(jdk7)編譯,而使用此jar包的工程jdk版本為jdk1.6(jdk6),故版本不支持。

    解決目標:項目使用的JRE System Library和外用JDK版本保持一致。即修改后是這樣的:

      

    解決步驟

      第一大步:修改JDK版本(注:這里本來是一個鏈接,但博客園非說這個鏈接有違禁內容,連直接把鏈接地址粘貼到這里里都不行......故啰嗦下怎么進行)

        ①修改Eclipse/Myeclipse JDK版本:Window ----> Preference ----> Java ----> Installed JREs。選擇相應的JDK版本。

          

        ②修改項目的JDK編譯版本:項目右鍵 ----> Java Compiler ----> Enable project specific settings。

          

        ③Window ----> Preference ----> Myeclipse ----> Servers ----> Resin ----> Resin3.x ----> JDK

          

      第二大步:修改JRE system library (點擊查看參考文章)

      注:這兩大步必不可少。

  (2) 解決完以上錯誤之后,執行Test類,出現異常Exception in thread "main" java.lang.UnsatisfiedLinkError: no jacob-1.18-x64 in java.library.path

    錯誤原因:path路徑下找不到jacob-1.18-x64.dll文件

    解決方案

    ① 找到path路徑。

      在Test類中增加輸出:

System.out.println(System.getProperty("java.library.path")); 

      執行得到:

D:\Java\jdk1.7.0_80\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;D:/Program Files/MyEclipse-8.6/Common/binary/com.sun.java.jdk.win32.x86_1.6.0.013/jre/bin/client;  .......(還有很多,不再列舉)

    ② 將dll文件復制到C:\Windows\system32路徑之下。

    再次執行Test類,成功!

    畫外音:通過輸出path路徑,同時也更清楚地看到,Java程序在運行的時候會從前往后掃描path路徑,故在解決第一個錯誤之前使用的JDK版本是1.6。要是早將dll放在C:\Windows\system32路徑之下,就不會出現這第二個異常了。

4.進一步了解jacob

   (1)jacob是個什么玩意?

     jacob一個Java-COM中間件。通過這個組件我們就可以在Java應用程序中調用COM組件和Win32程序庫。

  (2)為什么我們用java去操縱office(如:word)要使用com,而不直接使用java去做?

    office是建立在windows平台之上的,本身是一個軟件,除了他自己提供的宏似乎沒有什么能對他進行直接的操作。

    在windows平台上為了解決像這樣的不同應用軟件,通信缺乏通用api問題,推出了com的解決方案。

    我們使用dll中的一組或多組相關的函數存取組件數據,總的合稱為接口(對應jacob,就是Dispatch),具體到每個細節的實現稱為方法。

    我們使用jacob就是通過一個接口來操作word的ActiveX對象(實質是調用指向接口的指針,這也是唯一途徑)。

    總結一下,有這么幾點:

      ①Java是與平台無關的語言,不能對平台軟件做個性化的操作。

      ②Windows平台提供了com組件來通信,但是java語言不認識這個com組件,所以我們用jacob來架起java程序與com組件溝通(通信)的橋梁。(注:java與dll交互的技術主要有3種:JNI,jawin和jacob。后兩種都是基於JNI。)

      同時這也說明了為什么本地應用沒有office應用就無法進行的原因:如果沒有office,則無法建立Java-COM橋,進而無法解析。

5.小結

  (1)JDK版本應該保持一致。

  (2)dll文件要放在C:\Windows\system32路徑之下。

  (3)jacob.jar括兩個部分:

    • com.jacob.activeX: ActiveXComponent類
    • com.jacob.com: 其它類和元素

  (4)Jacob類

  Jacob的結構很簡單,包含以下幾個類:

    • ActiveXComponent Class:封裝了Dispatch對象,用於創建一個封裝了COM組件對象的Java Object
    • Dispatch Class:用於指向封裝后的MS數據結構。常用的方法有call,subcall,get,invoke…后面會介紹使用方法。
    • Variant Class:用於映射COM的Variant數據類型。提供Java和COM的數據交換。
    • ComException Class:異常類

  (5)Jacob方法

用於訪問COM/DLL對象的方法,讀取、修改COM/DLL對象的屬性。

    • call method:屬於Dispatch類。用於訪問COM/DLL對象的方法。方法進行了重載,方便不同場合調用。返回一個Variant類型的值。
    • callSub method:使用方法和call一樣,不過它不返回值。
    • get method:讀取COM對象的屬性值,返回一個Variant類型值。
    • put method:設置COM對象的屬性值。
    • invoke method:call的另一種用法,更復雜一些。
    • invokesub method:subcall的另一種用法
    • getProperty method:屬於ActiveXComponent類,讀取屬性值,返回一個Variant類型值。
    • setProperty method:屬於ActiveXComponent類,設置屬性值。

    注:API在下載里面也附帶了(點擊單獨下載API)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM