Mailmerge with multiline field and \t

Dear Aspose team,

our customizer has a template with mergefields which values contains multilines, i.e.
1.\tline 1
2.\tline 2: a very long line, which needs more space than in line is available and should get an additional linebreak
3.\tline 3

On mailmerging the second line gets the expected linebreak, but is not idented like the second line itself:

1.\tline 1
2.\tline 2: a very long line, which needs more space than
in line is available and should get an additional linebreak
3.\tline 3

The customer would expect following output:

1.\tline 1
2.\tline 2: a very long line, which needs more space than
\tin line is available and should get an additional linebreak
3.\tline 3

Is there any possibility on com.aspose.words.IFieldMergingCallback#fieldMerging to control this like expected? Or is there any possibility in template to mark the mergefield as formatted multiline element?

Thanks a lot! Cheers,
Jens

@ns1045,

Thanks for your inquiry. You can achieve your requirement by using both cases.

  1. Implement IFieldMergingCallback interface and insert the content at the place of mail merge field according to your requirement.
  2. Add TabStop to paragraph which contains the mail merge field.

Please share some detail about your data source. How are you getting these values? Please also share your expected Word document. We will investigate how you want your final Word output be generated like. We will then provide you more information on this along with code.

Hi Tahir,

thanks for the reply&suggestion. Additional you’ll find the template document, the generated output and the expected output. Further you’ll find the code snippet we are using for filling mergefields.

MultiLineMegreFieldsDocuments.zip (29.8 KB)

  @Test
  public void testMultiLineMergeField() throws Exception {
    AsposeLicense.checkLicense();
    Document document = new Document(this.getClass().getResourceAsStream("ExampleMultiLineMergeField.docx"));

    String[] values = new String[]{"1.\tFirst line\n2.\tSecondline with is so long, that there will be inserted a new linebreak. Oh but no additional tabstopp. So bad....\n3.\t third line\n4.\tanother additional line"};
    String[] fields = new String[]{"Field"};
    document.getMailMerge().execute(fields, values);
    document.save("/Users/boeckel1/Desktop/outputMultilineField.docx");
  }   
Summary

This text will be hidden

@ns1045,

Thanks for sharing the detail. In your case, we suggest you please set the hanging indent of paragraph as shown in attached image. We have attached the modified input document and output document with this post for your kind reference. hanging indent.png (12.4 KB)
Docs.zip (17.7 KB)

Hi Tahir,

thank you very much. Unfortunately this does not help in every case. Our customer has the case that the value returned by mailmerge does not only contain the list but additional some other formatted text. Here again a code snippet to reproduce the unexpected document. Additional the expected output.

  @Test
  public void testMultiLineMergeField() throws Exception {
    AsposeLicense.checkLicense();
    Document document = new Document(this.getClass().getResourceAsStream("ExampleMultiLineMergeField.docx"));

    String[] values = new String[]{"1.\tFirst line\n2.\tSecondline with is so long, that there will be inserted a new linebreak. Oh but no additional tabstopp. So bad....\n3.\t third line\n4.\tanother additional line\n\n\nOh no, there is another not formatted line which should not be indented."};
    String[] fields = new String[]{"Field"};
    document.getMailMerge().execute(fields, values);
    document.save("/Users/boeckel1/Desktop/outputMultilineField.docx");
  }

Cheers
Jens Boeckel

MailMergeDocumentsWithAdditionalUnformatted text.zip (17.6 KB)

@ns1045,

Thanks for your inquiry. We are working over your query and will get back to you soon.

Hi @tahir.manzoor,

thanks for the information. Here another input: another possibility would be using RTF as value of mergefield, inserted as HTML with DocumentBuilder.insertHtml() (see following code snippet). But in that case the html document ignores the indenting of the mergefield. No matter if the flag ‘useBuilderFormatting’ is set to true or false.

  @Test
  public void testMultiLineMergeField_RTF() throws Exception {
    Document document = new Document(this.getClass().getResourceAsStream("ExampleMultiLineMergeField.docx"));

    document.getMailMerge().setFieldMergingCallback(new IFieldMergingCallback() {
      @Override
      public void fieldMerging(FieldMergingArgs fieldMergingArgs) throws Exception {
        if (fieldMergingArgs.getFieldName().equals("FIELD")) {
          insertRTF(fieldMergingArgs);
        }
      }

      @Override
      public void imageFieldMerging(ImageFieldMergingArgs imageFieldMergingArgs) throws Exception {

      }
    });

    String[] values = new String[]{""};
    String[] fields = new String[]{"Field"};
    document.getMailMerge().execute(fields, values);
    document.save("outputMultilineFieldRTF.docx");
  }

  private void insertRTF(@Nonnull final FieldMergingArgs fieldMergingArgs) throws Exception {
    DocumentBuilder builder = new DocumentBuilder(fieldMergingArgs.getDocument());
    //making sure that builder is at the parent of mergefield, not at the document start
    builder.moveTo(fieldMergingArgs.getField().getStart().getParentNode());
    //now go to nex mergefield with corresponding fieldname
    if (builder.moveToMergeField("FIELD")) {
      try (InputStream inputStream = TestAsposeDocument.class.getResourceAsStream("mergefieldContent.rtf");
           ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        LoadOptions options = new LoadOptions();
        Document rtfDocument = new Document(inputStream, options);
        HtmlSaveOptions saveOptions = new HtmlSaveOptions();
        rtfDocument.save(baos, saveOptions);
        baos.flush();
        builder.insertHtml(baos.toString("UTF-8"), true);
      }
      fieldMergingArgs.setText("");
    }
  }

