How to replace a Table inside a bookmark


#1

I have a template (.dot) file which contains bookmarks for areas of the document which need to be dynamically modified.

One of the bookmarks contains a Table: I need to be able to locate the table and manipulate it.

With Word automation I do it something like the following:

Set bookmark = document.Bookmarks(BookmarkName)
Set range = bookmark.Range
If range.Tables.Count <> 1 ... then raise an error
table = range.Tables(1)
... manipulate the table

How can I achieve the same thing using Aspose.Words? I have a StartBookmark and EndBookmark, but I don't see a method of the Bookmark object to search it for contained nodes.


#2

There is no Range property for Bookmark in our API yet. I suggest using the following makeshift procedure:

private ArrayList GetTablesInBookmark(Document doc, string bookmarkName)

{

NodeCollection nodes = doc.GetChildNodes(NodeType.Any, true);

bool bmstarted = false;

ArrayList tables = new ArrayList();

foreach (Node node in nodes)

{

if(node is BookmarkStart && ((BookmarkStart)node).Name == bookmarkName)

bmstarted = true;

if(bmstarted)

if(node is Table)

tables.Add(node);

if(node is BookmarkEnd && ((BookmarkEnd)node).Name == bookmarkName)

break;

}

return tables;

}


#3

Here is the same example in Visual Basic:

Private Function GetTablesInBookmark(ByVal doc As Document, ByVal bookmarkName As String) As ArrayList

Dim nodes As NodeCollection = doc.GetChildNodes(NodeType.Any, True)

Dim bmstarted As Boolean = False

Dim tables As ArrayList = New ArrayList

Dim node As Node

For Each node In nodes

If TypeOf node Is BookmarkStart And (CType(node, BookmarkStart)).Name = bookmarkName Then

bmstarted = True

End If

If bmstarted Then

If TypeOf node Is Table Then

tables.Add(node)

End If

End If

If TypeOf node Is BookmarkEnd And (CType(node, BookmarkEnd)).Name = bookmarkName Then

Exit For

End If

Next

Return tables

End Function


#4

This didn't work for me. I am only interested in the first Table found inside the bookmark, so I used a variant of your code (see below), but it always returns null. When I step through with a debugger, the only nodes I see when inBookmark is true are Cell, Paragraph or Run nodes. I don't see any Table nodes.

I've attached the Word document I'm using. The bookmark I'm interested is "PerformanceTable".

Also I'd like to know if there are any performance implications with this technique, which has to search the whole document each time.

private Table GetBookmarkedTable(string bookmarkName)
{
NodeCollection nodes = _document.GetChildNodes(NodeType.Any, true);
bool inBookmark = false;

foreach(Node node in nodes)
{
if ((node.NodeType == NodeType.BookmarkStart) && (((BookmarkStart)node).Name == bookmarkName))
{
inBookmark = true;
continue;
}
if (inBookmark)
{
if (node.NodeType == NodeType.Table) return (Table) node;
if ((node.NodeType == NodeType.BookmarkEnd) && (((BookmarkEnd)node).Name == bookmarkName)) return null;
}
}
return null;
}


#5

The code is not working for your document because the bookmark actionally starts inside the table. The following code modification will handle this case:

private ArrayList GetTablesInBookmark(Document doc, string bookmarkName)

{

NodeCollection nodes = doc.GetChildNodes(NodeType.Any, true);

bool bmstarted = false;

ArrayList tables = new ArrayList();

foreach (Node node in nodes)

{

if(node is BookmarkStart && ((BookmarkStart)node).Name == bookmarkName)

bmstarted = true;

if(bmstarted)

{

if(node is Table)

tables.Add(node);

if(node is Cell)

{

Table table = ((Cell)node).ParentRow.ParentTable;

if(!tables.Contains(table))

tables.Add(table);

}

}

if(node is BookmarkEnd && ((BookmarkEnd)node).Name == bookmarkName)

break;

}

return tables;

}

You should not care about perfomance in this case. Simple iterating over the nodes is very fast. Only operations that involve a number of recursions can be slow.