Thanks for the sample code… My code is in VB so I had to convert it. I get no errors, however no data at all is saved into the template… Does the conversion look correct to you? I feel something in the handler may have gotten converted wrong.
Sorry, I found my issue. Was missing the TableName definition…
One thing I noticed is my merge fields in the header section of my document are not getting updated now. Do I have to create another Region area for handle that portion of the document?
Hi
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Thanks for your inquiry.
1. Yes, “Data” in your case is name of region in the document. Regions is part of document between “TableStart:XXX” and “TableEnd:XXX” merge fields, where XXX is name of region.
2. No, you do not need to create a separate region. Just execute simple mail merge after execution Mail Merge With Regions.
Best regards,
I get over 8000 page document when I add the normal mail merge info after the regions code…
Hi
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Thank you for additional information. Actually you do not need to execute simple mail merge with the same data source. As I remember in the header you have only few merge fields. So you need to select data for these merge fields into a separate data source (with only one data row) and execute simple mail merge with this data source.
Best regards.
Got it… Thanks!
I’ve got another request. I now have my document created successfully. My users would like for the a table of contents to be inserted. They simply want the page number where each company is located at for quick reference. How would something like this be accomplished?
It seems maybe a Table of Contents could solve this for me? I dont know how the table of contents should work though with the merge fields. I would like To have each Company name listed along with the page number…
Hi
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Thanks for your inquiry. I think the best way to achieve what you need it building TOC using TOC entries. You can insert TOC entries (TC fields) from the code during executing mail merge.
The only one thing you need to change in your template is inserting TOC field like the following:
{ TOC \f \h }
Here is the modified code:
// Get data.
string connectionsString = @"Driver={Microsoft Excel Driver (*.xls)};DriverId=790;Dbq=C:\Temp\datasource.xls;DefaultDir=C:\Temp;";
string queryString = "SELECT * FROM Data";
OdbcConnection connection = new OdbcConnection(connectionsString);
OdbcDataAdapter adapter = new OdbcDataAdapter(queryString, connection);
DataTable data = new DataTable();
adapter.Fill(data);
data.TableName = "Data";
// Open template.
Document doc = new Document(@"C:\Temp\in.doc");
// Add MergeField callback.
doc.MailMerge.FieldMergingCallback = new HandleMergeField();
// Execute mail merge with regions.
doc.MailMerge.ExecuteWithRegions(data);
// Execute simple mail merge to fill the header with data.
doc.MailMerge.Execute(new string[] { "Canvassed", "Salesperson" }, new object[] { "test", "James Bond" });
// Update page layout to update page numbers in TOC.
doc.UpdatePageLayout();
// Save output.
doc.Save(@"C:\Temp\out.doc");
==================================================================
private class HandleMergeField : IFieldMergingCallback
{
void IFieldMergingCallback.FieldMerging(FieldMergingArgs args)
{
DocumentBuilder builder = new DocumentBuilder(args.Document);
if(args.FieldName == "City")
{
string currentCity = args.FieldValue.ToString();
// Move to the paragraph where the mergefied is located.
builder.MoveToField(args.Field, false);
mRecordIndex++;
if((!string.IsNullOrEmpty(mCity) && mCity!=currentCity) || mRecordIndex>2)
{
mRecordIndex = 0;
// Set PageBreakBefore property.
builder.CurrentParagraph.ParagraphFormat.PageBreakBefore = true;
}
// Insert TC field to build TOC. Insert TC only if this is the first time when City occur.
if (mCity != currentCity)
{
// Get current cell and move builder to the beginning of it.
Cell cell = (Cell)builder.CurrentParagraph.GetAncestor(NodeType.Cell);
builder.MoveTo(cell.FirstParagraph.FirstChild);
builder.InsertField(string.Format("TC \"{0}\" \\l 1", args.FieldValue));
}
mCity = currentCity;
}
// Also insert TC field for each company.
if(args.FieldName == "Company")
{
// Move to the paragraph where the mergefied is located.
builder.MoveToField(args.Field, false);
// Companies is the second level of TOC.
builder.InsertField(string.Format("TC \"{0}\" \\l 2", args.FieldValue));
}
}
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs e)
{
// Do nothing.
}
private string mCity;
private int mRecordIndex;
}
I highlighted my changes in the code and attached the modified template. Hope this helps.
Best regards,
Source Error:
|
If I comments out the following it runs, and when the document opens it shows the TOC, but then it quickly dissapears along with the merge data in the header of the document.
This seems wierd. The TOC and page numbers show if I print, but if I just look at the document, they dont show…
Hi Ryan,
Thanks for this additonal information.
That runtime error is occuring because there are Cell classes in both Aspose.Words and Aspose.Cells but the wrong types are being matched in your code. To fix this you should give the fully qualified names of the classes as to avoid any confusion. i.e instead of just Cell have instead Aspose.Words.Tables.Cell.
Regarding your question on sorting, there is no easy way to sort a TOC as it is the order of the entries are suppost to reflect the positition relative to the order they appear in the document. We can provide you with some code to do this using an index if you need this functionality.
If things still aren't working with your program above could you paste your full code here and I will take a closer look.
Thanks,
I modified the template and code to use an index. What I’m confused about is he index is not automatically built. After the word document is created and opened, it says index has no entries found (or something like that), but if you right click on the index and select update, it appears. Can Aspose.Words automatically do this? I attached my template.
Hi Ryan,
Thanks for posting your code here.
Yes, you can automatically populate index and TOC fields by calling doc.UpdateFields() first, then doc.UpdatePagelayout().
Thanks,
I added the logic below. Still says the following when the document is opened: No index entries found.
<span style=“font-size:
10.0pt;font-family:“Calibri”,“sans-serif””><o:p></o:p>
doc.UpdateFields()
doc.UpdatePageLayout()
Hi
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Thanks for your inquiry. TOC is properly generated on my side. Could you please specify which version of Aspose.Words you use in your application? I used the latest version for testing.
Best regards,
Is there any difference between a TOC and index. I do not have a TOC on my page, only an index… No TC entries, using XE.
Hello
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Thanks for your interest in Aspose.Words. Please just open your document using MS Word and press Alt-F9 to hide/show the field code. You will see TOC field code (Table of Content).
Best regards,