How do I create a Word document from a template or an existing document using Java?

I have a document template where some fields are static and others are dynamic. I need to replace some data (first name, last name, salary) and generate a new file. In which library do you recommend doing this? Is POI compliant? I am working with Spring, Java EE6 and Oracle.

+3


source to share


2 answers


You can try Apache POI, but the HWPF and XWPF POI parts that are required to work with text files are really tricky to use - you need to have at least a good understanding of how a text file is structured!

Solution using iText and PDF

I did something similar with PDF (this might be an option for you)

1) You can use LibreOffice to create fields in your document (for example, in Acrobat Pro)

  • Create a .odt file and customize it
  • or convert your template to it using MS Word or LibreOffice Writer
  • Then go to "View" β†’ "Tools" β†’ "Shape Design" and set "Design Mode On / Off"
  • Now you can add fields to your file (double clicking on it will open the field properties)
  • When you're done: "File -> Export as PDF"

2) Now you can use iText to fill in the generated fields

Below is a sample code:



    public byte[] getDocumentAsByteArray(Object dataBean, String pdfTemplateName) throws KkmsException {

    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    PdfStamper stamp = null;
    InputStream templateInputStream = null;

    Locale local = new Locale(language);

    try {
        templateInputStream = // get the file input stream of the pdf
        PdfReader reader = new PdfReader(templateInputStream);

        // Create a stamper that will copy the document to a new file
        stamp = new PdfStamper(reader, outputStream);

        AcroFields form = stamp.getAcroFields();

        // form fields are normal text in the end
        stamp.setFormFlattening(true);
        Map<String, AcroFields.Item> map = (Map<String, AcroFields.Item>)form.getFields();
        if (map != null) {
            if (map.size() == 0) {
                logger.debug("There are no fields in this PDF layout");
            }
            for (Entry<String, AcroFields.Item> e : map.entrySet()) {
                logger.debug("PDF fieldname = " + e.getKey());

                // at the moment we only handle text fields
                if (AcroFields.FIELD_TYPE_TEXT == form.getFieldType(e.getKey())) {
                    fillForm(dataBean, form, e.getKey(), local);
                } else {
                    logger.warn("Field type is not supported: "+form.getFieldType(e.getKey()));
                }
            }
        }

        stamp.close();
    } catch (Exception e) {
        logger.warn("Failed to create PDF document", e);
        throw new KkmsException("Failed to create PDF document: "+e.getMessage());
    } finally {
        if (templateInputStream != null) {
            try {
                templateInputStream.close();
            } catch (IOException e) {
                throw new KkmsException("Failed to close InputStream of PDF document", e);
            }
        }
    }
    return outputStream.toByteArray();
}

      

At the end you get a PDF -> hope this helps you at least a little!

Another quick and dirty solution

You can use the power of odt or docx -> convert your document to docx or odt -> its just a zip file -> so unzip it -> you will see the content.xml file in the zip root -> all the document content is there Now you can add some magic tags (like $ $$), which can later be replaced by your program

<text:p text:style-name="P3">SAP Customer Number:</text:p>

<text:p text:style-name="P3">SAP Customer Number: $$$sapCustomerNumber$$$</text:p>

      

Now create a program that unpacks the odt / docx file -> replace tags -> zips the file again

+3


source


These slides , from a presentation I gave at OSDC 2012, describe some of the main approaches.



These days I'll most likely add "generate what you want as XHTML and then export it to docx". Since we introduced docx4j-ImportXHTML with support for converting @class CSS values ​​to Word styles, we've seen this approach more and more.

+2


source







All Articles