Blogs

Rachel Reese - DevExpress Scheduler & RichEdit Blog

DevExpress XtraRichEdit - Master-Detail Mail Merge (available now in v2011, volume 1)

     

You now have more mail merge options than ever! We're enhancing our mail merge functionality in RichEdit to include support for nested master-detail merge operations.

Remember the new DOCVARIABLE fields that we're adding? Well, they're like the MERGEFIELD but you don't need to bind them to a datasource, instead, you calculate their value at runtime. If we combine these with the RichEditDocumentServer, which allows you to access the functionality of the RichEdit control via the API, you can perform a master-detail merge. This is huge! You can create catalogs, header/detail invoices, or even statements!

It works similarly to a basic mail merge. First, you need the templates. For this example, let's create a sheet of customers and orders. First, you would set up the main mail merge template in this manner:

image

with a master template for the orders like this:

image

and a detail template to describe the products in each category, as follows:

image

In the master template, the document variable takes a merge field as a parameters. When you update the master fields during the merge, the CalculateDocumentVariables event is raised, which will allow you to calculate and display the nested variables for each section. Let's go through this bit by bit. :)

First, I added a Merge button to the ribbon, and in the ItemClick event for it, I set the mail merge datasource, make sure to wire up the Calculate Document Variables event, and then merge the original template (reTemplate) and display it in the reResultingDoc RichEditControl.

private void mergebutton_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
    reTemplate.Options.MailMerge.DataSource = GetDocument();

    reResultingDoc.CalculateDocumentVariable += reResultingDoc_CalculateDocumentVariable;
    reTemplate.MailMerge(reResultingDoc.Document);

}

This next step loads all the customers into the template. When the mail merge begins, the document variables event is triggered to calculate the "Customers" DOCVARIABLE. Here, we create an instance of the RichEditDocumentServer, and wire the document server's CalculuateDocumentVariables event to a new method for it. We're using the Customer template for the "master", so we set the datasource for this template, and perform a mail merge into the just created document server. 

void reResultingDoc_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e) {
    if (String.Equals(e.VariableName, "Customers")) {

	reCustomer.Options.MailMerge.DataSource = GetCustomers();
	
	RichEditDocumentServer docserver = new RichEditDocumentServer();
        docserver.CalculateDocumentVariable += docserver_CalculateDocumentVariable;

        reCustomer.MailMerge(docserver);

        e.Value = docserver;
        e.Handled = true;

    }
}

Now, we still need to load the orders, so we repeat the steps: create an instance of the RichEditDocumentServer, set the datasource for the template to use (in this case, the Order template), and mail merge from the RichEditControl which contains the template, into the RichEditDocumentServer that we've just created.

void docserver_CalculateDocumentVariable(object sender, CalculateDocumentVariableEventArgs e) {
    if (String.Equals(e.VariableName, "Orders")) {
        if (e.Arguments.Count > 0) {
            RichEditDocumentServer docserverOrders = new RichEditDocumentServer();

            reOrder.Options.MailMerge.DataSource = GetOrders(e.Arguments[0].Value);
            reOrder.MailMerge(docserverOrders);

            e.Value = docserverOrders;
            e.Handled = true;
        }
    }
} 

And, our output file:

image

I can't wait to see what you guys do with this! I know I've been asked about it a bunch of times, and I'm sure you're all pretty excited to see it. :D

For more information, check out the master-detail merge demo in our demo center – it's in the Beta!

Published May 27 2011, 07:54 AM by Rachel Reese (DevExpress)
Bookmark and Share

Comments

 

Sigurd Decroos said:

A bit more 'complicated' than I hoped for, but it'll do what I want :). Great!

Perhaps you could make an example where the detail is shown in a table with left/right alignment and for numbers a specific format. I'm sure your customers would find it very helpfull.

May 27, 2011 12:59 PM
 

Rachel Reese (DevExpress) said:

Sigurd -- that is a fabulous idea. Thanks! :)

May 27, 2011 6:48 PM
 

Michael Proctor [DX-Squad] said:

Interesting... agree with Sigurd, it seems a little daunting for end users, but the "end result" is definately what I am after.

I wonder what the risks are of using a table here. Because each line will actually be a complete table and not a row. Therefore if the "end user" went to resize a column in the "merge" document they will only resize for that line, they would have to go back into the Detail template and change it there then re-merge to see the result.

Not sure how much this would affect screen readers or say the end user selecting the "tables" and copy-paste into excel.

It might all work, just thought I would throw it out there.

With the announcement about a Table API which I was very happy to hear about, I might still see if I can use a DOCVARIABLE as a place holder for me to "insert" a table and populate it with the rows.

