MailMergeWithRegions on an ILIST of items - Two column layout

Hi,

I have two queries on DOC to PDF conversion using Aspose.words,

  1. I have to make a two column layout in a page . Overflow on one column needs to continue in the next column on the page. The catch is that , data is in the form of an Ilist of object. Object consists of header and a value pair . Need to loop through the object -printing header first in bold and values next .

  2. How do we image merging dynamically from URL - URL subject to change on every request .

Thanks !

Hi,

I have two queries on DOC to PDF conversion using Aspose.words,

  1. I have to make a two column layout in a page . Overflow on one column needs to continue in the next column on the page. The catch is that , data is in the form of an Ilist of object. Object consists of header and a value pair . Need to loop through the object -printing header first in bold and values next .

  2. How do we implement image merging dynamically from URL - URL subject to change on every request .

Thanks !

Hi Imran,

Thanks for your inquiry.

*ImranShah:

  1. I have to make a two column layout in a page . Overflow on one column needs to continue in the next column on the page. The catch is that , data is in the form of an Ilist of object. Object consists of header and a value pair . Need to loop through the object -printing header first in bold and values next .*

In your case, I suggest you please use IMailMergeDataSource interface. Implement this interface to allow mail merge from a custom data source, such as a list of objects. You need to add two columns in your template document and use Next field to flow data from one column to other column. Please check the attach template document and following code example for your kind reference.

public void MailMergeCustomDataSource()
{
    // Create some data that we will use in the mail merge.
    CustomerList customers = new CustomerList();
    customers.Add(new Customer("Thomas Hardy", "120 Hanover Sq., London"));
    customers.Add(new Customer("Paolo Accorti", "Via Monte Bianco 34, Torino"));
    // Open the template document.
    Document doc = new Document(MyDir + "MailMerge.CustomDataSource.doc");
    // To be able to mail merge from your own data source, it must be wrapped
    // into an object that implements the IMailMergeDataSource interface.
    CustomerMailMergeDataSource customersDataSource = new CustomerMailMergeDataSource(customers);
    // Now you can pass your data source into Aspose.Words.
    doc.MailMerge.Execute(customersDataSource);
    doc.Save(MyDir + "MailMerge.CustomDataSource Out.doc");
}

/// 
/// An example of a "data entity" class in your application.
/// 
public class Customer
{
    public Customer(string aFullName, string anAddress)
    {
        mFullName = aFullName;
        mAddress = anAddress;
    }
    public string FullName
    {
        get { return mFullName; }
        set { mFullName = value; }
    }
    public string Address
    {
        get { return mAddress; }
        set { mAddress = value; }
    }
    private string mFullName;
    private string mAddress;
}

/// 
/// An example of a typed collection that contains your "data" objects.
/// 
public class CustomerList : ArrayList
{
    public new Customer this[int index]
    {
        get { return (Customer)base[index]; }
        set { base[index] = value; }
    }
}

/// 
/// A custom mail merge data source that you implement to allow Aspose.Words 
/// to mail merge data from your Customer objects into Microsoft Word documents.
/// 
public class CustomerMailMergeDataSource : IMailMergeDataSource
{
    public CustomerMailMergeDataSource(CustomerList customers)
    {
        mCustomers = customers;
        // When the data source is initialized, it must be positioned before the first record.
        mRecordIndex = -1;
    }

    /// 
    /// The name of the data source. Used by Aspose.Words only when executing mail merge with repeatable regions.
    /// 
    public string TableName
    {
        get { return "Customer"; }
    }

    /// 
    /// Aspose.Words calls this method to get a value for every data field.
    /// 
    public bool GetValue(string fieldName, out object fieldValue)
    {
        switch (fieldName)
        {
            case "FullName":
                fieldValue = mCustomers[mRecordIndex].FullName;
                return true;
            case "Address":
                fieldValue = mCustomers[mRecordIndex].Address;
                return true;
            default:
                // A field with this name was not found, 
                // return false to the Aspose.Words mail merge engine.
                fieldValue = null;
                return false;
        }
    }

    /// 
    /// A standard implementation for moving to a next record in a collection.
    /// 
    public bool MoveNext()
    {
        if (!IsEof)
            mRecordIndex++;
        return (!IsEof);
    }

