最近老板让我搞java操纵word的一些操作。有一定的感想于大家分享下。 
主要让我实现的功能如下:实现模版套打功能 
工程协议 
  该用户!@{name}@!需要的信息。这个只是lkiz 
中文ddddd!@{pwd}@!fsdfsdfsd!@{delete}@!层 
这个word   文档中的内容。通过java控制并修改该word的内容。 
在需修改处用!@{修改处}@!标识。 
通过一段时间的研究。发现根本无法实现此功能。 
最初用poi   实现,结果发现poi的功能对excle的操作还不错。 
但对word却不行。他只能够读里面的数据。拿到一个String对象。 
用字符流把里面的数据写到word中可以,但是无法控制字体大小。 
看过了poi   的api感觉始终无法对所需功能进行操作。转jxl   
然后通过搜索jxl   对word   的操作发现其功能于poi相似也是无法操作word。 
有人说jacob   和java2word   可以对他进行很好的操作。观察了一下。 
这两种东西同出一辙几乎是一样的东东,只是java2word把jacob封装了进去。 
对所需功能还是无法实现,无法定位每个!@{}@!的位置。而且此技术不是纯java代码。 
需要安装或者在system32下面加入jacob.dll的类库文件。感觉稳定性和兼容性都不好。 
不能跨平台操作。所以不予考虑。结果有寻找了一段时间。就是使用jni   java去调用c++的 
动态连接函式库去实现操作word的功能。还是一样不稳定对平台可能还有局限。 
这只是我个人的一些看法,难道java无法操纵word吗?希望大家能给与解答!!!!