May 27, 2011 7:45 PM
 

Sigurd Decroos said:

Rachel: I got your mail, I'll answer ASAP :).

I have 1 more idea... The 'out of the box' arrangement of the buttons in the Ribbon. It simply sucks! Start Word and look how the paragrapgh alignment buttons are placed close to each other. Things like 'bold', 'italic', ... are grouped as are 'font' and 'font size'. You can achieve the same with the Ribbon of DevExpress, but it requires a bit of work. I'm sure the developers can fix this quite easily and the arrangement for the end-user would look a lot better and easier. What do you think?

May 27, 2011 9:31 PM
 

Sigurd Decroos said:

Michael: I was kinda hoping DX would realise this shortcoming while making the mentioned example :D. The detail-mailmerge should add rows to the table. That's the only proper way that the table can have 1 (column)-header and a nice footer instead of a header and footer line per detail record...

May 27, 2011 9:33 PM
 

Rachel Reese (DevExpress) said:

Michael, Sigurd -- Actually, the way it works is that the detail rows will be added to one table, as long as the detail template doesn't have any other content in it. Check the Master-Detail demo in the beta. :)

May 28, 2011 3:07 PM
 

Michael Proctor [DX-Squad] said:

.... OMG .... I C I C, I just played with the Master-Detail in the Demo, I see it but don't believe it. Bloody clever dev's :D

Spot on, have copy and pasted, also saved it as a doc to verify and indeed everytime it is recognised as a single table.

GREAT WORK. I can now realise a feature in my app that will make my customers so happy it isn't funny.

Two big thumbs up guys

May 29, 2011 5:48 AM
 

Michael Proctor [DX-Squad] said:

P.S In the future I will not jump the gun and assume what the output is

May 29, 2011 5:49 AM
 

John Botibol said:

Rachel, this is truly fantastic. As you know, once you launch something like this we all want more :-) so a question for you. Is it possible to perform more than one "master-detail" merge in one document. Lets say you had a course booking object containing the delegate, a list of courses booked and the Invoice (which has several lines). Could you create a single merged document with a master-detail for the courses and another for the Invoice lines?

May 29, 2011 6:00 AM
 

Rachel Reese (DevExpress) said:

Michael -- Yay!! :D And no worries at all, I didn't explain the whole tables thing to begin with. :-)

John -- Totally! You could have two docvariables in the main mail merge template -- where I have just the customers, you'd have one for courses, and one for the invoice -- then, in the mergebutton_itemclick, just add an if statement to see which you're calculating, and then fill them both separately. Make sense?

May 29, 2011 12:30 PM
 

Ajay Bal 1 said:

That is great way to implement master detail. Can I stretch more

------------------------------------------------------------------

Item      | 25/5  | 26/5  | 28/5

------------------------------------------------------------------

Item A   | 15     |  0     |   22

Item B   | 12     |  16   |   5  

------------------------------------------------------------------

where date in the column headings is Variable and the Detail contains Item Name and Quantity purchased on those dates

Is it possible to do as Master Detail Mail merge and how ?

May 31, 2011 7:14 AM
 

Garry Lowther said:

This looks excellent Rachel. I look forward to creating contract documentation containing multiple lines for each pay/charge rate and also invoices with multiple lines for each product/services.

May 31, 2011 7:17 AM
 

Rachel Reese (DevExpress) said:

Ajay -- I'm pretty sure you can do it, but without knowing how your data is structured I wouldn't be able to tell you the best way to go about it. Once you've played around with it, if you're having trouble, I'd contact our support. I'll bet they'll be able to help you get it working. Good luck!

Garry -- Great! :)

May 31, 2011 1:52 PM
 

Ajay Bal 1 said:

Thanks for the instant response.

My data is in a simple IList (Orders) of Order Class

Order Class contains three properties - OrderDate, ItemName and QtyPurchased.

Example list is

Orders.add (New Order With {OrderDate = 25/5/2011, ItemName = Item A, Qty = 15} )

Orders.add (New Order With {OrderDate = 26/5/2011, ItemName = Item A, Qty = 0} )

Orders.add (New Order With {OrderDate = 28/5/2011, ItemName = Item A, Qty = 22} )

Orders.add (New Order With {OrderDate = 25/5/2011, ItemName = Item B, Qty = 12} )

Orders.add (New Order With {OrderDate = 26/5/2011, ItemName = Item B, Qty = 16} )

Orders.add (New Order With {OrderDate = 28/5/2011, ItemName = Item B, Qty = 5} )

Thanks

June 3, 2011 7:24 AM
More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.