Page 1 of 1

Mail Merge with Next Keyword

PostPosted: Thu Oct 08, 2015 11:39 pm
by el_majori
Hi guys

I'm kind of struggling with the docx4j framework at the moment. I hope you guys can help me, that would be amazing :D So here is my case

First of all, this is the code snipped i'm using right now. I found the snippet here.
Code: Select all
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.docx4j.XmlUtils;
import org.docx4j.model.fields.merge.DataFieldName;
import org.docx4j.model.fields.merge.MailMerger.OutputField;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

/**
* Example of how to process MERGEFIELD.
*
* See http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/MERGEFIELD.html
*
*/
public class MMTester {

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

        // Whether to create a single output docx, or a docx per Map of input data.
        // Note: If you only have 1 instance of input data, then you can just invoke performMerge
        boolean mergedOutput = true;

        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(
                new java.io.File(
                        System.getProperty("user.dir") + "/src/docs/Template.docx"));
//                  System.getProperty("user.dir") + "/template.docx"));

        List<Map<DataFieldName, String>> data = new ArrayList<Map<DataFieldName, String>>();

        // Instance 1
        Map<DataFieldName, String> map = new HashMap<DataFieldName, String>();
        map.put( new DataFieldName("Name"), "Daffy duck");
        map.put( new DataFieldName("Adresse"), "Plutext");
        map.put(new DataFieldName("Kundenstrasse"), "Bourke Street");
        // To get dates right, make sure you have docx4j property docx4j.Fields.Dates.DateFormatInferencer.USA
        // set to true or false as appropriate.  It defaults to non-US.
        map.put(new DataFieldName("yourdate"), "15/4/2013");
        map.put(new DataFieldName("yournumber"), "2456800");
        data.add(map);

        // Instance 2
        map = new HashMap<DataFieldName, String>();
        map.put( new DataFieldName("Name"), "Jason");
        map.put(new DataFieldName("Adresse"), "Collins Street");
        map.put(new DataFieldName("yourdate"), "12/10/2013");
        map.put(new DataFieldName("yournumber"), "1234800");
        data.add(map);


        if (mergedOutput) {
         /*
          * This is a "poor man's" merge, which generates the mail merge 
          * results as a single docx, and just hopes for the best.
          * Images and hyperlinks should be ok. But numbering
          * will continue, as will footnotes/endnotes.
          * 
          * If your resulting documents aren't opening in Word, then
          * you probably need MergeDocx to perform the merge.
          */

            // How to treat the MERGEFIELD, in the output?
            org.docx4j.model.fields.merge.MailMerger.setMERGEFIELDInOutput(OutputField.KEEP_MERGEFIELD);

         System.out.println(XmlUtils.marshaltoString(wordMLPackage.getMainDocumentPart().getJaxbElement(), true, true));

            WordprocessingMLPackage output = org.docx4j.model.fields.merge.MailMerger.getConsolidatedResultCrude(wordMLPackage, data, true);

         System.out.println(XmlUtils.marshaltoString(output.getMainDocumentPart().getJaxbElement(), true, true));

            output.save(new java.io.File(
                    System.getProperty("user.dir") + "/OUT_Template.docx") );

        } else {
            // Need to keep the MERGEFIELDs. If you don't, you'd have to clone the docx, and perform the
            // merge on the clone.  For how to clone, see the MailMerger code, method getConsolidatedResultCrude
            org.docx4j.model.fields.merge.MailMerger.setMERGEFIELDInOutput(OutputField.KEEP_MERGEFIELD);

            int i = 1;
            for (Map<DataFieldName, String> thismap : data) {
                org.docx4j.model.fields.merge.MailMerger.performMerge(wordMLPackage, thismap, true);
                wordMLPackage.save(new java.io.File(
                        System.getProperty("user.dir") + "/OUT_FieldsMailMerge_" + i + ".docx") );
                i++;
            }
        }

    }

}


So, i've got a template (.docx) with placeholders like "Name", "Address" of a person inside, followed by the "Next" Keyword for Mail Merge. Now i would like to generate just ONE Word-Document. For each Person specified in
Code: Select all

List<Map<DataFieldName, String>> data = new ArrayList<Map<DataFieldName, String>>();

i wanna generate ONE line with the persons data. On the next line, there should be Person 2, after Person 3 and so on...

There is this option
Code: Select all
boolean mergedOutput = true;
to set, what i've read this is exactly what i'm looking for.

Apparently it doesn't work the right way. Here is the template and the output document:
Template.docx
(13.2 KiB) Downloaded 571 times

OUT_Template.docx
(13.23 KiB) Downloaded 513 times


This comment i found in the release notes of the last version 3.2.1 of docx4java...
MailMergerWithNext (baudinseb): supports NEXT, useful for mailing labels

I guess this is what i'm looking for?

I hope you guys can help me out a little bit.
Thank you very much!
Regards san

Re: Mail Merge with Next Keyword

PostPosted: Fri Oct 09, 2015 12:13 am
by el_majori
Ayy i just found the solution here:
https://github.com/plutext/docx4j/commi ... 6ad1f3f496

Thank you very much :)

I had to add this code:
Code: Select all
org.docx4j.model.fields.merge.MailMergerWithNext.performLabelMerge(output, data);


Regrads san