mergefieldContent.rtf.zip (1.6 KB)

@ns1045,

Thanks for your inquiry. Please note that Aspose.Words mimics the same behavior as MS Word does. If you insert the RTF or HTML content to desired location using MS Word, you will get the same output.

In your case, we suggest you please implement IFieldMergingCallback interface. Insert each paragraph of RTF and HTML document to the desired location and set its left and hanging indent according to your requirement. We have modified the code example for your kind reference. Please do the same for RTF paragraphs. Hope this helps you.

Document document = new Document(MyDir + "ExampleMultiLineMergeField.docx");

String[] values = new String[]{"1.\tFirst line\n2.\tSecondline with is so long, that there will be inserted a new linebreak. Oh but no additional tabstopp. So bad....\n3.\t third line\n4.\tanother additional line\n\n\nOh no, there is another not formatted line which should not be indented."};
String[] fields = new String[]{"Field"};
 
document.getMailMerge().setFieldMergingCallback(new IFieldMergingCallback() {

    public void fieldMerging(FieldMergingArgs e) throws Exception {
        if (mBuilder == null)
            mBuilder = new DocumentBuilder(e.getDocument());

        if (e.getFieldName().equals("FIELD")) {
            mBuilder.moveToMergeField("FIELD", true, false);
            double hanging = mBuilder.getParagraphFormat().getFirstLineIndent();
            double leftindnt = e.getField().getStart().getParentParagraph().getParagraphFormat().getLeftIndent();
            System.out.println(leftindnt);
            String[] values = e.getFieldValue().toString().split("\n");

            for(String item : values)
            {
                if(item.contains("\t"))
                    mBuilder.getParagraphFormat().setFirstLineIndent(hanging);
                else {
                    mBuilder.getParagraphFormat().setLeftIndent(leftindnt - -hanging);
                    mBuilder.getParagraphFormat().setFirstLineIndent(0);
                }

                mBuilder.writeln(item);
            }
            e.setText("");
        }
    }

    public void imageFieldMerging(ImageFieldMergingArgs args) throws Exception {
        // Do nothing.
    }

    private DocumentBuilder mBuilder;
});
document.getMailMerge().execute(fields, values);

document.save(MyDir + "output.docx");

Hi Tahir,

thanks a lot for the example how to solve the problem. That should do it for our customer.

Cheers,

Jens Böckel

Hi Tahir,

there is a following problem. With your solution there is always an additional linebreak added to to written lines. Is there any possibility to remove this linebreak?

You can reproduce that with the given example, by adding any text straight behind the multiline mailmerge field.

Thanks a lot! Cheers,
Jens Böckel

@ns1045,

Thanks for your inquiry. Please use the following modified code example to remove the extra empty paragraph.

public void fieldMerging(FieldMergingArgs e) throws Exception {
    if (mBuilder == null)
        mBuilder = new DocumentBuilder(e.getDocument());

    if (e.getFieldName().equals("FIELD")) {
        mBuilder.moveToMergeField("FIELD", true, false);
        double hanging = mBuilder.getParagraphFormat().getFirstLineIndent();
        double leftindnt = e.getField().getStart().getParentParagraph().getParagraphFormat().getLeftIndent();

        String[] values = e.getFieldValue().toString().split("\n");

        for(String item : values)
        {
            if(item.contains("\t"))
                mBuilder.getParagraphFormat().setFirstLineIndent(hanging);
            else {
                mBuilder.getParagraphFormat().setLeftIndent(leftindnt - -hanging);
                mBuilder.getParagraphFormat().setFirstLineIndent(0);
            }

            mBuilder.writeln(item);
        }
        if(mBuilder.getCurrentParagraph().toString(SaveFormat.TEXT).trim().equals(""))
                mBuilder.getCurrentParagraph().remove();
        e.setText("");
    }
}

Thanks Tahir,

that works.

Cheers