Performance Issues with GetChildNodes()

Hi Roman,



I’m glad to see that the Insert() methods now return the node that was
inserted. Can you do the same for the DocumentBuilder.Write() and
Writeln() methods? I’d like them to return the Run node that was
just inserted. Currently, I have to do the following to get the
last run:



wrdBody = DocumentBuilder.Document.GetChild(NodeType.Body, 0, True)

wrdBodyRuns = wrdBody.GetChildNodes(NodeType.Run, True)

wrdRun = DirectCast(wrdBodyRuns(wrdBodyRuns.Count - nTotalRuns), Run)



When wrdBodyRuns.Count gets up into the thousands, performance is
extremely impacted. The reason I always need to retrieve the Run
node is because I have to apply style to it.



Thanks, Natan.




Why don't you set the style you want using DocumentBuilder.Font? The runs inserted by Write and Writeln get a copy of the attributes (including style) specified there.

builder.Font.StyleName = "MyStyle";

builder.Write("Hello");

"Hello" gets assigned the MyStyle character style.

We will make Write and Writeln to return something in the future, but be aware that Write and Writeln might create and insert more than one node at a time. For example if you call Write("Hello\rHello") it will actually create one run node than one paragraph node and then one more run node. So it will not be able to return all nodes it created, only the last run node probably.

Another thing I plan is to expose GetChildNodes collection that is "dead" I mean a snapshot. All collections returned by GetChildNodes are live at the moment and if you do have many of them around and you keep modifying the document, they are all listening for changes.

Roman,



I can use DocumentBuilder.Font if it only applies to runs, but I’m
pretty sure it behaves as a global style applied to everything
inserted. Another option is to reset the Font property back to
the defaults after each run is inserted. Can I do this?



Do you have a timeframe for when the updated Write() and Writeln() methods will be complete?



Thanks,

Natan

I'm not sure what do you mean by DocumentBuilder.Font behaves as a global style.

Think of DocumentBuilder as having a cursor. Formatting properties that are available from DocumentBuilder reflect formatting that is available in the document at the cursor.

// Say you create document builder, the cursor is at the beginning of the document.
// DocumentBuilder.Font reflects formatting available at that location, say its Times New Roman 12 pt.
// Then you set your formatting to bold.
//Like in MS Word, when you just press Bold and you have no selection, nothing immediately becomes bold.
//But Bold is selected at the cursor location.
builder.Font.Bold = true;

//Then you type some text it comes out in bold.
builder.Write("Hello");

//Then you can jump to another location, say to a bookmark
builder.MoveToBookmark("aaa");

//DocumentBuilder.Font now reflects formatting available at the bookmark.
//For example it was not bold in the bookmark.
Assert.IsFalse(builder.Font.Bold);

Let me know why this does not work for you.

Also in Aspose.Words 3.6 we added DocumentBuilder.PushFont and PopFont that allow to temporarily save font formatting and then restore it. Maybe it will help. Aspose.Words uses these methods internally when importing HTML for example.

It is easy to modify Write and Writeln to return the last node they created, I'm just not sure we really need to do that because as I said they can insert more than one node.

Roman,



I got everything working after I tried it. I simply call
DocumentBuilder.Font.ClearFormatting() to clear the styles applied to
the last run.



Thanks,

Natan