Condtional template inside of merge region

Hello,


I would like to know if it is possible to change the output of elements within a merge region (TableStart->TableEnd) depending on the data passed. I have a use case where two types of objects can be sorted in the same list and should be outputted within the same merge region in the order they were sorted in the application.

Depend on the type of object I would like to switch the template during the mailmerge.

For example:

<TableStart:MyPojo>
If(typeof MyPojo == TypeA)
Template A
If(typeof MyPojo == TypeB)
Template B
<TableEnd:MyPojo>

Is it possible to interchange the template of a merge region during the mailmerge? I am using the IMailMergeDataSource interface to format my data.

Hi Bart,


Thanks for your inquiry. Mail merge with regions is used to dynamically grow portions inside the document. Please attach the following resources here for testing:

  1. Your input template Word document.
  2. The expected document when “MyPojo” is of type "TypeA"
  3. The expected document when “MyPojo” is of type "TypeB"

Please create these expected documents using Microsoft Word. We will investigate the scenario and provide you more information.

Best regards,

Hello,


I have attached a template and desired output. This does not work but this is how I would like it to be. If it’s not possible inside a template I am willing to do it through the API before the mailmerge happens or even during the mailmerge. Please just provide me with some insight in how I can accomplish this.

Thanks,

Bart

Hi Bart,


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

Best regards,

Hello,


Have you been able to take a look at my templates and perhaps a possible solution yet? I need to get this integrated before friday.

Thanks,

Bart

Hi Bart,


