Problem with mail merge repeating entire document body N times - Help me

Good evening,

I’m having a problem with mail merge.

Introduction:

I’m using version 22.12, and the same problem occurs when trying the online mail merge from the Aspose website, where, I assume, the latest version is available.

Problem:

A case where the mail merge of a document composed of a single table, in addition to populating the table by adding rows for each set of values ​​in the XML, also repeats the entire body of the document N times (equal to the number of rows generated).

I found this in the Aspose documentation:

https://docs.aspose.com/words/net/types-of-mail-merge-operations
“SimpleMailMerge operation … The main limitation of using this type is the whole document content will be repeated for each record in the data source.”

I don’t know if this could be the cause, and if so, what solution can I adopt?

For now, I’ve solved the problem by simply adding an extra node to the XML at the same level as the table (<EXTREMELY_SAFE_TAG>IAM_SAFE</EXTREMELY_SAFE_TAG>).

I’m attaching the template input files, the metadata (I’m attaching the docx to convert to xml because it won’t let me attach the xml directly), and the resulting output.

demo.docx (812,9 KB)

dati.docx (13,6 KB)

Result_demo.docx (418,6 KB)

result obtained from the online mail merge:

demoMerged.docx (379,3 KB)

Below is the code used for the mail merge:

public void stampaUnione(final File mergedFile, final File metadatiFile, final File img, 
                             final boolean cancellaCampi) throws Exception {
        
        //Leggo la sorgente dati da un file xml e ne creo un DataSet
        final DataSet dataSet = new DataSet();
        dataSet.readXml(metadatiFile.getAbsolutePath());

        // Apro il documento template
        final MailMerge mm = this.doc.getMailMerge();

        // imposto pulizia campi non usati
        if (cancellaCampi) {
            mm.setCleanupOptions(
                    // rimozione regioni non compilate
                    MailMergeCleanupOptions.REMOVE_UNUSED_REGIONS
                    // rimozione campi non compilati
                    | MailMergeCleanupOptions.REMOVE_UNUSED_FIELDS
                    // rimozione campi innestati
                    | MailMergeCleanupOptions.REMOVE_CONTAINING_FIELDS
            );
        }
        

        //Callback per il merge di un'immagine, se passata come input
        if (img != null) {
            mm.setFieldMergingCallback(new HandleMergeImageField(img));
        }

        //Eseguo prima la chiamata ad un execute per le regioni
        mm.executeWithRegions(dataSet);

        //Seccessivamente eseguo la execute per i campi fuori regione
        //Nota: Si assume che a livello 0 ci sia un elemento tag contenitore
        mm.execute(dataSet.getTables().get(0));

        if (cancellaCampi) {
            mm.deleteFields();
        }
        
        this.doc.save(mergedFile.getAbsolutePath());     
    }

As mentioned in the introduction, I also checked the online version of Aspose, and even there (despite not replacing the mail merge tags) it generates the body N times.

Can you help me understand the cause and possibly find a solution?

Thank you.

@L1b3r0 The behavior is expected. In your data source there is only one table with the following fields:

  • Valuta
  • Quantita
  • Destinatario

Which are defined in the region in your template and are properly filled with data by executeWithRegions.
The fields that should be filled outside the region, i.e. Note, Indirizzo and Contatto, should be filled with execute method, but the data passed to execute method does not have these fields. To properly resolve the problem you should define another table in the data set with required fields. Foe example see the following modified XML:

<root>
	<header>
		<Note>This is Note</Note>
		<Indirizzo>This is Indirizzo</Indirizzo>
		<Contatto>This is Contatto</Contatto>
	</header>	
	<Pagamenti>
		<Valuta>euro</Valuta>
		<Quantita>0.5</Quantita>
		<Destinatario>Tanaka</Destinatario>
	</Pagamenti>
	<Pagamenti>
		<Valuta>euro</Valuta>
		<Quantita>0.5</Quantita>
		<Destinatario>Tanaka</Destinatario>
	</Pagamenti>
	<Pagamenti>
		<Valuta>euro</Valuta>
		<Quantita>0.5</Quantita>
		<Destinatario>Tanaka</Destinatario>
	</Pagamenti>
</root>

As you ca see there are two table now - header and Pagamenti
Now, you can use the following code:

DataSet dataSet = new DataSet();
dataSet.readXml("C:\\Temp\\data.xml");
    
Document doc = new Document("C:\\Temp\\in.docx");
MailMerge mm = doc.getMailMerge();
    
mm.executeWithRegions(dataSet);
mm.execute(dataSet.getTables().get("header"));
    
doc.save("C:\\Temp\\out.docx");

Thanks,
I hadn’t noticed that some information was missing from the data file.
I inserted the missing tags, and my code worked even without enclosing “Contacts,” “Notes,” and “Address” in the “header” tag.
I just wanted to clarify one thing: why is it necessary to make a double “execute” and “executeWithRegion” call to handle models containing a “mix” of regions and non-regions? Can’t I do it with a single call?

I also wanted to ask if there’s a way to tell if a template has only regions or no regions so I can avoid calling execute if it’s not necessary.

By passing it this model

demoBis.docx (14,0 KB)

and this data

dati.docx (13,3 KB)

result:

resutlDemoBis.docx (52,9 KB)

for example, I get the repeated body, this is because I should avoid the call to “execute”, but I don’t understand if there is a way to do it?

Thanks

@L1b3r0 It looks like you are looking for nested mail merge with regions. Please see our documentation for more information:
https://docs.aspose.com/words/java/nested-mail-merge-with-regions/

Hi,

Yes, in my example I have a union with regions.
The problem is that the “cascading” call:

 ...
   //Eseguo prima la chiamata ad un execute per le regioni
    mm.executeWithRegions(dataSet);

    //Seccessivamente eseguo la execute per i campi fuori regione
    //Nota: Si assume che a livello 0 ci sia un elemento tag contenitore
    mm.execute(dataSet.getTables().get(0));
 ...

generates, if there is no data outside the region, the document body repetition.

Therefore, I want to avoid calling the execution if it’s not necessary.
Is there a way to do this? I haven’t found anything related in the documentation.

I saw something that might work for me in this post:

https://forum.aspose.com/t/mixed-usage-of-mailmerge-execute-and-mailmerge-executewithregions/69169/5

But, in my case, it didn’t work.

@L1b3r0 This is exactly what mail merge with nested regions does. In your data source there can be root data source with some records and child data sources associated with records in the root data source. In this case when mail merge with regions is executed both outer and inner regions are filled with data.

Here is a code and template examples that demonstrates the basic technique.

DataSet pizzaDs = new DataSet();
pizzaDs.readXml("C:\\Temp\\data.xml");
    
Document doc = new Document("C:\\Temp\\in.docx");
doc.getMailMerge().executeWithRegions(pizzaDs);
doc.save("C:\\Temp\\out.docx");

data.zip (568 Bytes)
in.docx (58.3 KB)
out.docx (52.9 KB)

Thanks, now I understand. All I had to do was modify my data model and template, and it “magically” worked.

1 Like