IMailMergeDataSource with Sections

Hi there,

I am a complete beginner using aspose.word with Java and I am currently evaluating the product to check if it does suit our needs. So excuse me if my questions sounds silly.

I am trying to find out how to work with IMailMergeDataSource classes and Sections.

The scenario is as follows: We have one word template which contains our layout. It contains a number of fields as well as a number of nested tables. I created a bunch of IMailMergeDataSourcestyle objects with getValue and getChildDataSource methods. All works reasonably well and the final report does contain all we need nicely. It just so happens that we allow the user during runtime to change the order of paragraphs in the document, independent or their order in the wordfile. How can I achieve this?

I assumed that I should use Sections, but my Document does only contain one single Section.

Any suggestions would be appreciated.

Hi Thierry,

Thanks for your inquiry.

Thierry:
It just so happens that we allow the user during runtime to change the order of paragraphs in the document, independent or their order in the wordfile.

You can work with paragraph nodes while doing mail merge by implementing IMailMergeDataSource interface.Please read following documentation link for your kind reference.
https://docs.aspose.com/words/java/using-documentbuilder-to-modify-a-document/

It would be great if you please share some more information about your query (order of paragraphs). Please manually create your expected Word document using Microsoft Word and attach it here along with input template for our reference. We will investigate that how you want your final Word output be generated like. We will then provide you more information on this along with code.

Thierry:
I assumed that I should use Sections, but my Document does only contain one single Section.
Please note that the TableStart and TableEnd fields must be inside the same section in the document.

Hi there, and thanks for your prompt reply.

Thank you for the link to the documentation, but it did not really give me a solution to my problem. Anyway, as it turns out, I completely misunderstood the concept of “Sections” in my word template.

I will try to explain my problem a bit more in detail. I attached a simplified version of our template containing the information below:

«TableStart:Root»
Report
«TableStart:ReportInformation»
Author
«author» 
Report date
«reportDate»
Prediction date
«predictionDate»
Program version
«programVersion»
Compound name
«compoundName»
Species
«species»
«TableEnd:ReportInformation»

«TableEnd:Root»

Essentially I would like to be able to determine the order of items given in the ReportInformation» table (for
example: give the Report date before giving the Author) without editing
the template beforehand. So in the code, my items have an order, which can be different each time the report is produced.

So in short, I am wondering how I could exchange:
Author
«author»
with:
Report date
«reportDate»

Hi Thierry,

Thanks for your inquiry. In this case, you first need to modify the document’s contents (Text + Mail Merge Field) and then do the mail merge operation. The article ‘Find and Replace Overview’ sounds like exactly what you want.

I am working over your query and will share the code asap.

Hi Thierry,

Please use the following code snippet to achieve your requirements. The following code snippet exchange text “Author” and “Report date” and exchange specific mail merge fields. Hope this helps you. Please let us know if you have any more queries.

Document doc = new Document(MyDir + "Template.docx");
DocumentBuilder builder = new DocumentBuilder(doc);
// Swap fields 
SwapFields("author", "reportDate", builder);
// Do mail merge
doc.MailMerge.ExecuteWithRegions(....);
doc.Save(MyDir + "out.docx");
private Field GetField(string fieldname, DocumentBuilder builder)
{
    builder.MoveToMergeField(fieldname, false, false);
    FieldStart startField = (FieldStart)builder.CurrentNode;
    // Retrieve the facade object which represents the field in the document.
    return startField.GetField();
}
private void SwapFields(string firstfield, string secondfield, DocumentBuilder builder)
{
    // get first field 
    Field field1 = GetField(firstfield, builder);
    // get second field 
    Field field2 = GetField(secondfield, builder);
    // get the field code 
    string fieldcode1 = field1.GetFieldCode();
    // get the field code 
    string fieldcode2 = field2.GetFieldCode();
    // Replace text Author with Report date
    Paragraph authorPara = (Paragraph)field1.Start.ParentParagraph.PreviousSibling;
    authorPara.RemoveAllChildren();
    authorPara.AppendChild(new Run(builder.Document, "Report date"));
    Paragraph reportdataPara = (Paragraph)field2.Start.ParentParagraph.PreviousSibling;
    reportdataPara.RemoveAllChildren();
    reportdataPara.AppendChild(new Run(builder.Document, "Author"));
    // Swap fields
    builder.MoveToMergeField(secondfield, false, false);
    builder.InsertField(fieldcode1);
    field2.Remove();
    builder.MoveToMergeField(firstfield, false, false);
    builder.InsertField(fieldcode2);
    field1.Remove();
}

Thank you very much for that code, I think that is exactly what I was looking for.
I forgot to mention however that I am actually using java (sorry for that), and the FieldStart class in Java does not have a .getField() method. I managed to convert everything else into java.

How do I get the Field in java?

Hi Thierry,

Thanks for your inquiry. Perhaps, you are using an older version of Aspose.Words. I would suggest you please upgrade to the latest version of Aspose.Words i.e. v13.2.0. The FieldStart class contains the getField() method, please use the following GetField method in your code. Unfortunately, it is not updated in documentation. We will update the documentation soon.

private Field GetField(String fieldname, DocumentBuilder builder) throws Exception
{
    builder.moveToMergeField(fieldname, false, false);
    FieldStart startField = (FieldStart)builder.getCurrentNode();
    // Retrieve the facade object which represents the field in the document.
    return startField.getField();
}

Hi Tahir,

Yes, that did the trick. Changed to the new version and now it works perfectly.

Thank you very much for your answers.

Hi Thierry,

Thanks for your feedback. Please feel free to ask if you have any question about Aspose.Words, we will be happy to help you.