Table of contents link to top of page

I am trying to merge multiple Word documents together and a table of contents at the beginning. I’m inserting TC fields at the top of each document before I append it so that the table of contents has something to target. The documents have big headers in them, so the TC field ends up quite far down the page, so when you click on a link in the table of contents it takes you 1/3 of the way down the target page.

Is there any way of getting the table of contents link to go to the top of the page? I tried putting the TC field in the header but it didn’t work.

I am using Aspose.Words.NET v23.1.0

Here is an example document:

download (2).docx (21.9 KB)

var mergedDoc = new Document();
var mergedDocBuilder = new DocumentBuilder(mergedDoc);

mergedDocBuilder.ParagraphFormat.StyleIdentifier = StyleIdentifier.Title;
mergedDocBuilder.Writeln(title);
mergedDocBuilder.InsertBreak(BreakType.PageBreak);

// https://support.microsoft.com/en-us/office/field-codes-toc-table-of-contents-field-1f538bc4-60e6-4854-9f64-67754d78d05c
var toc = mergedDocBuilder.InsertTableOfContents(@"\h \z \f p");

var policiesWithDocuments = policies
	.Where(p => p.Document != null)
	.ToList();

var importFormatOptions = new ImportFormatOptions() {
	IgnoreHeaderFooter = true,
	SmartStyleBehavior = true
};

foreach (var policy in policiesWithDocuments) {
	using var vs = await _documentService.DownloadPolicyDocumentAsStreamAsync(policy.Document!.Id, false);

	var policyDoc = new Document(vs.Stream);

	policyDoc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;
	policyDoc.FirstSection.HeadersFooters.LinkToPrevious(false);
	policyDoc.FirstSection.PageSetup.RestartPageNumbering = false;

	var builder = new DocumentBuilder(policyDoc);
	CopyFontFromStyle(mergedDoc.Styles[StyleIdentifier.Toc1], builder.Font);
	builder.InsertField($@"TC ""{policy.Name}"" \f p");

	mergedDoc.AppendDocument(policyDoc, ImportFormatMode.KeepDifferentStyles, importFormatOptions);
}

toc.Update();

var ms = new MemoryStream();
mergedDoc.Save(ms, SaveFormat.Pdf);

@jmunro You can put TC field into a textbox shape and place it at the top of the page. Please try modifying your code like the following:

using var vs = await _documentService.DownloadPolicyDocumentAsStreamAsync(policy.Document!.Id, false);

var policyDoc = new Document(vs.Stream);

policyDoc.FirstSection.PageSetup.SectionStart = SectionStart.NewPage;
policyDoc.FirstSection.HeadersFooters.LinkToPrevious(false);
policyDoc.FirstSection.PageSetup.RestartPageNumbering = false;

var builder = new DocumentBuilder(policyDoc);

// Create a textbox shape where TC field will be inserted.
Shape tcBox = new Shape(policyDoc, ShapeType.TextBox);
tcBox.Stroked = false;
tcBox.Width = 100;
tcBox.Height = 15;
tcBox.WrapType = WrapType.None;
tcBox.RelativeHorizontalPosition = RelativeHorizontalPosition.Page;
tcBox.RelativeVerticalPosition = RelativeVerticalPosition.Page;
tcBox.Left = 0;
tcBox.Top = 0;
tcBox.AppendChild(new Paragraph(policyDoc));

builder.InsertNode(tcBox);
builder.MoveTo(tcBox.FirstChild);
builder.InsertField($@"TC ""{policy.Name}"" \f p");

mergedDoc.AppendDocument(policyDoc, ImportFormatMode.KeepDifferentStyles, importFormatOptions);
1 Like