解决方案 »

  1.   

    你那个我说不准,毕竟没做过,但我开发过程中却真遇到了Api错误,
    在apache的CollectionUtils(3.2版)里
    当时用到了里面的retainAll和removeAll,但怎么弄都和预想结果不对,
    当时那个折腾啊,从来没想倒API会出错。
    最后down下来source打开一看,差点没吐血,把源码翻出来给大家看看吧
        //-----------------------------------------------------------------------
        /**
         * Returns a collection containing all the elements in <code>collection</code>
         * that are also in <code>retain</code>. The cardinality of an element <code>e</code>
         * in the returned collection is the same as the cardinality of <code>e</code>
         * in <code>collection</code> unless <code>retain</code> does not contain <code>e</code>, in which
         * case the cardinality is zero. This method is useful if you do not wish to modify
         * the collection <code>c</code> and thus cannot call <code>c.retainAll(retain);</code>.
         * 
         * @param collection  the collection whose contents are the target of the #retailAll operation
         * @param retain  the collection containing the elements to be retained in the returned collection
         * @return a <code>Collection</code> containing all the elements of <code>collection</code>
         * that occur at least once in <code>retain</code>.
         * @throws NullPointerException if either parameter is null
         * @since Commons Collections 3.2
         */
        public static Collection retainAll(Collection collection, Collection retain) {
            return ListUtils.retainAll(collection, retain);
        }    /**
         * Removes the elements in <code>remove</code> from <code>collection</code>. That is, this
         * method returns a collection containing all the elements in <code>c</code>
         * that are not in <code>remove</code>. The cardinality of an element <code>e</code>
         * in the returned collection is the same as the cardinality of <code>e</code>
         * in <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which
         * case the cardinality is zero. This method is useful if you do not wish to modify
         * the collection <code>c</code> and thus cannot call <code>collection.removeAll(remove);</code>.
         * 
         * @param collection  the collection from which items are removed (in the returned collection)
         * @param remove  the items to be removed from the returned <code>collection</code>
         * @return a <code>Collection</code> containing all the elements of <code>collection</code> except
         * any elements that also occur in <code>remove</code>.
         * @throws NullPointerException if either parameter is null
         * @since Commons Collections 3.2
         */
        public static Collection removeAll(Collection collection, Collection remove) {
            return ListUtils.retainAll(collection, remove);
        }最后只好改用ListUtils了。
    谁还有类似经历也分享一下啊!
      

  2.   

    恩,看出来了,这几天竟看java和word的PK了,
    原来是你搞的鬼。
    没做过,无能为力啊。
      

  3.   

    用jacob操作比较容易,具体你自己看吧。http://free2008.bokee.com/2277069.html
      

  4.   

    难道真的无法实现操作word吗?
      

  5.   

    To 二楼:呵呵,所以说有时候调试Java比调试C/C++更麻烦,不能看汇编,这些错误很难被发现。希望以后Java能够公开Java虚拟指令集,这样在调试时可以更方便一些。
      

  6.   

    只要Java有能力能往Word文件里面写宏那就好办了, 有个叫Robhelp的软件就是这么干地, 呵呵。
      

  7.   

    java往word 里面写宏?怎么写???想象不出来。
      

  8.   

    不好意思,不是写宏, 应该是用Java调用宏的某个方法:) 某些Java组件是支持的,有这一点就不怕操作不了Word了
    http://j-integra.intrinsyc.com/support/com/doc/#other_examples/Word_VBA_from_Java.htm
    Accessing Microsoft Word VBA from Java   This example demonstrates how to access Microsoft Word VBA from Java. J-Integra® for COM is a Java interoperability component that bridges Java and Microsoft Word VBA. It provides bi-directional access of Java objects and COM components. We do not provide the documentation of the generated Java proxies since the Java proxies are just mapped from the programming API of the COM component. For more information about Microsoft Word programming, please refer to Microsoft Word Objects programming API. The quickest way to start programming Java-to-Word applications is to find a VB example first, and then map the VB code to Java.We also provide J-Integra® Development Services for you to out-source your Java and COM bridging development work. Please visit our support page for more information.Refer to the Excel VBA example for the details of steps.// This example invokes the Visual Basic method 'method1' in the template associated with a 
    // Word document. 
    // 
    // Prior to running this example define the VBA 'method1' in the default Word  
    // template's 'ThisDocument' object: 
    // o Start Word. 
    // o Click on Tools|Macro|Visual Basic Editor 
    // o In the Project window, expand Normal->Microsoft Word Objects->ThisDocument 
    // o Double-click on 'ThisDocument' to edit its code. 
    // o Insert the following method: 
    //    Public Function method1(ByVal p1 As String, ByVal p2 As Date) As Double 
    //       ActiveDocument.Content.InsertBefore (p1 & " " & p2) 
    //       method1 = 1234.5678 
    //     End Function 
    // o Click on File|Save Normal 
     
    public class WordDynamicInvoke { 
     
      public static void main(java.lang.String[] args) { 
        try { 
     
          // If running Jvm on same machine as Word, then leave the AuthInfo.setDefault() line 
          // commented, and put J-Integra®'s 'bin' directory in your PATH to allow J-Integra® to 
          // use native code to ascertain and use your current login identity. 
          // If running JVM on a UNIX machine, uncomment the line, configure DCOM access to 
          // Microsoft Word on the Windows machine, and pass the Windows machine's IP name as 
          // a parameter to the word.Application constructor 
          // com.linar.jintegra.AuthInfo.setDefault("NT DOMAIN", "USER", "PASSWORD"); 
     
          // Start Word and make it visible 
          word.Application app = new word.Application(); 
          app.setVisible(true); 
     
          // Add a document 
          word.Documents docs = app.getDocuments(); 
          word.Document doc = docs.add(null, null); 
     
          // Set up Object array of parameters to be passed to the method. 
          // Only passing parameters by value is currently supported. 
          Object[] params = { "hello", new java.util.Date() }; 
     
          // Invoke the method "method1" -- it returns a double, which J-Integra® wraps in the 
          // corresponding primitive type wrapper. 
          java.lang.Double retVal = (java.lang.Double) doc.invokeMethodByName("method1", params); 
          System.out.println("Return Value is " + retVal); 
     
          // Sleep 5 seconds so that you can see the Word document's content has been 
          // modified to include the string and date passed as parameters to the method. 
          Thread.sleep(5000); 
     
          // Quit -- don't save changes 
          app.quit(new Integer(word.WdSaveOptions.wdDoNotSaveChanges), null, null); 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } finally { 
          com.linar.jintegra.Cleaner.releaseAll(); 
        } 
      } 
    }
     
      

  9.   

    to:18楼。
    什么叫做浪费时间?
    每个关于生成报表或协议的程序。
    都不必不可少的操作word或excle
    不懂,就不要瞎说
      

  10.   

    实在不行就 JNI 不要告诉我你操作MSOffice都要跨平台。
      

  11.   

    就是使用jni       java去调用c++的   
    动态连接函式库去实现操作word的功能。还是一样不稳定对平台可能还有局限。
    ================================================
    1.jni为什么不稳定?不解。
    2.操作MS Office还要跨平台?java既然要跨平台,必然不会针对某个系统做太多的事情。
    jni就是用来解决java没有实现,需要通过与其他语言交互来解决的问题。
      

  12.   

    to:23楼。
    感谢。我看过王择佑的一个jni 调用c++的视屏。
    但是按照他的方法我写的程序无法跑起来。
    我用的是c++6.0写出来的代码他会报错
    Linking...
       Creating library Debug/TestNativeCode.lib and object Debug/TestNativeCode.exp
    LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
    Debug/TestNativeCode.exe : fatal error LNK1120: 1 unresolved externals
    执行 link.exe 时出错.c++源码
    #include "com_together_TestNative.h"
    #include <iostream>
    using namespace std;JNIEXPORT void JNICALL Java_com_together_TestNative_SayHell(JNIEnv * env, jobject obj){
    printf("HelloWord!");
    }头文件我都加进去了。为什么会出现错误。
    大家帮我看看。
      

  13.   

    sorry 是我自己的问题。建错工作组了。
      

  14.   

    我说你用java操作word是浪费时间
    要用java操作word的系统用asp.net来做就可以了
    为什么要拿java去骗钱?
      

  15.   

    汗。一个项目用两个工具去开发?
    哪不如直接用asp.net搞好了,用java干吗。
    老板让怎么搞就怎么搞。骗钱也罢。
    我没有权力去过问。我只要把本质工作做好就可以了。