1. 程式人生 > >java操作word文件(jacob,poi)

java操作word文件(jacob,poi)

專案需要,使用者從系統裡面下載word文件,該文件進行了填寫限制和加密,使用者只能在固定位置填寫內容。現要求系統驗證上傳的附件是否從系統上下載下來的。
思路:系統上面的文件都加入一個固定書籤,使用者上傳文件的時候,檢驗文件裡是否包含這個書籤。
採用jacob操作word文件

JACOB(java -com bridge)是一個 JAVA到微軟的COM介面的橋樑。使用JACOB允許任何JVM訪問COM物件,從而使JAVA應用程式能夠呼叫COM物件。
下載地址:http://sourceforge.net/projects/jacob-project/

其中jacob-1.16.1-x64.dll 是用於64位機器上的,jacob-1.16.1-x86.dll用於32位的。
該dll放於 C:\Windows\system32 目錄下。jacob.jar放於應用lib底下
測試程式碼
Java程式碼 收藏程式碼
ActiveXComponent word = null;
try {
word = new ActiveXComponent(“Word.Application”);
System.out.println(“jacob當前版本:”+word.getBuildVersion());
}catch(Exception e ){
e.printStackTrace();
}
下面再貼出網上常見的程式碼+自己整理的幾個方法(模糊查詢書籤等)
注意插入書籤+書籤值的方法,要先插入書籤值再選中書籤值,之後插入書籤。這樣根據書籤名才能取得書籤值。否則根據網路上很多方法,都取不到書籤值或者取到空。因為書籤值可以是一個點也可以是一大段內容。
Java程式碼 收藏程式碼
import java.io.File;
import java.util.HashMap;
import java.util.Map;

import com.gdcn.bpaf.common.helper.StringHelper;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* *
*

Description: {jacob操作word類}


*
*

Copyright: Copyright (c) 2011


*
*

CreateDate: 2012-6-28


*
* @author Beny
* @version 1.0
*/

