Problem with Bookmarks and Text boxes

Hi there,

I’m just experiencing some strange problems when using text boxes close to bookmarks. Such a text box (which is not part of the bookmark in MS Word), seems to be in between the BOOKMARK_START and BOOKMARK_END nodes once Aspose.Words reads the document.

Please check the attached sample document BookmarkTextbox.docx. Also attached is an image of the document structure in Aspose Document Explorer. As you can see the text box shape is somehow inside the bookmark now. The real problem is, when I remove the default text of the bookmark like so

Bookmark b = doc.getRange().getBookmarks().get("Bookmark");
b.setText("");

to insert new content instead, like so

builder.moveToBookmark("Bookmark");
builder.insertHtml("My new content");

then the text box gets removed as well (which is not intended because the Word document is designed so that the text box is not part of the bookmark).

Is there anything I can do about this? Any workaround?

Thanks in advance!

Just as an additional info, I’m using Aspose.Words for Java 13.9.0.

Hi Kevin,

Thanks for your inquiry. Please note that Aspose.Words mimics the same as MS Word do. The shape node (text box) is part of bookmark. The position of shape node is absolute (see ShapePosition.png) and text wrapping is ‘in front of text’ (see Shape-TextWrapping.png).

Please changed the text wrapping style of shape node to ‘inline with text’ and check the MS Words behavior (see Shape-inline-with-text.png). I have modified the input document and have attached it with this post for your kind reference.

All text of the document is stored in runs of text. You can remove the run nodes between BookmarkStart and BookmarkEnd nodes and insert the new contents into a bookmark. Please use the following code example to achieve your requirements and let us know if you have any more queries.

Document doc = new Document(MyDir + "BookmarkTextbox.docx");
DocumentBuilder builder = new DocumentBuilder(doc);
Bookmark bm = doc.getRange().getBookmarks().get("Bookmark");
ArrayList runNodes = new ArrayList();
Node currentNode = bm.getBookmarkStart();
while (currentNode != bm.getBookmarkEnd() && currentNode != null)
{
    if (currentNode.getNodeType() == NodeType.RUN)
    {
        runNodes.add(currentNode);
    }
    currentNode = currentNode.getNextSibling();
}
for (Node node : (Iterable<Node>)runNodes)
{
    node.remove();
}
builder.moveToBookmark("Bookmark");
builder.insertHtml("My new content");
doc.save(MyDir + "Out.docx");

Sorry, accidental double post, see message below.

Hi Tahir,

thanks for your quick response. This is quite interesting. I find the behavior of MS Word really strange though. I mean, from a user perspective it doesn’t look like the text box is actually a part of the bookmark until you switch to “inline with text”. Thanks for clearing this up.

Your code sample is actually quite similar to something I was experimenting with. There’s just one more thing that’s causing some trouble - a bookmark spanning multiple paragraphs. For example, the bookmark starts in paragraph one and ends in paragraph two (see attached docx). Now I’d like to remove the text (runs) inside the bookmark (but leave the shape intact). Basically I’d like to go from the structure in attached BookmarkText2.png to the structure in BookmarkText3.png, so that I can just add text at the bookmark position via insertHtml instead of the old text. Is there any way to achieve this?

Edit: Something that just crossed my mind - maybe it would save a lot of trouble if I could just copy any shape nodes inside the bookmark and insert them before the bookmark_start node so I could just work with bookmark.setText("") to remove any text inside the bookmark. Would this be possible?

Hi Kevin,

Thanks for your inquiry. I have modified the code according to your requirements. Hope this helps you.

Document doc = new Document(MyDir + "BookmarkTextbox2.docx");
DocumentBuilder builder = new DocumentBuilder(doc);
Bookmark bm = doc.getRange().getBookmarks().get("Bookmark");
ArrayList nodes = new ArrayList();
Node currentNode = bm.getBookmarkStart();
while (currentNode != bm.getBookmarkEnd() && currentNode != null)
{
    if (currentNode.getNodeType() == NodeType.RUN)
    {
        nodes.add(currentNode);
    }
    currentNode = currentNode.nextPreOrder(doc);
}
//Remove Run nodes
for (Node node : (Iterable<Node>)nodes)
{
    node.remove();
}
builder.moveToBookmark("Bookmark");
builder.insertHtml("My new content");
doc.save(MyDir + "Out.docx");

k.s:

Edit: Something that just crossed my mind - maybe it would save a lot of trouble if I could just copy any shape nodes inside the bookmark and insert them before the bookmark_start node so I could just work with bookmark.setText("") to remove any text inside the bookmark. Would this be possible?

Yes, you can achieve the same requirements by using following code example. Please let us know if you have any more queries.

Document doc = new Document(MyDir + "BookmarkTextbox2.docx");
DocumentBuilder builder = new DocumentBuilder(doc);
Bookmark bm = doc.getRange().getBookmarks().get("Bookmark");
ArrayList nodes = new ArrayList();
Node currentNode = bm.getBookmarkStart();
while (currentNode != bm.getBookmarkEnd() && currentNode != null)
{
    if (currentNode.getNodeType() == NodeType.SHAPE)
    {
        nodes.add(currentNode);
    }
    currentNode = currentNode.nextPreOrder(doc);
}
bm.setText("");
builder.moveToBookmark("Bookmark");
for (Node node : (Iterable<Node>)nodes)
{
    builder.insertNode(node);
}
builder.insertHtml("My new content");
doc.save(MyDir + "Out.docx");

Hi Tahir,

thanks for your reply.

The first code example (removing the runs) still produces some problems for me (e.g. it also removes the runs inside the shape). But after all, removing the runs might not be the way to go.

Your second code example (“moving” the shape nodes) is perfection. It produces exactly the output I wanted. I tried to pull it off myself but couldn’t quite manage to insert the shape nodes into the right place (I was trying to work with insertBefore). Thanks a lot for that!

Kevin

Hi Kevin,

Thanks for your inquiry. Yes, the second code example will work fine in your case. However, if you still face any issue, please share following detail for investigation purposes.

  • Please attach your input Word document.
  • Please attach the output Word file that shows the undesired behavior.
  • Please
    attach your target Word document showing the desired behavior. You can
    use Microsoft Word to create your target Word document. I will
    investigate as to how you are expecting your final document be generated
    like.