Page 1 of 1

docx4j 2.8.0 - mergefields

PostPosted: Thu May 24, 2012 10:38 pm
by Timothy
Jason,

This morning I have changed the version of docx4j in the main pom of our project to 2.8.0. In the previous version of our application we replaced mergefield by own code. I read about the new feature of replacing mergefields in the new docx4j release and updated.

I have tested the code with a docx file consisting of a maindocument part and a footer. I see the footer's mergefields are not replaced. In the MailMerger class there is a piece of comment saying the mergefield feature is only appriopriate for the mainDocument part.

Is there a reason for this limitation?

Thx in advance.

Timothy

Re: docx4j 2.8.0 - mergefields

PostPosted: Thu May 24, 2012 11:07 pm
by jason
Timothy wrote:In the MailMerger class there is a piece of comment saying the mergefield feature is only appriopriate for the mainDocument part.

Is there a reason for this limitation?


Hi Timothy, not particularly. It ought to be straightforward to extend to headers/footers, and I'd be happy to accept a pull request which does so. cheers .. Jason

Re: docx4j 2.8.0 - mergefields

PostPosted: Fri May 25, 2012 12:35 am
by Timothy
Jason,

I made a LocalMAilMerger class with a new version of the getConsolidatedResultCrude method but it doesn't seem to work. Can you tell me what I'm doing wrong here?

Code: Select all
public static WordprocessingMLPackage getConsolidatedResultCrude(WordprocessingMLPackage input,
         List<Map<DataFieldName, String>> data) throws Docx4JException, WordIntegrationException {

      // Just MDP for now -> not enough (expand to all parts)
      WordprocessingMLPackage target = input;
      Parts docParts = input.getParts();
      Iterator<Part> partIterator = docParts.getParts().values().iterator();
      while (partIterator.hasNext()) {
         Part part = (Part) partIterator.next();
         if (part instanceof ContentAccessor && part instanceof JaxbXmlPart) {

            FieldsPreprocessor.complexifyFields((JaxbXmlPart) part);
            List<List<Object>> results = perform((ContentAccessor) part, data);

            // Prepare for cloning
            OpcPackage result = null;

            // Zip it up
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            SaveToZipFile saver = new SaveToZipFile(target);
            saver.save(baos);
            byte[] template = baos.toByteArray();

            target = WordprocessingMLPackage.load(new ByteArrayInputStream(template));
            SectPr documentSeparator = getDocumentSeparator(target);
            List<Object> contentList = ((ContentAccessor) part).getContent();
            contentList.clear();

            for (List<Object> content : results) {

               // now inject the content
               contentList.addAll(content);

               // for all but last document
               if (!content.equals(results.get(results.size() - 1))) {
                  // add sectPr to final paragraph
                  Object last = content.get(content.size() - 1);
                  P lastP = null;
                  if (last instanceof P) {
                     lastP = (P) last;
                  } else {
                     lastP = Context.getWmlObjectFactory().createP();
                     contentList.add(lastP);
                  }
                  if (lastP.getPPr() == null) {
                     lastP.setPPr(Context.getWmlObjectFactory().createPPr());
                  }
                  lastP.getPPr().setSectPr(documentSeparator);
               }
            }
         }
      }

      return target;
   }

Re: docx4j 2.8.0 - mergefields

PostPosted: Fri May 25, 2012 5:07 pm
by Timothy
I found the problem. The following code works for all parts that implements ContentAccessor:

Code: Select all
   public static WordprocessingMLPackage getConsolidatedResultCrude(WordprocessingMLPackage input,
         List<Map<DataFieldName, String>> data) throws Docx4JException, WordIntegrationException {

      // Just MDP for now -> not enough (expand to all parts)
      WordprocessingMLPackage target = input;
      Parts docParts = input.getParts();
      Iterator<Part> partIterator = docParts.getParts().values().iterator();
      while (partIterator.hasNext()) {
         Part part = (Part) partIterator.next();
         if (part instanceof ContentAccessor && part instanceof JaxbXmlPart) {

            FieldsPreprocessor.complexifyFields((JaxbXmlPart) part);
            List<List<Object>> results = perform((ContentAccessor) part, data);

            // Prepare for cloning
            OpcPackage result = null;

            // Zip it up
            // ByteArrayOutputStream baos = new ByteArrayOutputStream();
            // SaveToZipFile saver = new SaveToZipFile(target);
            // saver.save(baos);
            // byte[] template = baos.toByteArray();

            // target = WordprocessingMLPackage.load(new ByteArrayInputStream(template));
            SectPr documentSeparator = getDocumentSeparator(target);
            List<Object> contentList = ((ContentAccessor) part).getContent();
            contentList.clear();

            for (List<Object> content : results) {

               // now inject the content
               contentList.addAll(content);

               // for all but last document
               if (!content.equals(results.get(results.size() - 1))) {
                  // add sectPr to final paragraph
                  Object last = content.get(content.size() - 1);
                  P lastP = null;
                  if (last instanceof P) {
                     lastP = (P) last;
                  } else {
                     lastP = Context.getWmlObjectFactory().createP();
                     contentList.add(lastP);
                  }
                  if (lastP.getPPr() == null) {
                     lastP.setPPr(Context.getWmlObjectFactory().createPPr());
                  }
                  lastP.getPPr().setSectPr(documentSeparator);
               }
            }
         }
      }

      return target;
   }

Re: docx4j 2.8.0 - mergefields

PostPosted: Tue May 29, 2012 5:07 pm
by Timothy
Jason,

I have two more questions.

1. Are mergefields possible in footnotes (the footnotes part doesn't implement ContentAccessor)
2. When I replace mergefields that are right aligned they jump to left after replacement by docx. Is that a normal side effect?

Thanx in advance!

Timothy

Re: docx4j 2.8.0 - mergefields

PostPosted: Tue May 29, 2012 7:44 pm
by jason
With https://github.com/plutext/docx4j/commi ... 7e454b9d00 the footnotes part implements ContentAccessor

The alignment issue you describe is probably because there is currently no support for MERGEFIELD formatting. What is the content of the MERGEFIELD you are looking at?

cheers .. Jason

Re: docx4j 2.8.0 - mergefields

PostPosted: Tue May 29, 2012 7:54 pm
by Timothy
Jason,

The alignment is defined as a paragraph property. In the performMappings method when creating a new Paragraph, I set the properties of the old paragraph to the new paragraph:

Code: Select all
newP.setPPr(p.getPPr());


the problem seems to be solved then.
The question about the footerParth though is still open...

Timothy

Re: docx4j 2.8.0 - mergefields

PostPosted: Tue May 29, 2012 7:57 pm
by Timothy
Oops, sorry I overlooked the first line in your answer, you may ignore my previous post :?

Thanx!

Re: docx4j 2.8.0 - mergefields

PostPosted: Tue May 29, 2012 10:01 pm
by jason