(转载)java操作word文档(jacob)

时间:2021-09-16 18:51:20

转载自http://wibiline.iteye.com/blog/1725492


项目需要,用户从系统里面下载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代码  (转载)java操作word文档(jacob)
  1. ActiveXComponent    word = null;  
  2. try {  
  3.         word = new ActiveXComponent("Word.Application");  
  4.         System.out.println("jacob当前版本:"+word.getBuildVersion());  
  5. }catch(Exception e ){  
  6.          e.printStackTrace();  
  7. }  

下面再贴出网上常见的代码+自己整理的几个方法(模糊查询书签等)

注意插入书签+书签值的方法,要先插入书签值再选中书签值,之后插入书签。这样根据书签名才能取得书签值。否则根据网络上很多方法,都取不到书签值或者取到空。因为书签值可以是一个点也可以是一大段内容。

Java代码  (转载)java操作word文档(jacob)
  1. import java.io.File;  
  2. import java.util.HashMap;  
  3. import java.util.Map;  
  4.   
  5. import com.gdcn.bpaf.common.helper.StringHelper;  
  6. import com.jacob.activeX.ActiveXComponent;  
  7. import com.jacob.com.ComThread;  
  8. import com.jacob.com.Dispatch;  
  9. import com.jacob.com.Variant;  
  10. /** 
  11.  *  * 
  12.  * <p>Description: {jacob操作word类}    </p> 
  13.  * 
  14.  * <p>Copyright: Copyright (c) 2011</p> 
  15.  *  
  16.  * <p>CreateDate: 2012-6-28</p> 
  17.  * 
  18.  * @author Beny 
  19.  * @version 1.0 
  20.  */  
  21.   
  22. public class JacobHelper {  
  23.     // word文档  
  24.     private Dispatch doc;  
  25.   
  26.     // word运行程序对象  
  27.     private ActiveXComponent word;  
  28.   
  29.     // 所有word文档集合  
  30.     private Dispatch documents;  
  31.   
  32.     // 选定的范围或插入点  
  33.     private Dispatch selection;  
  34.   
  35.     private boolean saveOnExit = true;  
  36.   
  37.     public JacobHelper(boolean visible) throws Exception {  
  38.         ComThread.InitSTA();//线程启动  
  39.         if (word == null) {  
  40.             word = new ActiveXComponent("Word.Application");  
  41.             word.setProperty("Visible"new Variant(visible)); // 不可见打开word  
  42.             word.setProperty("AutomationSecurity"new Variant(3)); // 禁用宏  
  43.         }  
  44.         if (documents == null)  
  45.             documents = word.getProperty("Documents").toDispatch();  
  46.     }  
  47.   
  48.     /** 
  49.      * 设置退出时参数 
  50.      *  
  51.      * @param saveOnExit 
  52.      *            boolean true-退出时保存文件,false-退出时不保存文件 
  53.      */  
  54.     public void setSaveOnExit(boolean saveOnExit) {  
  55.         this.saveOnExit = saveOnExit;  
  56.     }  
  57.   
  58.     /** 
  59.      * 创建一个新的word文档 
  60.      *  
  61.      */  
  62.     public void createNewDocument() {  
  63.         doc = Dispatch.call(documents, "Add").toDispatch();  
  64.         selection = Dispatch.get(word, "Selection").toDispatch();  
  65.     }  
  66.   
  67.     /** 
  68.      * 打开一个已存在的文档 
  69.      *  
  70.      * @param docPath 
  71.      */  
  72.     public void openDocument(String docPath) {  
  73. //      closeDocument();  
  74.         doc = Dispatch.call(documents, "Open", docPath).toDispatch();  
  75.         selection = Dispatch.get(word, "Selection").toDispatch();  
  76.     }  
  77.   
  78.     /** 
  79.      * 只读方式打开一个加密的文档 
  80.      *  
  81.      * @param docPath-文件全名 
  82.      * @param pwd-密码 
  83.      */  
  84.     public void openDocumentOnlyRead(String docPath, String pwd)  
  85.             throws Exception {  
  86. //      closeDocument();  
  87.         doc = Dispatch.callN(  
  88.                 documents,  
  89.                 "Open",  
  90.                 new Object[] { docPath, new Variant(false), new Variant(true),  
  91.                         new Variant(true), pwd, ""new Variant(false) })  
  92.                 .toDispatch();  
  93.         selection = Dispatch.get(word, "Selection").toDispatch();  
  94.     }  
  95.     /** 
  96.      * 打开一个加密的文档 
  97.      * @param docPath 
  98.      * @param pwd 
  99.      * @throws Exception 
  100.      */  
  101.     public void openDocument(String docPath, String pwd) throws Exception {  
  102. //      closeDocument();  
  103.         doc = Dispatch.callN(  
  104.                 documents,  
  105.                 "Open",  
  106.                 new Object[] { docPath, new Variant(false), new Variant(false),  
  107.                         new Variant(true), pwd }).toDispatch();  
  108.         selection = Dispatch.get(word, "Selection").toDispatch();  
  109.     }  
  110.   
  111.     /** 
  112.      * 从选定内容或插入点开始查找文本 
  113.      *  
  114.      * @param toFindText 
  115.      *            要查找的文本 
  116.      * @return boolean true-查找到并选中该文本,false-未查找到文本 
  117.      */  
  118.     @SuppressWarnings("static-access")  
  119.     public boolean find(String toFindText) {  
  120.         if (toFindText == null || toFindText.equals(""))  
  121.             return false;  
  122.         // 从selection所在位置开始查询  
  123.         Dispatch find = word.call(selection, "Find").toDispatch();  
  124.         // 设置要查找的内容  
  125.         Dispatch.put(find, "Text", toFindText);  
  126.         // 向前查找  
  127.         Dispatch.put(find, "Forward""True");  
  128.         // 设置格式  
  129.         Dispatch.put(find, "Format""True");  
  130.         // 大小写匹配  
  131.         Dispatch.put(find, "MatchCase""True");  
  132.         // 全字匹配  
  133.         Dispatch.put(find, "MatchWholeWord""false");  
  134.         // 查找并选中  
  135.         return Dispatch.call(find, "Execute").getBoolean();  
  136.     }  
  137.   
  138.     /** 
  139.      * 把选定选定内容设定为替换文本 
  140.      *  
  141.      * @param toFindText 
  142.      *            查找字符串 
  143.      * @param newText 
  144.      *            要替换的内容 
  145.      * @return 
  146.      */  
  147.     public boolean replaceText(String toFindText, String newText) {  
  148.         if (!find(toFindText))  
  149.             return false;  
  150.         Dispatch.put(selection, "Text", newText);  
  151.         return true;  
  152.     }  
  153.   
  154.     /** 
  155.      * 全局替换文本 
  156.      *  
  157.      * @param toFindText 
  158.      *            查找字符串 
  159.      * @param newText 
  160.      *            要替换的内容 
  161.      */  
  162.     public void replaceAllText(String toFindText, String newText) {  
  163.         while (find(toFindText)) {  
  164.             Dispatch.put(selection, "Text", newText);  
  165.             Dispatch.call(selection, "MoveRight");  
  166.         }  
  167.     }  
  168.   
  169.     /** 
  170.      * 在当前插入点插入字符串 
  171.      *  
  172.      * @param newText 
  173.      *            要插入的新字符串 
  174.      */  
  175.     public void insertText(String newText) {  
  176.         Dispatch.put(selection, "Text", newText);  
  177.     }  
  178.   
  179.   
  180.   
  181.     /** 
  182.      * 设置当前选定内容的字体 
  183.      *  
  184.      * @param boldSize 
  185.      * @param italicSize 
  186.      * @param underLineSize 
  187.      *            下划线 
  188.      * @param colorSize 
  189.      *            字体颜色 
  190.      * @param size 
  191.      *            字体大小 
  192.      * @param name 
  193.      *            字体名称 
  194.      * @param hidden 
  195.      *            是否隐藏 
  196.      */  
  197.     public void setFont(boolean bold, boolean italic, boolean underLine,  
  198.             String colorSize, String size, String name,boolean hidden) {  
  199.         Dispatch font = Dispatch.get(selection, "Font").toDispatch();  
  200.         Dispatch.put(font, "Name"new Variant(name));  
  201.         Dispatch.put(font, "Bold"new Variant(bold));  
  202.         Dispatch.put(font, "Italic"new Variant(italic));  
  203.         Dispatch.put(font, "Underline"new Variant(underLine));  
  204.         Dispatch.put(font, "Color", colorSize);  
  205.         Dispatch.put(font, "Size", size);  
  206.         Dispatch.put(font, "Hidden", hidden);  
  207.     }  
  208.   
  209.   
  210.     /** 
  211.      * 文件保存或另存为 
  212.      *  
  213.      * @param savePath 
  214.      *            保存或另存为路径 
  215.      */  
  216.     public void save(String savePath) {  
  217.         Dispatch.call(Dispatch.call(word, "WordBasic").getDispatch(),  
  218.                 "FileSaveAs", savePath);  
  219.     }  
  220.   
  221.     /** 
  222.      * 文件保存为html格式 
  223.      *  
  224.      * @param savePath 
  225.      * @param htmlPath 
  226.      */  
  227.     public void saveAsHtml(String htmlPath) {  
  228.         Dispatch.invoke(doc, "SaveAs", Dispatch.Method, new Object[] {  
  229.                 htmlPath, new Variant(8) }, new int[1]);  
  230.     }  
  231.   
  232.     /** 
  233.      * 关闭文档 
  234.      *  
  235.      * @param val 
  236.      *            0不保存修改 -1 保存修改 -2 提示是否保存修改 
  237.      */  
  238.     public void closeDocument(int val) {  
  239.         Dispatch.call(doc, "Close"new Variant(val));//注 是documents而不是doc  
  240.         documents = null;  
  241.         doc = null;  
  242.     }  
  243.   
  244.     /** 
  245.      * 关闭当前word文档 
  246.      *  
  247.      */  
  248.     public void closeDocument() {  
  249.         if (documents != null) {  
  250.             Dispatch.call(documents, "Save");  
  251.             Dispatch.call(documents, "Close"new Variant(saveOnExit));  
  252.             documents = null;  
  253.             doc = null;  
  254.         }  
  255.     }  
  256.   
  257.     public void closeDocumentWithoutSave() {  
  258.         if (documents != null) {  
  259.             Dispatch.call(documents, "Close"new Variant(false));  
  260.             documents = null;  
  261.             doc = null;  
  262.         }  
  263.     }  
  264.   
  265.     /** 
  266.      * 保存并关闭全部应用 
  267.      *  
  268.      */  
  269.     public void close() {  
  270.         closeDocument(-1);  
  271.         if (word != null) {  
  272. //          Dispatch.call(word, "Quit");  
  273.             word.invoke("Quit"new Variant[] {});  
  274.             word = null;  
  275.         }  
  276.         selection = null;  
  277.         documents = null;  
  278.         ComThread.Release();//释放com线程。根据jacob的帮助文档,com的线程回收不由java的垃圾回收器处理  
  279.   
  280.     }  
  281.     /** 
  282.      * 打印当前word文档 
  283.      *  
  284.      */  
  285.     public void printFile() {  
  286.         if (doc != null) {  
  287.             Dispatch.call(doc, "PrintOut");  
  288.         }  
  289.     }  
  290.   
  291.     /** 
  292.      * 保护当前档,如果不存在, 使用expression.Protect(Type, NoReset, Password) 
  293.      *  
  294.      * @param pwd 
  295.      * @param type 
  296.      *            WdProtectionType 常量之一(int 类型,只读): 
  297.      *            1-wdAllowOnlyComments  仅批注 
  298.      *            2-wdAllowOnlyFormFields 仅填写窗体 
  299.      *            0-wdAllowOnlyRevisions 仅修订 
  300.      *            -1-wdNoProtection 无保护,  
  301.      *            3-wdAllowOnlyReading 只读 
  302.      *  
  303.      */  
  304.     public void protectedWord(String pwd,String type) {  
  305.         String protectionType = Dispatch.get(doc, "ProtectionType").toString();  
  306.         if (protectionType.equals("-1")) {  
  307.             Dispatch.call(doc, "Protect", Integer.parseInt(type), new Variant(true),pwd);  
  308.         }  
  309.     }  
  310.   
  311.     /** 
  312.      * 解除文档保护,如果存在 
  313.      *  
  314.      * @param pwd 
  315.      *            WdProtectionType 常量之一(int 类型,只读): 
  316.      *            1-wdAllowOnlyComments  仅批注 
  317.      *            2-wdAllowOnlyFormFields 仅填写窗体 
  318.      *            0-wdAllowOnlyRevisions 仅修订 
  319.      *            -1-wdNoProtection 无保护,  
  320.      *            3-wdAllowOnlyReading 只读 
  321.      *  
  322.      */  
  323.     public void unProtectedWord(String pwd) {  
  324.         String protectionType = Dispatch.get(doc, "ProtectionType").toString();  
  325.         if (!protectionType.equals("0")&&!protectionType.equals("-1")) {  
  326.             Dispatch.call(doc, "Unprotect", pwd);  
  327.         }  
  328.     }  
  329.     /** 
  330.      * 返回文档的保护类型 
  331.      * @return 
  332.      */  
  333.     public String getProtectedType(){  
  334.         return Dispatch.get(doc, "ProtectionType").toString();  
  335.     }  
  336.   
  337.     /** 
  338.      * 设置word文档安全级别 
  339.      *  
  340.      * @param value 
  341.      *            1-msoAutomationSecurityByUI 使用“安全”对话框指定的安全设置。 
  342.      *            2-msoAutomationSecurityForceDisable 
  343.      *            在程序打开的所有文件中禁用所有宏,而不显示任何安全提醒。 3-msoAutomationSecurityLow 
  344.      *            启用所有宏,这是启动应用程序时的默认值。 
  345.      */  
  346.     public void setAutomationSecurity(int value) {  
  347.         word.setProperty("AutomationSecurity"new Variant(value));  
  348.     }  
  349.   
  350.    
  351.    
  352.    
  353.     /** 
  354.      * 在word中插入标签 labelName是标签名,labelValue是标签值 
  355.      * @param labelName 
  356.      * @param labelValue 
  357.      */  
  358.     public  void insertLabelValue(String labelName,String labelValue) {  
  359.   
  360.        Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  361.        boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
  362.         if (isExist == true) {  
  363.             Dispatch rangeItem1 = Dispatch.call(bookMarks, "Item", labelName).toDispatch();  
  364.             Dispatch range1 = Dispatch.call(rangeItem1, "Range").toDispatch();  
  365.             String bookMark1Value = Dispatch.get(range1, "Text").toString();  
  366.             System.out.println("书签内容:"+bookMark1Value);  
  367.         } else {  
  368.             System.out.println("当前书签不存在,重新建立!");  
  369.             //TODO 先插入文字,再查找选中文字,再插入标签  
  370.             this.insertText(labelValue);  
  371. //          this.find(labelValue);//查找文字,并选中  
  372.             this.setFont(truetrue,true,"102,92,38""20""",true);  
  373.             Dispatch.call(bookMarks, "Add", labelName, selection);  
  374.             Dispatch.call(bookMarks, "Hidden", labelName);  
  375.         }  
  376.     }  
  377.     /** 
  378.      * 在word中插入标签 labelName是标签名 
  379.      * @param labelName 
  380.      */  
  381.     public  void insertLabel(String labelName) {  
  382.   
  383.        Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  384.        boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
  385.         if (isExist == true) {  
  386.             System.out.println("书签已存在");  
  387.         } else {  
  388.             System.out.println("建立书签:"+labelName);  
  389.             Dispatch.call(bookMarks, "Add", labelName, selection);  
  390.         }  
  391.     }     
  392.     /** 
  393.      * 查找书签 
  394.      * @param labelName 
  395.      * @return 
  396.      */  
  397.     public boolean findLabel(String labelName) {  
  398.        Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  399.        boolean isExist = Dispatch.call(bookMarks, "Exists", labelName).getBoolean();  
  400.        if (isExist == true) {  
  401.             return true;  
  402.         } else {  
  403.             System.out.println("当前书签不存在!");  
  404.             return false;  
  405.         }  
  406.     }  
  407.     /** 
  408.      * 模糊查找书签,并返回准确的书签名称 
  409.      * @param labelName 
  410.      * @return 
  411.      */  
  412.     public String findLabelLike(String labelName) {  
  413.        Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  414.        int count = Dispatch.get(bookMarks, "Count").getInt(); // 书签数  
  415.        Dispatch rangeItem = null;  
  416.        String lname = "";  
  417.        for(int i=1;i<=count;i++){  
  418.            rangeItem = Dispatch.call(bookMarks, "Item"new Variant(i)).toDispatch();  
  419.            lname = Dispatch.call(rangeItem, "Name").toString();//书签名称  
  420.            if(lname.startsWith(labelName)){//前面匹配  
  421. //             return lname.replaceFirst(labelName, "");//返回后面值  
  422.                return lname;  
  423.            }  
  424.        }  
  425.        return "";  
  426.     }  
  427.     /** 
  428.      * 模糊删除书签 
  429.      * @param labelName 
  430.      */  
  431.     public void deleteLableLike(String labelName){  
  432.         Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  433.        int count = Dispatch.get(bookMarks, "Count").getInt(); // 书签数  
  434.        Dispatch rangeItem = null;  
  435.        String lname = "";  
  436.        for(int i=1;i<=count;i++){  
  437.            rangeItem = Dispatch.call(bookMarks, "Item"new Variant(i)).toDispatch();  
  438.            lname = Dispatch.call(rangeItem, "Name").toString();//书签名称  
  439.            if(lname.startsWith(labelName)){//前面匹配  
  440.                Dispatch.call(rangeItem, "Delete");  
  441.                count--;//书签已被删除,书签数目和当前书签都要相应减1,否则会报错:集合找不到  
  442.                i--;  
  443.            }  
  444.        }  
  445.     }  
  446.     /** 
  447.      * 获取书签内容 
  448.      * @param labelName 
  449.      * @return 
  450.      */  
  451.     public String getLableValue(String labelName){  
  452.         if(this.findLabel(labelName)){  
  453.             Dispatch bookMarks = Dispatch.call(doc, "Bookmarks").toDispatch();  
  454.             Dispatch rangeItem1 = Dispatch.call(bookMarks, "Item", labelName).toDispatch();  
  455.             Dispatch range1 = Dispatch.call(rangeItem1, "Range").toDispatch();  
  456.             Dispatch font = Dispatch.get(range1, "Font").toDispatch();  
  457.             Dispatch.put(font, "Hidden"new Variant(false)); //显示书签内容  
  458.             String bookMark1Value = Dispatch.get(range1, "Text").toString();  
  459.             System.out.println("书签内容:"+bookMark1Value);  
  460. //            font = Dispatch.get(range1, "Font").toDispatch();  
  461. //              Dispatch.put(font, "Hidden", new Variant(true)); //隐藏书签内容  
  462.             return bookMark1Value;  
  463.         }  
  464.         return "";  
  465.     }  
  466.   
  467.    
  468.     public static void main(String[] args) throws Exception {  
  469.   
  470.     }     
  471.    
  472. }  

 采用jacob方式操作文档,经常会出现卡机的现象,所以最后采用poi方式来操作书签。若单纯的操作书签用poi方式还是比较简单的,但要操作表格、文档格式之类的还是用jacob功能比较强大。