Page 1 of 1

Issue with Fields with (incorrect) multiple Instructions

PostPosted: Wed Apr 29, 2020 10:55 pm
by sledwich
I am using the MailMerger.performMerge which is working fine in most cases but I have a library of documents where some of the merge fields have incorrectly spanned across multiple instructions and the performMerge is throwing null pointer exception.
So the xml looks like this:
Code: Select all
<w:p w:rsidR="000060E0" w:rsidRDefault="00EF2C0C" w:rsidP="000060E0">
   <w:r>
      <w:fldChar w:fldCharType="begin" />
   </w:r>
   <w:r>
      <w:instrText xml:space="preserve"> MERGEFIELD D6_15_0#Blank_Field</w:instrText>
   </w:r>
   <w:r>
      <w:instrText xml:space="preserve"> \* MERGEFORMAT </w:instrText>
   </w:r>
   <w:r>
      <w:fldChar w:fldCharType="separate" />
   </w:r>
   <w:r w:rsidR="000060E0">
      <w:rPr>
         <w:noProof />
      </w:rPr>
      <w:t>«D6_15_0#Blank_Field»</w:t>
   </w:r>
   <w:r>
      <w:rPr>
         <w:noProof />
      </w:rPr>
      <w:fldChar w:fldCharType="end" />
   </w:r>
</w:p>


I would like to be able to combine the instructions into one (which is what they should be) and I have tried

Code: Select all
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
       ComplexFieldLocator fl = new ComplexFieldLocator();
       new TraversalUtil(documentPart.getContent(), fl);
       List<FieldRef> fieldRefs = new ArrayList<>();
       for (P p : fl.getStarts()) {
             FieldsPreprocessor.canonicalise(p, fieldRefs);
         }
       for (FieldRef fr : fieldRefs) {
          System.out.println(fr.getInstructions().size());
          if( fr.getInstructions().size()>1)
          {
            
            for( int i=1; i<fr.getInstructions().size(); i++) {
               final Object x = fr.getInstructions().get(i);
               final Object o = XmlUtils.unwrap(x);
//               System.out.println(x);
//               System.out.println(o);
               if (o instanceof Text) {
                  final String value = ((Text)o).getValue();
                  if( StringUtils.isNotEmpty(value)) {
                     final Object x0 = fr.getInstructions().get(0);
                     final Object o0 = XmlUtils.unwrap(x0);
                     if (o0 instanceof Text) {
                        final String value0 = ((Text)o0).getValue();
                        ((Text)o0).setValue(value0+value);
                     }
                  }
               }
            }
            for( int i=fr.getInstructions().size()-1; i>0; i--) {
               fr.getInstructions().remove(i);
            }            
          }
       }


Which does remove the second instruction but does not write that back to the wordMLPackage. Is there any way to do it, or a better way to do it. Thank you.

Re: Issue with Fields with (incorrect) multiple Instructions

PostPosted: Thu Apr 30, 2020 8:00 pm
by sledwich
just to add a bit more context on this, the root cause of the problem is to do with this:

In MailMerger#performOnInstance
there is call to get

String instr = extractInstr(fr.getInstructions() );

Which looks like this:
Code: Select all
   protected static String extractInstr(List<Object> instructions) {
      // For MERGEFIELD, expect the list to contain a simple string
      
      if (instructions.size()!=1) {
         log.error("TODO MERGEFIELD field contained complex instruction");


In our situation the second instruction is "\* MERGEFORMAT" but this is causing it to throw a NPE when Instr is referred to as its will always come as NULL where the instruction count <> 1.