Thanks for being patient. Please find attached a couple of input/output Word documents, a simple database file and try running the following code to achieve what you’re looking for:
public class Program
{
public static void main(String[] args) throws Exception
{
URI exeDir = Program.class.getResource("").toURI();
String dataDir = new File(exeDir.resolve("…/…/Data")) + File.separator;
    DataSet ds <font color="BLUE">=</font> <font color="RED"><b>new</b></font> DataSet<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    createConnection<font color="BLUE"><b>(</b></font>dataDir<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    DataTable orders <font color="BLUE">=</font> <font color="RED"><b>new</b></font> DataTable<font color="BLUE"><b>(</b></font>executeQuery<font color="BLUE"><b>(</b></font><font color="PURPLE">"SELECT * from Orders"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>,</b></font> <font color="PURPLE">"Orders"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
    ds<font color="BLUE"><b>.</b></font>getTables<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>add<font color="BLUE"><b>(</b></font>orders<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    DataTable items <font color="BLUE">=</font> <font color="RED"><b>new</b></font> DataTable<font color="BLUE"><b>(</b></font>executeQuery<font color="BLUE"><b>(</b></font><font color="PURPLE">"SELECT * from Items"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>,</b></font> <font color="PURPLE">"Items"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
    ds<font color="BLUE"><b>.</b></font>getTables<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>add<font color="BLUE"><b>(</b></font>items<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    ds<font color="BLUE"><b>.</b></font>getRelations<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>add<font color="BLUE"><b>(</b></font><font color="RED"><b>new</b></font> DataRelation<font color="BLUE"><b>(</b></font>
            <font color="PURPLE">"OrdersItems"</font><font color="BLUE"><b>,</b></font>
            orders<font color="BLUE"><b>,</b></font>
            items<font color="BLUE"><b>,</b></font>
            <font color="RED"><b>new</b></font> String<font color="BLUE"><b>[</b></font><font color="BLUE"><b>]</b></font><font color="BLUE"><b>{</b></font><font color="PURPLE">"OrderID"</font><font color="BLUE"><b>}</b></font><font color="BLUE"><b>,</b></font>
            <font color="RED"><b>new</b></font> String<font color="BLUE"><b>[</b></font><font color="BLUE"><b>]</b></font><font color="BLUE"><b>{</b></font><font color="PURPLE">"OrderID"</font><font color="BLUE"><b>}</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    Document doc <font color="BLUE">=</font> <font color="RED"><b>new</b></font> Document<font color="BLUE"><b>(</b></font>dataDir <font color="BLUE">+</font> <font color="PURPLE">"input.docx"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    doc<font color="BLUE"><b>.</b></font>getMailMerge<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>setCleanupOptions<font color="BLUE"><b>(</b></font>MailMergeCleanupOptions<font color="BLUE"><b>.</b></font>REMOVE_UNUSED_REGIONS<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
    doc<font color="BLUE"><b>.</b></font>getMailMerge<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>executeWithRegions<font color="BLUE"><b>(</b></font>ds<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    doc<font color="BLUE"><b>.</b></font>save<font color="BLUE"><b>(</b></font>dataDir <font color="BLUE">+</font> <font color="PURPLE">"output.doc"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    assert doc<font color="BLUE"><b>.</b></font>getMailMerge<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>getFieldNames<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>length <font color="BLUE">=</font><font color="BLUE">=</font> <font color="BROWN">0</font> <font color="BLUE">:</font> <font color="PURPLE">"There was a problem with mail merge"</font><font color="BLUE"><b>;</b></font> <font color="GREEN"><i>//ExSkip

}

<font color="RED"><b>protected</b></font> <font color="RED"><b>static</b></font> ResultSet executeQuery<font color="BLUE"><b>(</b></font>String query<font color="BLUE"><b>)</b></font> <font color="RED"><b>throws</b></font> Exception
<font color="BLUE"><b>{</b></font>
    <font color="RED"><b>return</b></font> createStatement<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>.</b></font>executeQuery<font color="BLUE"><b>(</b></font>query<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
<font color="BLUE"><b>}</b></font>

<font color="RED"><b>public</b></font> <font color="RED"><b>static</b></font> <font color="RED"><b>void</b></font> createConnection<font color="BLUE"><b>(</b></font>String dataDir<font color="BLUE"><b>)</b></font> <font color="RED"><b>throws</b></font> Exception
<font color="BLUE"><b>{</b></font>
    Class<font color="BLUE"><b>.</b></font>forName<font color="BLUE"><b>(</b></font><font color="PURPLE">"sun.jdbc.odbc.JdbcOdbcDriver"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    File dataBase <font color="BLUE">=</font> <font color="RED"><b>new</b></font> File<font color="BLUE"><b>(</b></font>dataDir<font color="BLUE"><b>,</b></font> <font color="PURPLE">"DB.mdb"</font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>

    String connectionString <font color="BLUE">=</font> <font color="PURPLE">"jdbc:odbc:DRIVER={Microsoft Access Driver (*.mdb)};"</font> <font color="BLUE">+</font>
            <font color="PURPLE">"DBQ="</font> <font color="BLUE">+</font> dataBase <font color="BLUE">+</font> <font color="PURPLE">""</font><font color="BLUE"><b>;</b></font>

    mConnection <font color="BLUE">=</font> DriverManager<font color="BLUE"><b>.</b></font>getConnection<font color="BLUE"><b>(</b></font>connectionString<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
<font color="BLUE"><b>}</b></font>

<font color="RED"><b>private</b></font> <font color="RED"><b>static</b></font> Connection mConnection<font color="BLUE"><b>;</b></font>

<font color="RED"><b>public</b></font> <font color="RED"><b>static</b></font> Statement createStatement<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font> <font color="RED"><b>throws</b></font> Exception
<font color="BLUE"><b>{</b></font>
    <font color="RED"><b>return</b></font> mConnection<font color="BLUE"><b>.</b></font>createStatement<font color="BLUE"><b>(</b></font>ResultSet<font color="BLUE"><b>.</b></font>TYPE_SCROLL_INSENSITIVE<font color="BLUE"><b>,</b></font> ResultSet<font color="BLUE"><b>.</b></font>CONCUR_READ_ONLY<font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
<font color="BLUE"><b>}</b></font>

}

I hope, this helps.

Best regards,

This does not answer my question at all. I think you seem to be missing my point. I have one list/table/… which contains multiple types of classes. Depending on which class my current cursor is at inside of the TableStart I want to use a different template.


This is why I need to have the IF ELSE END IF syntax. I have searched through the forums and saw that mutiple people have already request this functionality.

I have already implemented a rough version of what I want to accomplish by inserting a nested if which outputs custom tags which I clean up after the mail merge.

I really think you should consider implementing the following syntax:
<TableStart:Pojo>
<>
… my template for x …
<>
… my template otherwise …
<>
<TableEnd:Pojo>

Hi Bart,


Thanks for the additional information. Please share your existing code (in running form); we will investigate the structure of your data source (list/datatable) and devise some solution to meet your requirement. Thanks for your cooperation.

Best regards,

Hi Bart,


Additionally, please find attached a modified version of your template document “template-modified.docx”, in this case, you just need to supply values for the “type” merge field from inside the class implementing the “IMailMergeDataSource”. I hope, this helps.

Best regards,

Thank you for your quick reply. The if with nested templates is not an option as we are developing a product which processes end-user templates with data from the application. It’s just too complicated for an end user to input that into his word file and does not provide a good overview of the template. I could write a pre processor which converts the client’s template to the nested if structure but I’m afraid I won’t be able to maintain the clients layout while doing so.


I have accomplished what I wanted to accomplish simply by cleaning up the IF structure after the mailmerge has done its thing. I will try to provide you with an example of it next week.

I do have another question though.

I am using an IFieldMergingCallback implementation to insert HTML into certain MergeFields. However, when I use the builder.insertHtml() the MergeField switches aren’t processed. When the MergeField has a \b “Text before field” it never gets added before the text inserted with builder.insertHtml(). I have tried to implement this myself and it worked, but I cannot preserve the \b formatting specified in the template.

Is this is a known issue? Can I somehow implement this myself? It’s very hard to get the FieldStart from the MergingArgs inside IFieldMergingCallback. Either when I insert something it never shows up in my template or the FieldSeperator can never be found.

Thanks

Hi Bart,


Thanks for the additional information. We are checking with this scenario and will get back to you soon.

Best regards,

Hi Bart,


Please find attached couple of sample input/output documents here with this post. The template has one parent region which contains multiple nested regions inside. Based on some value in parent region, you can programmatically switch nested templates and remove unused mergefields. The code to achieve this using Aspose.Words is also attached. I hope, this helps.
I hope, this helps.
Bart:
I am using an IFieldMergingCallback implementation to insert HTML into certain MergeFields. However, when I use the builder.insertHtml() the MergeField switches aren’t processed. When the MergeField has a \b “Text before field” it never gets added before the text inserted with builder.insertHtml(). I have tried to implement this myself and it worked, but I cannot preserve the \b formatting specified in the template.
Could you please attach your sample document, source code and output document showing the undesired behavior here for testing? We will investigate the issue on our end and provide you more information.

Best regards,

Hello,


Thank you for your additional feedback regarding this issue. Your example would indeed work but I have a specific use case in which multiple entities are sorted in the same datasource. So it’s critical to preserve the order of the different elements in the same list. That is why they need to be in the same datasource but can differ from template (Because they are different entities and might have sub-nested entities). I have already solved this particular issue so it is not that important anymore. However, I do believe you should consider implementing the expanded if structure. This would provide so much options to customize the output.

Concerning the mergefield before switch: As attachment the template that does not work and the source code I am using to insert the html into my template.

Bart

Hi,


Thanks for the additional information. The problem occurs because the DocumentBuilder.MoveToMergeField(String) method moves the cursor to a position just beyond the specified merge field and removes the merge field (including the \b switch). Please see the following changes in your code to workaround this issue:
public void fieldMerging(FieldMergingArgs args) throws Exception
{
if (StringUtils.startsWith(args.getFieldName(), “tekstvak”)
|| StringUtils.equals(args.getFieldName(), “inhoud”)
|| StringUtils.equals(args.getFieldName(), “geheimestemming”)
|| StringUtils.equals(args.getFieldName(), “bijlagenlijn”)
|| StringUtils.equals(args.getFieldName(),myHtmlField)
)
{
// Insert the text for this merge field as HTML data, using DocumentBuilder.
DocumentBuilder builder = new DocumentBuilder(args.getDocument());
builder.moveToMergeField(args.getDocumentFieldName(), true, false);
if (args.getFieldValue() != null && !StringUtils.isBlank(args.getFieldValue().toString()))
{
if (args.getField().getFieldCode().contains("\b")){
String textBefore = args.getField().getResult();
textBefore = textBefore.replace(args.getFieldName(), “”);
textBefore = textBefore.replace("«»", “”);
            builder<font color="BLUE"><b>.</b></font>insertHtml<font color="BLUE"><b>(</b></font>textBefore <font color="BLUE">+</font> <font color="BLUE"><b>(</b></font>String<font color="BLUE"><b>)</b></font> args<font color="BLUE"><b>.</b></font>getFieldValue<font color="BLUE"><b>(</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>)</b></font><font color="BLUE"><b>;</b></font>
        <font color="BLUE"><b>}</b></font></span>

        <font color="GREEN"><i>// The HTML text itself should not be inserted.

// We have already inserted it as an HTML.
args.setText("");
}

<font color="BLUE"><b>}</b></font>

}

I hope, this helps.

Best regards,