Per the documentation and postings, IMailMergeDataSource is to be used when creating a custom data source which gives us the ultimate flexibility in generating data for the mail merge. The examples we have seen (and also used as a basis for our implementation) has the implementation of the interface incrementing the current record pointer for each call to the moveNext method. A few questions:
Under what conditions should the moveNext method throw the Exception?
When should, if ever, the current record index be reset back to the first record? We would see this perhaps when you have the same table region being used more than once in the same template/word document.
Is it a fundamental assumption by the Aspose API that the getDataSource method of the IMailMergeDataSourceRoot presents a “new” instance of the data source object with the current record point reset to the beginning?
How we are using this:
Implementing IMailMergeDataSourceRoot that returns the implemented IMailMergeDataSource for the given table name
Using executeWithRegions(IMailMergeDataSourceRoot) call for the merge
Can provide more details if that helps the conversation.
Thanks for your interest in Aspose.Words. When a data source is created, it should be initialized to point to BOF (before the first record). The Aspose.Words mail merge engine will invoke MoveNext to advance to next record and then invoke GetValue for every merge field it encounters in the document or the current mail merge region.
*Martin:
Under what conditions should the moveNext method throw the Exception?*
It is unlikely to throw exception, it returns True if moved to next record successfully and False if reached end of the data source.
Martin:
2) When should, if ever, the current record index be reset back to the first record? We would see this perhaps when you have the same table region being used more than once in the same template/word document.
You can use MailMerge.MergeDuplicateRegions property to set a value indicating whether all of the document mail merge regions with the name of a data source should be merged while executing of a mail merge with regions against the data source or just the first one. But, its usage may cause performance decrease
Martin:
3) Is it a fundamental assumption by the Aspose API that the getDataSource method of the IMailMergeDataSourceRoot presents a “new” instance of the data source object with the current record point reset to the beginning?
Generally, yes. When the Aspose.Words mail merge engines populates a document with data and encounters MERGEFIELD TableStart:TableName, it invokes GetDataSource on this object. Your implementation needs to return a new data source object. Aspose.Words will use the returned data source to populate the mail merge region. If a data source (table) with the specified name does not exist, your implementation should return null.
Thank you for the reply. There appears to be a slight disconnect in the way the IMailMergeDataSource is being used based on the following observations (using the executeWithRegions call):
If the data source is passed to executeWithRegions, then all instances in the document where the region is used are correctly merged.
If the data source is instead provisioned by IMailMergeDataSourceRoot and the executeWithRegions is performed with the root object as the parameter, then only the first instance of the region where the data source is used is correctly merged (the other subsequent instances are left un-merged)
In both cases, the underlying code that implements IMailMergeDataSource is identical. The key difference appears to be that when IMailMergeDataSourceRoot is being used that each data source is used X number of times (once for each time the region appears in the document) vs. a data source being used only once. So assuming this is a correct observation, then a few remaining questions:
Why the disparity in how the data source is used?
One of the key rules of implementing IMailMergeDataSourceRoot, based on the previous reply, is that the getDataSource must guarantee the returned data source has its record pointer at the beginning of the record set, correct?
Thanks for your inquiry. Please see the following point from documentation:
Duplicate regions with the same name are allowed. To allow merging of duplicate regions set MailMerge.MergeDuplicateRegions property to true. For backward compatibility reasons if you are merging using a IMailMergeDataSourceRoot or a DataSet datasource then duplicate regions will be merged automatically regardless of the value of the MailMerge.MergeDuplicateRegions option.
Could you please attach your template document and complete source code here for testing? We will investigate the issue further on our end and provide you more information.
I believe that we have implemented the code per the documentation. Attached to this posting is the source code as well as the template. It will reproduce behavior as I have described it.
Thanks for your inquiry. I tested the scenario and have managed to reproduce the same problem on my side. For the sake of correction, I have logged this problem in our issue tracking system as WORDSNET-10608. Our development team will further look into the details of this problem and we will keep you updated on the status of correction. We apologize for your inconvenience.
Thanks for your inquiry. Unfortunately, this issue is not resolved yet. Our development team has completed the analysis of this issue. We will inform you via this thread as soon as this issue is resolved. We apologize for any inconvenience.
Regarding WORDSNET-10608, our development team has completed the work on your issue and has come to a conclusion that they won’t be able to implement the fix to your issue. Your issue (WORDSNET-10608) is now closed with ‘Won’t Fix’ resolution.
Aspose.Words uses different behaviour for mail merge for IMailMergeDataSource and IMailMergeDataSourceRoot.
IMailMergeDataSource:
Aspose.Words internally decorates data source with resettable data source to process duplicated regions if needed.
IMailMergeDataSourceRoot:
Aspose.Words invokes the IMailMergeDataSourceRoot.GetDataSource method for each region regardless region’s duplication.
This difference is by design.
So, you should rework code to make the IMailMergeDataSourceRoot.GetDataSource method returns data source in initial state. For example, with following code snippets.
Extend the MailMergeDS class:
public void reset() {
currentRecord = 0;
}
Invoke the MailMergeDS.reset method in the MailMergeDS.getDataSource method:
@Override
public MailMergeDS getDataSource(String name) throws Exception {
MailMergeDS ds = sources.get(name);
ds.reset();
return ds;
}
This thread really helped us resolving the problem of using an IMailMergeDataSource multiple times.
As you already indicated in one of the post above the documentation clearly indicates the following: For backward compatibility reasons if you are
merging using a IMailMergeDataSourceRoot or a DataSet datasource then
duplicate regions will be merged automatically regardless of the value
of the MailMerge.MergeDuplicateRegions option.
It would be good to mention in that place that a reset of the resource is needed.
The above example where the currentRecord is put to 0 is not working, when doing that you are in fact loosing the first record. It should be set to -1:
// When the data source is initialised, it must be positioned before the first record.
mRecordIndex = -1;
Thanks for your suggestions. We have logged your comment in our issue tracking system against WORDSNET-10608 and will update you of any further responses that we may receive from our product team.