public class JacobHelper {
// word文件
private Dispatch doc;

// word執行程式物件  
private ActiveXComponent word;  

// 所有word文件集合  
private Dispatch documents;  

// 選定的範圍或插入點  
private Dispatch selection;  

private boolean saveOnExit = true;  

public JacobHelper(boolean visible) throws Exception {  
    ComThread.InitSTA();//執行緒啟動  
    if (word == null) {  
        word = new ActiveXComponent("Word.Application");  
        word.setProperty("Visible", new Variant(visible)); // 不可見開啟word  
        word.setProperty("AutomationSecurity", new Variant(3)); // 禁用巨集  
    }  
    if (documents == null)  
        documents = word.getProperty("Documents").toDispatch();  
}  

/** 
 * 設定退出時引數 
 *  
 * @param saveOnExit 
 *            boolean true-退出時儲存檔案,false-退出時不儲存檔案 
 */  
public void setSaveOnExit(boolean saveOnExit) {  
    this.saveOnExit = saveOnExit;  
}  

/** 
 * 建立一個新的word文件 
 *  
 */  
public void createNewDocument() {  
    doc = Dispatch.call(documents, "Add").toDispatch();  
    selection = Dispatch.get(word, "Selection").toDispatch();  
}  

/** 
 * 開啟一個已存在的文件 
 *  
 * @param docPath 
 */  
public void openDocument(String docPath) {  

// closeDocument();
doc = Dispatch.call(documents, “Open”, docPath).toDispatch();
selection = Dispatch.get(word, “Selection”).toDispatch();
}

/** 
 * 只讀方式開啟一個加密的文件 
 *  
 * @param docPath-檔案全名 
 * @param pwd-密碼 
 */  
public void openDocumentOnlyRead(String docPath, String pwd)  
        throws Exception {  

// closeDocument();
doc = Dispatch.callN(
documents,
“Open”,
new Object[] { docPath, new Variant(false), new Variant(true),
new Variant(true), pwd, “”, new Variant(false) })
.toDispatch();
selection = Dispatch.get(word, “Selection”).toDispatch();
}
/**
* 開啟一個加密的文件
* @param docPath
* @param pwd
* @throws Exception
*/
public void openDocument(String docPath, String pwd) throws Exception {
// closeDocument();
doc = Dispatch.callN(
documents,
“Open”,
new Object[] { docPath, new Variant(false), new Variant(false),
new Variant(true), pwd }).toDispatch();
selection = Dispatch.get(word, “Selection”).toDispatch();
}

/** 
 * 從選定內容或插入點開始查詢文字 
 *  
 * @param toFindText 
 *            要查詢的文字 
 * @return boolean true-查詢到並選中該文字,false-未查詢到文字 
 */  
@SuppressWarnings("static-access")  
public boolean find(String toFindText) {  
    if (toFindText == null || toFindText.equals(""))  
        return false;  
    // 從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", "false");  
    // 查詢並選中  
    return Dispatch.call(find, "Execute").getBoolean();  
}  

/** 
 * 把選定選定內容設定為替換文字 
 *  
 * @param toFindText 
 *            查詢字串 
 * @param newText 
 *            要替換的內容 
 * @return 
 */  
public boolean replaceText(String toFindText, String newText) {  
    if (!find(toFindText))  
        return false;  
    Dispatch.put(selection, "Text", newText);  
    return true;  
}  

/** 
 * 全域性替換文字 
 *  
 * @param toFindText 
 *            查詢字串 
 * @param newText 
 *            要替換的內容 
 */  
public void replaceAllText(String toFindText, String newText) {  
    while (find(toFindText)) {  
        Dispatch.put(selection, "Text", newText);  
        Dispatch.call(selection, "MoveRight");  
    }  
}  

/** 
 * 在當前插入點插入字串 
 *  
 * @param newText 
 *            要插入的新字串 
 */  
public void insertText(String newText) {  
    Dispatch.put(selection, "Text", newText);  
}  



/** 
 * 設定當前選定內容的字型 
 *  
 * @param boldSize 
 * @param italicSize 
 * @param underLineSize 
 *            下劃線 
 * @param colorSize 
 *            字型顏色 
 * @param size 
 *            字型大小 
 * @param name 
 *            字型名稱 
 * @param hidden 
 *            是否隱藏 
 */  
public void setFont(boolean bold, boolean italic, boolean underLine,  
        String colorSize, String size, String name,boolean hidden) {  
    Dispatch font = Dispatch.get(selection, "Font").toDispatch();  
    Dispatch.put(font, "Name", new Variant(name));  
    Dispatch.put(font, "Bold", new Variant(bold));  
    Dispatch.put(font, "Italic", new Variant(italic));  
    Dispatch.put(font, "Underline", new Variant(underLine));  
    Dispatch.put(font, "Color", colorSize);  
    Dispatch.put(font, "Size", size);  
    Dispatch.put(font, "Hidden", hidden);  
}  


/** 
 * 檔案儲存或另存為 
 *  
 * @param savePath 
 *            儲存或另存為路徑 
 */  
public void save(String savePath) {  
    Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(),  
            "FileSaveAs", savePath);  
}  

/** 
 * 檔案儲存為html格式 
 *  
 * @param savePath 
 * @param htmlPath 
 */  
public void saveAsHtml(String htmlPath) {  
    Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {  
            htmlPath, new Variant(8) }, new int[1]);  
}  

/** 
 * 關閉文件 
 *  
 * @param val 
 *            0不儲存修改 -1 儲存修改 -2 提示是否儲存修改 
 */  
public void closeDocument(int val) {  
    Dispatch.call(doc, "Close", new Variant(val));//注 是documents而不是doc  
    documents = null;  
    doc = null;  
}  

/** 
 * 關閉當前word文件 
 *  
 */  
public void closeDocument() {  
    if (documents != null) {  
        Dispatch.call(documents, "Save");  
        Dispatch.call(documents, "Close", new Variant(saveOnExit));  
        documents = null;  
        doc = null;  
    }  
}  

