Hi,
I have a document template that has a bunch of tables for repeating data (take the order example provided). One of the cells in the table needs to have RTF formatted text coming from the database (say the items description)
I have created a method for inserting RTF text in plain feilds (say for example, custom order details that is not in a TableStart/TableEnd structure, just a plain merge field). This works great. I was able to use an example on these forums that creates a new document with the RTF text and inserts it into the Word Doc.
What my problem is, when I do the document.mailmerge.executewithregions(mydatatable), it obviously inserts the RTF text (the actual string from the DB), so you have everything like {/rtf{ , etc.
How do I get around this? The end result should have a table with a couple of rows from the database, but the column that is RTF text be formatted correclty, or at least removing the RTF tags.
Jon
Hi
Thanks for your request. There is no direct way to insert RTF into the document. But you can achieve this using Aspose.Words. Please see the following forum thread:
The same technique you can use in MereFieldEventHandler.
https://reference.aspose.com/words/net/aspose.words.mailmerging/ifieldmergingcallback/
Hope this helps. Please let me know in case of any issues.
Best regards.
I used the first link to build up my insert RTF and this works great. Also, for another place in the document, im using MergeFieldEventHandlers.
What my issue is now, is setting the merge field to what I have here.
For an example, I have an order list. This is using the merge regions, and just going through an executewithregions. In this list, I have a field for tags (which could be 1 or more tags). Im using the mergefieldhandler to catch when it hits my tag field, and then use the orderid to find the tags for that order. These tags are placed into another document (in memory).
My problem now is how to set the tags merge field to the tags found in the matching document. Using the MergeFieldEventArgs, setting the .Text propterty should do what I would like it to do, but I can not easily save the contents of this document to the text property of the calling order.
Thank you for your help.
Jon
I have another example that may help to clear up what my issue is.
I have a list of items, with a name and description. The document itself has an overall description as well. The name is a string, the description is an RTF field. The list has 10 items it, and currently just handled by a Table:start and Table:end, with the item_name and item_description as merge fields inside of it.
The overall description is already handled using some of the samples before, using the Insert Document method. This works great.
I user the executeWithRegions to bind my table to the datatable. The issue now is that the item_description is RTF text, and if I just insert it, you get the RTF text (with all the RTF fields, like {rtf1/ansi/{).
I have a mergeventhandler for that field (if (e.DocumentFieldName.Equals(“item_description”))). This fires when it hits the field. But im confused on where to go next with converting the text from RTF into something I could use in the document. I would think I could create a document in memory and insert the RTF into that, but I am at a lost of how to then insert this document into my main document. The only option I seem to have is to set the Text value, which only wants a string, not another document.
Jon
Hello Jon!
Thank you for explanation.
RTF fragment cannot be inserted to a document directly, like it’s easily done with HTML. But you can create a separate document from that fragment as you succeeded.
The next arising question is how to insert a document or anything else but string value into Text property. But you can avoid assigning Text property and manipulate with node tree directly as it’s illustrated in the second article (provided by my colleague):
https://reference.aspose.com/words/net/aspose.words.mailmerging/ifieldmergingcallback/
Since you can insert a document at any node this can be a merge field in particular. To locate this merge field node knowing its name you can use DocumentBuilder class as shown in the article. DocumentBuilder has a cursor called CurrentNode:
https://reference.aspose.com/words/net/aspose.words/documentbuilder/currentnode/
It’s a child of a paragraph or a paragraph itself if the cursor points to an empty paragraph. In first case you should get parent from this node. Then you use InsertDocument from the referenced thread. This is the idea. Of course you should test where it is actually inserted and ensure service nodes that belong to the merge field itself are removed after the mail merge operation.
Please let me know whether I understand the problem and whether this works.
Regards,
This got me a bit closer. I now have copies of the documents that I would like to insert (as in, a Document object, with the RTF text converted). I tested this by saving all them, opening them in Word, and noticing that they were all ‘formatted’ RTF text.
I also updated my code to use a DocumentBuilder, and move to the current field ( I actually used MoveToMergeField(e.DocumentFieldName) from the MergeFieldEventHandler documentation). To see if this worked correctly, I used one of the DocumentBuilder.Insert methods, for example db.InsertLink. I had it generate a link, and this inserted just fine (in the right place, in the correct format, everything)
But after trying various ways on using the InsertDocument method, I still couldn’t get my documents to insert. My latest try was something like InsertDocument(db.currentnode.parentnode, rtfDocument), but this still doesn’t work.
Is there any way you could provide some sample code to explain how to insert a document into this node?
Hi
Thanks for your request. Please try using the following code:
public void Test058()
{
// Open document
Document doc = new Document(@"Test058\in.doc");
// Create dummy datasource
string[] names = { "myField" };
string[] values = { @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\fnil\fcharset2 Symbol;}}\b\fs24Bold text\b0\par plain text}" };
// Create MergeFild event handler
doc.MailMerge.MergeField += new MergeFieldEventHandler(MailMerge_InsertRtf);
// Execute mail merge
doc.MailMerge.Execute(names, values);
// Save outpur document
doc.Save(@"Test058\out.doc");
}
void MailMerge_InsertRtf(object sender, MergeFieldEventArgs e)
{
// Get Paragraph that contains mergefield
DocumentBuilder builder = new DocumentBuilder(e.Document);
builder.MoveToField(e.Field, true);
Paragraph parentParagraph = builder.CurrentParagraph;
// Get RTF string from field value
string rtfString = e.FieldValue.ToString();
// Get bytes from string, this is needed to create MemoryStream
byte[] rtfBytes = Encoding.UTF8.GetBytes(rtfString);
// Create memorystream
MemoryStream rtfStream = new MemoryStream(rtfBytes);
// Create document from stream
Document rtfDoc = new Document(rtfStream);
// Insert rtd document into destination document
InsertDocument(parentParagraph, rtfDoc);
// Set text of mergefield
e.Text = string.Empty;
}
Hope this helps.
Best regards.
Thank you so much, this worked. I think my code was not handling the ‘Paragraph parentParagraph = builder.CurrentParagraph’. Instead of using the paragrah, I was trying to use the current nodes parent node as the first argument in my InsertDocument call.
I ended up just using part of the botom code to be called in my handler already, and this worked like a charm.
Thank you again