Pledgie



if you think this library has been useful, feel free to give any help. Don't be shy.


Click here to lend your support to: Java2word, coding for fun! and make a donation at www.pledgie.com !

Thursday, July 22, 2010

Java2Word Microsoft Word Document Generator from Java code without any "special" components or libraries

I had a problem in my work a few weeks ago which was how to generate one Microsoft Word Document from Java code. Reports were composite by 40 pages around and over 30 database queries to bring data. It also had cover page, table of contents, header, footer and many tables.

We tried a lot of things but they were all crap solution. We had to delivery those "word" reports so the solution was pretty bad: Generate Jasper RTF and open as an Word Document.

When you open this rtf, the result is just horrible. You can't properly edit those dodge tables generated by jasper. Other problem is when you save this document as .doc, file size increased from 5 MB to 40 MB.

So... there were I again... playing around with the problem...

I decide to create an API in Java to generate Word documents from Java code. The Document generated HAS to be compatible with Microsoft Word and can't have any manipulation - so has to be ready for the end user!

I wrote two implementations: one for Word 97 - 2003 and another for Word 2004 +.

To be honest I spent more time in W2004 because this is the current standard.

I have created the java project and hosted in Google code:

http://code.google.com/p/java2word/

The philosophy is have something in Java and really easy like:

   IDocument myDoc = new Document2004();
myDoc.getBody().addEle(new Heading1("Heading01"));
myDoc.getBody().addEle(new Paragraph("This is a paragraph..."));



You are Java dev and deal with this API. You Don't need to worry about the implementation!

*Project has 97% of code test coverage.

** When I say no "special" components I mean not using any MS library.
In order to use the Java2Word you will need in your classpath xstream (if you use images) and log4j (for other than JBoss server).
Please refer to dependencies section in the project page.