public void closeDocumentWithoutSave() {  
    if (documents != null) {  
        Dispatch.call(documents, "Close", new Variant(false));  
        documents = null;  
        doc = null;  
    }  
}  

/** 
 * 儲存並關閉全部應用 
 *  
 */  
public void close() {  
    closeDocument(-1);  
    if (word != null) {  

// Dispatch.call(word, “Quit”);
word.invoke(“Quit”, new Variant[] {});
word = null;
}
selection = null;
documents = null;
ComThread.Release();//釋放com執行緒。根據jacob的幫助文件,com的執行緒回收不由java的垃圾回收器處理

}  
/** 
 * 列印當前word文件 
 *  
 */  
public void printFile() {  
    if (doc != null) {  
        Dispatch.call(doc, "PrintOut");  
    }  
}  

/** 
 * 保護當前檔,如果不存在, 使用expression.Protect(Type, NoReset, Password) 
 *  
 * @param pwd 
 * @param type 
 *            WdProtectionType 常量之一(int 型別,只讀): 
 *            1-wdAllowOnlyComments  僅批註 
 *            2-wdAllowOnlyFormFields 僅填寫窗體 
 *            0-wdAllowOnlyRevisions 僅修訂 
 *            -1-wdNoProtection 無保護,  
 *            3-wdAllowOnlyReading 只讀 
 *  
 */  
public void protectedWord(String pwd,String type) {  
    String protectionType = Dispatch.get(doc, "ProtectionType").toString();  
    if (protectionType.equals("-1")) {  
        Dispatch.call(doc, "Protect", Integer.parseInt(type), new Variant(true),pwd);  
    }  
}  

/** 
 * 解除文件保護,如果存在 
 *  
 * @param pwd 
 *            WdProtectionType 常量之一(int 型別,只讀): 
 *            1-wdAllowOnlyComments  僅批註 
 *            2-wdAllowOnlyFormFields 僅填寫窗體 
 *            0-wdAllowOnlyRevisions 僅修訂 
 *            -1-wdNoProtection 無保護,  
 *            3-wdAllowOnlyReading 只讀 
 *  
 */  
public void unProtectedWord(String pwd) {  
    String protectionType = Dispatch.get(doc, "ProtectionType").toString();  
    if (!protectionType.equals("0")&&!protectionType.equals("-1")) {  
        Dispatch.call(doc, "Unprotect", pwd);  
    }  
}  
/** 
 * 返回文件的保護型別 
 * @return 
 */  
public String getProtectedType(){  
    return Dispatch.get(doc, "ProtectionType").toString();  
}  

/** 
 * 設定word文件安全級別 
 *  
 * @param value 
 *            1-msoAutomationSecurityByUI 使用“安全”對話方塊指定的安全設定。 
 *            2-msoAutomationSecurityForceDisable 
 *            在程式開啟的所有檔案中禁用所有巨集,而不顯示任何安全提醒。 3-msoAutomationSecurityLow 
 *            啟用所有巨集,這是啟動應用程式時的預設值。 
 */  
public void setAutomationSecurity(int value) {  
    word.setProperty("AutomationSecurity", new Variant(value));  
}  




/** 
 * 在word中插入標籤 labelName是標籤名,labelValue是標籤值 
 * @param labelName 
 * @param labelValue 
 */  
public  void insertLabelValue(String labelName,String labelValue) {  

   Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
   boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
    if (isExist == true) {  
        Dispatch rangeItem1 = Dispatch.call(bookMarks, "Item", labelName).toDispatch();  
        Dispatch range1 = Dispatch.call(rangeItem1, "Range").toDispatch();  
        String bookMark1Value = Dispatch.get(range1, "Text").toString();  
        System.out.println("書籤內容:"+bookMark1Value);  
    } else {  
        System.out.println("當前書籤不存在,重新建立!");  
        //TODO 先插入文字,再查詢選中文字,再插入標籤  
        this.insertText(labelValue);  

// this.find(labelValue);//查詢文字,並選中
this.setFont(true, true,true,”102,92,38”, “20”, “”,true);
Dispatch.call(bookMarks, “Add”, labelName, selection);
Dispatch.call(bookMarks, “Hidden”, labelName);
}
}
/**
* 在word中插入標籤 labelName是標籤名
* @param labelName
*/
public void insertLabel(String labelName) {

   Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
   boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
    if (isExist == true) {  
        System.out.println("書籤已存在");  
    } else {  
        System.out.println("建立書籤:"+labelName);  
        Dispatch.call(bookMarks, "Add", labelName, selection);  
    }  
}     
/** 
 * 查詢書籤 
 * @param labelName 
 * @return 
 */  
