I have a request to pull/get page numbers for the topics in our report. I understand the TOC, and that is not the problem. The struggle is that within the report, we have to create references to a topic from the TOC that links to the client section of the report.
So, in other words, if the client is on page 33 and sees the link/content for another reference on page 64 with TITLE and Page Number and decides to click on the link/content, it will take the client to that section of the report.
section.Blocks.Add(New TableOfEntries(document, FieldType.XE.TOC And āNew Horizonsā))
Hi Raymond,
If I understood you correctly, you want to create something like the content that you have inside the TOC somewhere in the documentās body.
Note that TOC entries are Paragraph elements with a Hyperlink containing text, tab, and PageRef field. So basically, you would need to recreate that or create a copy of the Paragraph from the TOC entries collection and use that instead.
I hope this helps. If you need more, please send us your Word file and specify what you would like to do with it and Iāll help you with that.
Regards,
Mario
Hi Mario,
I uploaded one of my home inspection reports. Link To Dropbox
On page 11 is the start of the table of contents.
My summary starts on page 19. Under Major Concerns, youāll see āGutters.ā
Under the comments, I need to insert a page number. In this example, I would need page 82 as a link to page 82.
I was thinking of automatically linking each section with its page number so I wouldnāt have to do it manually.
I was hoping that all I would need was a string āGutters: Exterior - Aluminum Guttersā and it would generate a page number.
Regards,
Ray
Hi Ray,
Try this:
var document = DocumentModel.Load("Inspection Report - 50286170.docx");
// Get TOC entry.
var toc = (TableOfEntries)document.GetChildElements(true, ElementType.TableOfEntries).First();
var tocEntry = (Paragraph)toc.Entries.First(e => e.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters"));
/* This TOC entry is a paragraph that contains the following elements:
*
* Paragraph:
* |_ Hyperlink:
* |_ Run ("Gutters: Exterior - Aluminum Gutters")
* |_ SpecialCharacter ("\t")
* |_ PageRef ("80")
*/
// Create "Page X" content by cloning the above TOC entry.
// We'll edit the text of the first element and remove the tab.
var cloneEntry = tocEntry.Clone(true);
var cloneHyperlink = (Hyperlink)cloneEntry.Inlines[0];
((Run)cloneHyperlink.DisplayInlines[0]).Text = "Page ";
cloneHyperlink.DisplayInlines.RemoveAt(1);
// Create comment.
var comment = new Comment(document);
comment.Blocks.Add(cloneEntry);
// Insert comment.
var content = document.Content.Find("Area: Gutters").First();
content.Start.InsertRange(new CommentStart(document, comment).Content);
content.End.InsertRange(new CommentEnd(document, comment).Content);
document.Save("output.docx");
I hope this helps.
Regards,
Mario
Thank you, Mario. Your suggestion was helpful.
Thank you, Nehakumari. Your suggestion of the TableOfEntries as a clickable link fits our scenario a bit better, given the algorithm we are forming in our code.
Hi Nehakumari,
Iāve tried the TableOfEnties about a hundred different ways with no success based on the topic string. The closest that Iāve gotten was utilizing the .XE function and calling the topic string name.
Would you have any other suggestions?
Hi Mario,
I converted your code to VB and Iām getting some errors. I was wondering if you could help me out again.
- "Local variable ātocā hides a variable in the enclosing block.
- Lambda parameter āeā hides a variable in an enclosing block.
- āHyperlinkā is a class type and cannot be used as an expression.
Hi Raymond,
Try this:
Dim document = DocumentModel.Load("Inspection Report - 50286170.docx")
' Get TOC entry.
Dim toc = CType(document.GetChildElements(True, ElementType.TableOfEntries).First(), TableOfEntries)
Dim tocEntry = CType(toc.Entries.First(Function(e) e.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters")), Paragraph)
' This TOC entry Is a paragraph that contains the following elements:
'
' Paragraph:
' |_ Hyperlink
' |_ Run ("Gutters: Exterior - Aluminum Gutters")
' |_ SpecialCharacter ("\t")
' |_ PageRef ("80")
' Create "Page X" content by cloning the above TOC entry.
' We'll edit the text of the first element and remove the tab.
Dim cloneEntry = tocEntry.Clone(True)
Dim cloneHyperlink = CType(cloneEntry.Inlines(0), Hyperlink)
Dim cloneRun = CType(cloneHyperlink.DisplayInlines(0), Run)
cloneRun.Text = "Page "
cloneHyperlink.DisplayInlines.RemoveAt(1)
' Create comment.
Dim comment = New Comment(document)
comment.Blocks.Add(cloneEntry)
' Insert comment.
Dim content = document.Content.Find("Area: Gutters").First()
content.Start.InsertRange(New CommentStart(document, comment).Content)
content.End.InsertRange(New CommentEnd(document, comment).Content)
document.Save("output.docx")
Regards,
Mario
1 Like
Thank you, Mario,
I appreciate you. You are the backbone of this forum.
Mario, please modify the code to find the āCommentsā part in the section and append ā(Page ??)ā link to it.
Hi Raymond,
Here is how to add that āPage Xā content into a specific paragraph instead of adding it into a Comment
element:
Dim document = DocumentModel.Load("Inspection Report - 50286170.docx")
' Get specific TOC entry.
Dim toc = CType(document.GetChildElements(True, ElementType.TableOfEntries).First(), TableOfEntries)
Dim tocEntry = CType(toc.Entries.First(Function(e) e.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters")), Paragraph)
' Create "Page X" content by cloning the hyperlink from the TOC entry.
Dim cloneHyperlink = CType(tocEntry.Inlines(0).Clone(True), Hyperlink)
Dim cloneRun = CType(cloneHyperlink.DisplayInlines(0), Run)
cloneRun.Text = "Page "
cloneHyperlink.DisplayInlines.RemoveAt(1)
' Add "Page X" content to specific paragraph.
Dim content = document.Content.Find("Comments: Missing/Bent/Pitched").First()
Dim paragraph = CType(content.Start.Parent.Parent, Paragraph)
paragraph.Inlines.Add(New Run(document, " ("))
paragraph.Inlines.Add(cloneHyperlink)
paragraph.Inlines.Add(New Run(document, ")"))
document.Save("output.docx")
Does this work for you?
Regards,
Mario
Hi Mario,
We do not need to load any documents because the document compilation is already in progress.
However, we continue to get two error in the āError Listā
- Variable ātocā hides a variable in the enclosed block.
- Lambda parameter āeā hides a variable in an enclosing block, a previously defined range variable, or an implicitly declared variable in the query expression.
In other words, if we started a new project and used the source code, we would continue to get the same errors.
We have the latest version of GemBox.Documents along with other components for this project.
Kind regards,
Ray
Ray, can you please send me a new project that uses that source code and gets those mentioned errors?
Unfortunately, Iām unable to reproduce the issue.
Hi Mario,
Sorry for the delay. Didnāt see the reply until now. Here is the link to the test project. https://drive.google.com/file/d/1pRWZCn00hnLJj_7NWUi3pHdmm6w5XBQp/view?usp=drive_link
Regards,
Ray
I get Access Denied.
Can you please try again to create a shared link or accept the Access Request I just sent you?
The 2. error occurs because there is a name collision, both of these lines of code use āeā as a parameter name:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim tocEntry = CType(toc.Entries.First(Function(e) e.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters")), Paragraph)
The solution is to rename one of them, for example:
Dim tocEntry = CType(toc.Entries.First(Function(entry) entry.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters")), Paragraph)
The 1. error I was unable to reproduce it, but it seems to be another name collision.
So, try renaming it:
Dim tocElement = CType(document.GetChildElements(True, ElementType.TableOfEntries).First(), TableOfEntries)
Dim tocEntry = CType(tocElement.Entries.First(Function(entry) entry.Content.ToString().Contains("Gutters: Exterior - Aluminum Gutters")), Paragraph)
Does this solve your issue?
Regards,
Mario
Hi Mario,
The logic makes 100% sense but I continue to get this error indicating that the sequence contains no matching elementā¦
Dim tocElement = CType(document.GetChildElements(True, ElementType.TableOfEntries).First(), TableOfEntries)
Dim tocEntry = CType(tocElement.Entries.First(Function(entry) entry.Content.ToString().Contains(āWalls: Basement - Wallsā)), Paragraph)
And for the āFindā the content is pretty much copied.
Dim content = document.Content.Find(āWalls Comments: Major Concern To Foundation Wall.ā).First()
I tried less wordy searches to find in the document with the same results.
Regards,
Ray
Hi Ray,
When I search for the āWalls: Basement - Wallsā text inside the āInspection Report - 50286170.docxā file from Microsoft Word, it shows me that there is no such text:
Are the screenshots perhaps from another file, the one that is not being loaded with a DocumentModel.Load
method?
Regards,
Mario
Hi Mario,
I sent you another link to another inspection report via Google Drive.
Kind regards,
Ray