49 comments:

  1. Hi there,

    Can you tell me if there are any Javadocs available for this project and where can I find them?

    Thanks!

    ReplyDelete
  2. Hey Gabriel

    I didn't generate the Javadoc because I am still entering the javadoc comments on the API.

    I can help you to set it up i you want.
    Take a look at http://code.google.com/p/java2word/ and see if you can get around with that.

    In my case, I use Maven and I build the jar locally because I couldn't find a public maven repo.

    Let me know if you have any problem to play around.

    cheers
    Leonardo

    ReplyDelete
  3. I've built a new project in eclipse and included in its classpath your "j2w-ejb-1.0.jar". Then I've created the following simple class:

    import word.api.interfaces.IDocument;
    import word.w2000.Document2000;
    import word.w2000.elements.BreakLine;
    import word.w2000.elements.Heading1;
    import word.w2000.elements.Paragraph;

    public class TestJava2Doc {
    public static void main(String[] args) {
    IDocument myWord = new Document2000();
    myWord.getBody().addEle(new Heading1("Heading01"));
    myWord.getBody().addEle(new Paragraph("This document is an example of paragraph"));

    myWord.getBody().addEle(new BreakLine());

    System.out.println(myWord.getContent());
    }
    }


    When I try to run it I get:

    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
    at word.w2000.Document2000.(Document2000.java:13)
    at TestJava2Doc.main(TestJava2Doc.java:9)
    Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Logger
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    ... 2 more

    I've added to the classpath the "log4j_1.2.15.jar" jar file and got this to work.


    However, on the Google Code link you mentioned it says that "There are NO third part components or libraries - only java code in one jar". Is it possible I misunderstood this as "There are no 3rd party dependencies, just add this jar to your classpath and you're good to go"? I know that this is still work in progress, however I find it to be the simplest and most straightforward way of exporting data from Java in Word format. The only question I have is if there are any othere dependencies I should be aware of when working with your library?

    Thank you very much! Keep up the good work!

    ReplyDelete
  4. Thank you very much Gabriel for the feedback!

    I will sort this out. I will maybe mention that we need "log4j_1.2.15.jar".

    When I say we don't need third part component, I meant no Microsoft stuff... just XML(for version >= 2004) or HTML(for version < 2003).

    I also see that you instantiate a Document2000. Remember to take a look at the "table of supported tags" in the project page.

    The implementation for W2004 has got more components like header, footer, images...

    If you are Dev and one day need to change the code, let me know and I add you as a Admin Project Member.

    Thanks for your feedback!!!

    You can send emails directly if you have any problem.

    cheers

    Leonardo

    ReplyDelete
  5. You are very welcome!
    Yes, I am a dev and when that day comes I will ask. :-) 'Till then, I bookmarked your project for future reference. Nice job!

    All the best 2u!
    Cheers!

    ReplyDelete
  6. I updated the project page with the information about log4j.

    This framework is made to work in a web application. So if you deploy in JBoss, you don't need to worry about log4j. Worse case scenario the JVM default log will be utilized.

    Thanks

    Leonardo

    ReplyDelete
  7. Hi,

    I am getting following error while using java2word.

    java.lang.UnsupportedClassVersionError: Bad version number in .class file (unable to load class word.api.interfaces.IDocument)
    at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1854)
    at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:890)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1354)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.newInstance0(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1116)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:809)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:129)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
    at java.lang.Thread.run(Unknown Source)

    ReplyDelete
  8. Did you download the j2w-ejb-1.0.jar or compile by yourself?

    What application server are you using?

    What is your Java version?

    I don't want to downgrade to java5 because java6 has been hanging around for a while and java7 is coming soon...

    The pom file in the j2w-app is set to compile using java 1.6 (line 121-128):

    The problem is definitely Java version of compiled classes.

    If you still have the problem and if you don't mind, please open an issue in the project page and I investigate this for you. Don't forget to give all details about your environment.

    Issues:
    http://code.google.com/p/java2word/issues/list

    Thanks for your feedback man!

    cheers

    Leonardo

    ReplyDelete
  9. Classes have been compiled in Java 1.6 but maybe your JAVA_HOME or JRE_HOME in your tomcat/jboss in set to Java 1.5

    More in:
    http://www.mkyong.com/java/javalangunsupportedclassversionerror-bad-version-number-in-class-file/

    and

    http://stackoverflow.com/questions/2466828/java-lang-unsupportedclassversionerror-bad-version-number-in-class-file

    ReplyDelete
  10. Seems from code that it needs dom4j also.

    ReplyDelete
  11. Hi Leonardo, you did a great job with this lib.
    But I would like to use a word template and fill it, and I didn't find the way to do this with your lib, is it possible ? it seems not but I prefer to ask, may be I missed something ... ^^

    Thanks ^^.

    Alex.

    ReplyDelete
  12. Hi Areku

    It is not possible to use template and I don't think will be... The framework wasn't designed for templates because the is a POI (Apache POI) that does this.

    For the time being, with java2word you can build very simple documents with headings, footer, H1, paragraph, break line, images but all will take a default styling...

    I will think about your problem and see if it is posible to solve...

    thanks for your feedback! Take a look at POI and let me know how you go. If you tell me that POI doesn't do it then we will have to implement one!


    cheers
    Leonardo

    ReplyDelete
  13. Is this meant to be a library?

    I ask because I find it odd that you selected the GNU license for the project.

    "The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read ."

    ReplyDelete
  14. You're right. But any one who reads knows that can use/change this library anytime.

    As I said, when I created java2word it wasn't supposed to be what is is now. I just wanted to put the code in a SVN repo.

    At that time, I didn't have permission to create one repo in my current company, so I decided to use google code.

    I have changed the license to "GNU Lesser General Public License". Now is is clear that you can do whatever with java2word.

    Btw if you really care about license and copy rights, DOC is a property format and belongs to M$.

    Thanks for your feedback! Don't be afraid to give more if your feel like.



    cheers

    Leonardo

    ReplyDelete
  15. Hi

    I use this code from your example. Can you tell me why this generates an empty Document? Thx!

    IDocument myDoc = null;
    try {
    PrintWriter writer = new PrintWriter("C:/word2000_3.doc");

    myDoc = new Document2000();
    myDoc.getBody().addEle(new Heading1("Heading01"));
    myDoc.getBody().addEle(new Paragraph("This document is an example of paragraph"));

    myDoc.getBody().addEle(new BreakLine());

    String myWord = myDoc.getContent();
    writer.println(myWord);

    } catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }

    best regards

    Thomas

    ReplyDelete
  16. I wrote a very basic unit test just to print it out:

    @Test
    public void xxx(){
    Document2000 myDoc = new Document2000();
    myDoc.getBody().addEle(new Heading1("Heading01"));
    myDoc.getBody().addEle(new Paragraph("This document is an example of paragraph"));
    myDoc.getBody().addEle(new BreakLine());
    String myWord = myDoc.getContent();
    System.out.println(myWord);
    }


    Then I copied the output and pasted on the Web Test Application (part of the framework) and worked fine.

    I have the screenshot but can't attach to the comment.

    You can always make sure the method myDoc.getContent() returns/prints something.

    I am not sure if you noticed but the MS Word 2000 of this framework will be removed in the version 2.0.

    W2000 implementation in Java2word is very limited whereas W2004 we can implement almost everything. W2004 is XML based.

    I strongly recommend you to use Document2004:

    Document2004 myDoc = new Document2004();

    Send me an email if you have any problem and I help you.


    cheers
    Leonardo

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. hi am using document2004 oly but i couldn't add the image into word doc ... plz help me

      Delete
  17. Another thing: Are you using Servlet?

    Because I can't see where you get a reference to the ServletResponse.

    ReplyDelete
  18. HI Leonardo
    G8 job..
    this is working fine for me...
    Thankx for your sharing

    ReplyDelete
  19. Hi Leonardo,

    I got a doubt that,if i want to insert an image in a td, how can i insert that?
    please suggest me on this.
    please correct me if i am wrong..

    ReplyDelete
  20. Hi Rajesh

    I will have a look and tell you. This is definitely possible.

    I am setting up a new computer and will have a look at this tomorrow or after tomorrow.

    * Style Framework is out!

    Leonardo

    ReplyDelete
  21. Hello Leonardo.

    I´m sorry but my English is very bad. I´m Spanish.
    I´m very interested in your project.
    I tried java2word a standalone application. This works fine. ;-)

    I´m very interested in supporting fonts, colors, lists and tables.
    How is all this?

    Thank you and encourage you with your project.

    ReplyDelete
  22. Holla Como estas Rrr,

    At the moment, you can apply colors to paragraphs and Headings. I will implement font very soon.

    list is a bit difficult to do. Numeric is ok but with bullet points is a bit complicated... I will try again in the future.

    I am still defining the Style pattern and the "Fluent Interface". When this happens, I will replicate/apply the same pattern for the other elements.

    Styling Tables is down on track.

    Hasta luego amigo!

    Leonardo

    ReplyDelete
  23. Holla Rrr,

    This is the solution for you:

    Table tbl01 = new Table();
    Image img = new Image("http://www.google.com.au/intl/en_com/images/srpr/logo1w.png", ImageLocation.WEB_URL);
    String [] cols = {img.getContent(), "aaa", "bbb"};
    tbl01.addTableEle(TableEle.TH, cols);

    This was already implemented but I had to test before I affirm anything...

    cheers

    Leonardo

    ReplyDelete
  24. Hi Leonardo,

    Thanks for your reply..


    Can we have api for this?if yes please let me know.
    i tried in java2word site,but i could not find that..

    ReplyDelete
  25. I couldn't find a nice way to display the Javadoc in google code. But this is possible because I have seen it before.

    If you want to have a look at the SVN you can access:
    http://code.google.com/p/java2word/source/browse/#svn/trunk/j2w-ejb/docs/2.0

    another good way to see what is possible is looking at the examples and also the page "Elements Reference".

    This will be improved in the future...

    Leonardo

    ReplyDelete
  26. Hola Leonardo!

    I am delighted with this project!.

    With your permission ... I've been doing some development testing to use the fonts.
    The first tests (very basic) are working well, although I think the approach that I have given is not correct. Right (I guess) would mix fonts with styles.
    I pass the class I developed, and an example of use, if you're serving.

    Saludos!

    Example of use:
    ---------------
    FontSimple fontSimple = new FontSimple("Courier New", "Hello", FontSimple.FONT_SIZE_16);
    fontSimple.setColor("C00000");
    fontSimple.setColorBackgroundFill("000000");
    fontSimple.setBold(true);
    fontSimple.setItalic(true);
    myDoc.getBody().addEle(fontSimple);
    -----
    Uhmmm... As I attached the Java class?

    ReplyDelete
  27. Hi Leonardo,
    Nice, Neat and Easy way to write MS Word files using java2word.
    Your statement above for AREKU:
    "The framework wasn't designed for templates because the is a POI (Apache POI) that does this."
    but POI doesn't do that, even they say they are in development stages.
    Can you link me to some examples/code for creating word files using java2word or POI.
    That would be of great help to me.
    I would like to see if I can contribute by writing some classes to add more functionality to java2word with your permission.
    Please show me the path.

    Thanks,
    Sudheer

    ReplyDelete
  28. Hi Sudheer

    There are some examples (Struts and Seam) in:
    http://code.google.com/p/java2word/source/browse/#svn/trunk/ExampleStruts

    The class AllInOneAction.java in the Struts Example shows a little bit of every element of the API but this class NEEDS UPDATE because new elements have been added:

    http://code.google.com/p/java2word/source/browse/trunk/ExampleStruts/JavaSource/demo/AllInOneAction.java


    See the Project Page to check what is going on: http://code.google.com/p/java2word/

    See the issue list to check what WILL be coming soon:
    http://code.google.com/p/java2word/issues/list


    cheers
    Leonardo

    ReplyDelete
  29. Hey Leonardo,
    I have found the example AllInOneAction.java, and was able to generate some good word doc.
    Thanks a lot.

    Hey Ricard,
    Can I get the FontSimple.class file.

    Thanks,
    Sudheer

    ReplyDelete
  30. Hey Leonardo,
    Can java2word can be used to read the .DOC or .DOT files.
    I have a requirement like this, is this achievable using JAVA.
    Can we convert a .DOT (a word template file) to a .DOC (ms word document file) programmatically by filling some values at given places.

    Ex: My MS Word template file would have "Attribute Display Name: Attribute Value", a key:pair value types, the program should fill these values with the array of values I pass.

    Let me know if such thing is achievable mostly in Java or C/C++.

    --
    Sudheer

    ReplyDelete
  31. Hi Sudheer

    I have created an issue so that other people can contribute: https://code.google.com/p/java2word/issues/detail?id=14

    Take a look pls. Someone has asked this before...

    cheers
    Leonardo

    ReplyDelete
  32. Hi
    Leonardo

    Gr8 job, I had requirments like admin will put rich test data in database(Html )also need to add TOC for word doc how do we do tat?

    Thanks
    Raghu

    ReplyDelete
  33. Hi ,Leonardo

    I am using Java2word for generating word document . and seriously saying its a wonderfull and very easy api i have ever seen for generating word document . I stuck in one problem . I am adding image into my word document . But my scenario is some thing like i need to add image at particular location.
    So is that any way by which i can provide X and Y cordination while inserting image . and image will at that cordinate only ...

    Thanks in advance .
    Jitendra

    ReplyDelete
  34. Thanks Jitendra for your feedback!

    I haven't implemented image styling yet. I created an issue for this. It shouldn't be too difficult.

    https://code.google.com/p/java2word/issues/detail?id=19

    what you can currently do with images is change the size: width and length.


    cheers
    Leonardo

    ReplyDelete
  35. Java2word with Templates is out!

    https://code.google.com/p/java2word/wiki/TemplatesWithJava2word

    ReplyDelete
  36. Hi Leonardo,

    I want to modify style of the table.How to do that?

    ReplyDelete
  37. It is not possible yet. There is a task to do it but it hasn't been implemented.

    ReplyDelete
  38. Leonardo,
    Thanks for your great code.
    I have a problem following your solution for Rrr :)
    When trying to instantiate Image as (to add in table):
    Image img = new Image();
    I get the:
    The constructor Image() is undefined.
    Any suggestions?
    Thanks,
    Blagoy

    ReplyDelete
    Replies
    1. the current version you HAVE to use fluent interfaces:

      Image.from_FULL_LOCAL_PATHL(...) or
      Image.from_WEB_URL

      Take a look at the class Image

      Delete
  39. Hi Leonardo first of all i want to thank you for your work , i'm doing a school proyect and it has been of great help.
    While doing this proyect i have had a problem in adding text dynamically to a paragraph. By dynamically i mean that i have an array which have a different size every time i need to write the document. Whenever i'm writing the document i need all of the elements in the array to be in the same paragraph.
    I have been trying to create the paragraph with ParagraphPieces, but since the Paragraph.withPieces accepts only ParagraphPieces arguments, everytime i write the elements they are in separate paragraphs.
    Is there a workaround to insert text in an already set paragraph?

    ReplyDelete
    Replies
    1. The paragraph will be composited by many paragraphPieces. Post the code and we have a look at it.

      Delete
  40. Im having this problem:

    ava.io.FileNotFoundException: build.properties (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.(FileInputStream.java:120)
    at java.io.FileInputStream.(FileInputStream.java:79)
    at word.utils.TestUtils.createLocalDocument(TestUtils.java:45)
    at word.utils.TestUtils.createLocalDoc(TestUtils.java:37)
    at paquete.OtraPruebaJavaAWord.testJava2wordAllInOne(OtraPruebaJavaAWord.java:254)
    at paquete.OtraPruebaJavaAWord.main(OtraPruebaJavaAWord.java:29)
    java.io.FileNotFoundException: null/Documento Nuevo Word (No such file or directory)
    at java.io.FileOutputStream.open(Native Method)
    at java.io.FileOutputStream.(FileOutputStream.java:194)
    at java.io.FileOutputStream.(FileOutputStream.java:145)
    at java.io.PrintWriter.(PrintWriter.java:218)
    at word.utils.TestUtils.createLocalDocument(TestUtils.java:58)
    at word.utils.TestUtils.createLocalDoc(TestUtils.java:37)
    at paquete.OtraPruebaJavaAWord.testJava2wordAllInOne(OtraPruebaJavaAWord.java:254)
    at paquete.OtraPruebaJavaAWord.main(OtraPruebaJavaAWord.java:29)
    Exception in thread "main" java.lang.NullPointerException
    at word.utils.TestUtils.createLocalDocument(TestUtils.java:64)
    at word.utils.TestUtils.createLocalDoc(TestUtils.java:37)
    at paquete.OtraPruebaJavaAWord.testJava2wordAllInOne(OtraPruebaJavaAWord.java:254)
    at paquete.OtraPruebaJavaAWord.main(OtraPruebaJavaAWord.java:29)
    Java Result: 1

    I cant find a solution. I have already linked the java2word.jar to the project libraries

    ReplyDelete
    Replies
    1. Copy the file build.properties.EXAMPLE to build.properties. Add it to SVN ignore list

      http://code.google.com/p/java2word/wiki/How_to_Implement_a_New_Element?ts=1327271293&updated=How_to_Implement_a_New_Element#Set_up_your_Development_Environment

      Delete
  41. Hi Leonardo Correa,

    Could you please tell me how to open msword documents(latest versions(.docx)) files in java(Android).

    ReplyDelete
  42. java2word doesn't generate .docx. It generates WordProcessingML which is XML representation of the document. If the file is .doc, you should be able to open in any MS Word version > 2003. I have never tried on androids. There are some issues related to androids: issue 43 and issue 52

    ReplyDelete
  43. hello sir...
    I have 5 Jtextfields with some data in java swing...and below this there is one button so when i clicked this button these text field data should display in MSword on one template in a table format. so how to achieve it ?

    ReplyDelete