    public IMailMergeDataSource GetChildDataSource(string tableName)
    {
        return null;
    }

    private bool IsEof
    {
        get { return (mRecordIndex >= mCustomers.Count); }
    }

    private readonly CustomerList mCustomers;
    private int mRecordIndex;
}

ImranShah:
2. How do we implement image merging dynamically from URL - URL subject to change on every request .

Please use DocumentBuilder.InsertImage method to inserts an image from a file or URL into the document. The image is inserted inline and at 100% scale. To be able to insert images via Merge Fields, you first need to configure mergefield’s name according to the following syntax in your template document:

Image:MyFieldName

Secondly, you can simply use the following code snippet to insert images during mail merge via DocumntBuilder:

// Create array with field names and array with field values
string[] names = { "MyFieldName" };
object[] values = { "http://www.aspose.com/images/aspose-logo.gif" };
// Open template
Document doc = new Document(MyDir + "in.docx");
doc.MailMerge.Execute(names, values);
doc.Save(MyDir + "Out.doc");

Hope this answers your query. Please let us know if you have any more queries.

Hi Tahir - Thanks for your response. We looked at the template doc attached and it looks like you have repeated the columns ‘n’ times in the template.

«NEXT»«FullName»

«Address»

But we dont know how many times the combination is going to repeat. So is there anyway to load it dynamically, instead of repeating it certain number of times in the template directly?

Hi Tahir - On the image solution, it works fine if am referring the local image path. But does not work well when am referring to any server image path. I only get "The remote name could not be resolved: " error for any server path I use, including the one you had mentioned in your example. any specific settings to be used?

Hi Imran,

Thanks for sharing the more details. You can achieve your requirements by using mail merge with regions. Please use the MailMerge.ExecuteWithRegions method as shown in following code snippet with attached template. I have modified the template document as follow:

«TableStart:Customer»
«FullName»
«Address»
«TableEnd:Customer»

Please read following documentation links for your kind reference.
https://docs.aspose.com/words/net/types-of-mail-merge-operations/
https://docs.aspose.com/words/java/types-of-mail-merge-operations/

Regarding image query, please make sure that you can access image via browser. Please let us know if you have any more queries.

// Create some data that we will use in the mail merge.
CustomerList customers = new CustomerList();
for (int i = 0; i < 100; i++)
{
    customers.Add(new Customer("Thomas Hardy", "120 Hanover Sq., London"));
    customers.Add(new Customer("Paolo Accorti", "Via Monte Bianco 34, Torino"));
}
// Open the template document.
Document doc = new Document(MyDir + "MailMerge.CustomDataSource_2.doc");
// To be able to mail merge from your own data source, it must be wrapped
// into an object that implements the IMailMergeDataSource interface.
CustomerMailMergeDataSource customersDataSource = new CustomerMailMergeDataSource(customers);
// Now you can pass your data source into Aspose.Words.
doc.MailMerge.ExecuteWithRegions(customersDataSource);
doc.Save(MyDir + "MailMerge.CustomDataSource Out.doc");

Hi Tahir - Thanks for the reply. We figured out that the image issue was due to firewall. And we also fixed the other issue of multi column as well.

We have run into another problem now. We have a template with background image. When the text overflows, it creates a new page, but the text starts at the page start, hence it writes over some of the background image. Is there any way to detect page overflow? From whatever we read, it does not look like we can. We basically want to detect page overflow, so that we can make that text start at a different position in the page and also add a different text to indicate page continuation.

Pls let us know if you need more details. Thanks for your help.

Hi Imran,

Thanks for your inquiry. Word document is flow document and does not contain any information about its layout into lines and pages. Therefore, technically there is no “Page” concept in Word document. Pages are created by Microsoft Word on the fly.
Aspose.Words uses our own Rendering Engine to layout documents into pages. Please check using the DocumentLayoutHelper sample from the offline samples pack. This sample demonstrates how to easily work with the layout elements of a document and access the pages, lines, spans etc.

You can get the page number of a Node by using LayoutCollector.GetStartPageIndex method. Please read about Aspose.Words.Layout namespace from here:
https://reference.aspose.com/words/net/aspose.words.layout/

Hope this answers your query. Please let us know if you have any more queries.