public boolean findLabel(String labelName) {  
   Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
   boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
   if (isExist == true) {  
        return true;  
    } else {  
        System.out.println("當前書籤不存在!");  
        return false;  
    }  
}  
/** 
 * 模糊查詢書籤,並返回準確的書籤名稱 
 * @param labelName 
 * @return 
 */  
public String findLabelLike(String labelName) {  
   Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
   int count = Dispatch.get(bookMarks, "Count").getInt(); // 書籤數  
   Dispatch rangeItem = null;  
   String lname = "";  
   for(int i=1;i<=count;i++){  
       rangeItem = Dispatch.call(bookMarks, "Item", new Variant(i)).toDispatch();  
       lname = Dispatch.call(rangeItem, "Name").toString();//書籤名稱  
       if(lname.startsWith(labelName)){//前面匹配  

// return lname.replaceFirst(labelName, “”);//返回後面值
return lname;
}
}
return “”;
}
/**
* 模糊刪除書籤
* @param labelName
*/
public void deleteLableLike(String labelName){
Dispatch bookMarks = Dispatch.call(doc, “Bookmarks”).toDispatch();
int count = Dispatch.get(bookMarks, “Count”).getInt(); // 書籤數
Dispatch rangeItem = null;
String lname = “”;
for(int i=1;i<=count;i++){
rangeItem = Dispatch.call(bookMarks, “Item”, new Variant(i)).toDispatch();
lname = Dispatch.call(rangeItem, “Name”).toString();//書籤名稱
if(lname.startsWith(labelName)){//前面匹配
Dispatch.call(rangeItem, “Delete”);
count–;//書籤已被刪除,書籤數目和當前書籤都要相應減1,否則會報錯:集合找不到
i–;
}
}
}
/**
* 獲取書籤內容
* @param labelName
* @return
*/
public String getLableValue(String labelName){
if(this.findLabel(labelName)){
Dispatch bookMarks = Dispatch.call(doc, “Bookmarks”).toDispatch();
Dispatch rangeItem1 = Dispatch.call(bookMarks, “Item”, labelName).toDispatch();
Dispatch range1 = Dispatch.call(rangeItem1, “Range”).toDispatch();
Dispatch font = Dispatch.get(range1, “Font”).toDispatch();
Dispatch.put(font, “Hidden”, new Variant(false)); //顯示書籤內容
String bookMark1Value = Dispatch.get(range1, “Text”).toString();
System.out.println(“書籤內容:”+bookMark1Value);
// font = Dispatch.get(range1, “Font”).toDispatch();
// Dispatch.put(font, “Hidden”, new Variant(true)); //隱藏書籤內容
return bookMark1Value;
}
return “”;
}

public static void main(String[] args) throws Exception {  

}     

}
採用jacob方式操作文件,經常會出現卡機的現象,所以最後採用poi方式來操作書籤。若單純的操作書籤用poi方式還是比較簡單的,但要操作表格、文件格式之類的還是用jacob功能比較強大。
Java程式碼 收藏程式碼
InputStream input = null;
File docFile = new File( fileName );
HWPFDocument document = null;
try{
input = new FileInputStream(docFile);//載入 doc 文件
document = new HWPFDocument(input);//檔案流方式建立hwpf
Bookmarks bookmarks = document.getBookmarks();//文件書籤
for(int i=0,length=bookmarks.getBookmarksCount();i