Bookmark and Table

Hello,
I am trying to convert DCOM Word to Aspose. Most of it is straight forward.However I can’t solve the following problem:
I have in a document a table. The first cell contains a BookMark. In de MSWord enviroment I was ableto set tekst in the cell, move to the cell right, set text and add a new row, set text, move cell to right and set text aso.
There are over 100 templates, so we would like to keep the bookmarks in the table.
Can someone help me how to solve this?
re

Hi
Thanks for your inquiry. You can use DocumentBuilder to achieve what you need. I create an example for you. See the following code and the attached documents.

//Create some datasource
DataTable tab = new DataTable();
tab.Columns.Add("col1");
tab.Columns.Add("col2");
tab.Columns.Add("col3");
tab.Columns.Add("col4");
tab.Columns.Add("col5");
//Add some data
for (int i = 0; i < 20; i++)
{
    tab.Rows.Add(new object[] { "val0_" + i.ToString(), "val1_" + i.ToString(), "val2_" + i.ToString(), "val3_" + i.ToString(), "val4_" + i.ToString() });
}
//Open document
Document doc = new Document("in.doc");
//Creade DocumentBuilder
DocumentBuilder builder = new DocumentBuilder(doc);
//Move DocumentBuildr cursor to bookmark
builder.MoveToBookmark("myBookmark");
//Get cell where bookmark is placed
Cell refCell = builder.CurrentNode.GetAncestor(NodeType.Cell) as Cell;
if (refCell != null)
{
    //Create copy of Row where bookmark is placed
    Row srcRow = (Row)refCell.ParentRow.Clone(true);
    //Loop through all rows in datasource table
    foreach (DataRow data in tab.Rows)
    {
        //Loop through all columns in the datarow
        foreach (DataColumn col in tab.Columns)
        {
            //Insert data into the current cell
            builder.Write(data[col].ToString());
            //Move to next cell
            if (refCell.NextSibling != null)
            {
                refCell = (refCell.NextSibling as Cell);
                builder.MoveTo(refCell.LastParagraph);
            }
            else
            {
                break;
            }
        }
        if (!data.Equals(tab.Rows[tab.Rows.Count - 1]))
        {
            //Add new row
            Row newRow = (Row)srcRow.Clone(true);
            refCell.ParentRow.ParentTable.Rows.Add(newRow);
            //Move cursor to the first cell of the newly created row
            refCell = newRow.FirstCell;
            builder.MoveTo(newRow.FirstCell.LastParagraph);
        }
    }
}
//Save document
doc.Save("out.doc");

I hope this could help you.
Also I think that the better way to achieve this is using mail merge feature, but then you should change your templates. See the following links for more information.
https://docs.aspose.com/words/net/types-of-mail-merge-operations/
Best regards.

Hi,
thanks for the help. I converted the project in 6 hours from WORD DCOM to Aspose. And the performance is great.
I can’t use the mail merge, but what I have is now ok.
However if have 1 problem with the following code:

foreach (Bookmark elem in doc.Document.Range.Bookmarks)
{
    n = elem.Name;
    try
    {
        t = elem.Text;
    }
    catch (Exception x1)
    {
        t = x1.Message + "{" + n + "}";
    }
}

I get an error on the elem.Text at some bookmarks. The error is:
Start and end node should have the same grand parent.
Any clue what this is?
re bert

Hello!
Thank you for asking this.
Your case corresponds to a known issue:
#502 – Allow to get and set bookmark text when start and end have different grand parents
As a workaround you can traverse nodes programmatically from bookmark start to bookmark end. In general getting text in not so complex as setting it to a new value. Let us know if you have difficulties with this.
Regards,

Hello
I still can get it to work. The rest of our application is working.
this is the snippit of my code:

public void ActionList(DocumentBuilder doc, string bookmark)
{
    bool first = true;
    SetBookMark(doc, bookmark, ""); //The bookmark has a defualttext in it whcih should not be displayed
    doc.MoveToBookmark(bookmark); //This should be in a table!!!
    Cell refCell = (Cell)doc.CurrentNode.GetAncestor(NodeType.Cell);
    Row copyRow = (Row)refCell.ParentRow.Clone(true);
    foreach (string Text in AllText)
    {
        if (first) //Eerste keer niet naar nieuwe cell springen, want daar sta je al
            first = false;
        else
        {
            Row newRow = (Row)copyRow.Clone(true);
            refCell.ParentRow.ParentTable.Rows.Add(newRow);
            //Move cursor to the first cell of the newly created row
            refCell = newRow.FirstCell;
            doc.MoveTo(refCell);
        }
        doc.Write(Text);
    }
}

However, it looks likes it copies(dupplicates) also the BookMark defined in the 1st row. Then I get this error.
What I need is a copy of the 1st row, without the bookmark. De row should be empty and I need to add text in ech cell.

Hi
Thanks for your inquiry. I think that error occurs in the following line:

doc.MoveTo(refCell);

This occurs because parameter of MoveTo method should be a Paragraph or a direct child of a Paragraph (e. g. Run).
In my example you can see the following

builder.MoveTo(refCell.LastParagraph);

Hope this helps.
Best regards.

Hi, sorry for giving you the wrong code. In my code I have the refCell.LastParagraph, however the error is still there:
Start and end node should have the same grand parent.
And the only reason I can think of is that the bookmark is also copied to the next line(s). Is there anyway I can just clear all the cells in the newRow. I then expect that the bookmark is also gone.
Thanks for you fast response and help.

Hi
Thank you for additional information. Could you also attach your document for testing? I will try to reproduce this issue and provide you more information.
Best regards.

I have attached the document (sorry for the Dutch Part).
Please look at the 2 tables with the bookmarks start with bl__
Please rename the attachment from .txt to .dot

Hi
Thanks for your inquiry. I can’t reproduce this issue on my side. You can try to remove all content from the cell before inserting text. Please see the following code:

string[] AllText = { "test1", "test2", "test3" };
bool first = true;
//Open document
Document doc = new Document(@"Test251\Memo.dot");
//Creade DocumentBuilder
DocumentBuilder builder = new DocumentBuilder(doc);
//Move DocumentBuildr cursor to bookmark
builder.MoveToBookmark("bl__KopieLijst"); //bl__ActieLijst bl__KopieLijst
                                            //Get cell where bookmark is placed
Cell refCell = builder.CurrentNode.GetAncestor(NodeType.Cell) as Cell;
if (refCell != null)
{
    //Create copy of Row where bookmark is placed
    Row copyRow = (Row)refCell.ParentRow.Clone(true);
    //Loop through all rows in datasource
    foreach (string Text in AllText)
    {
        if (first)
            first = false;
        else
        {
            Row newRow = (Row)copyRow.Clone(true);
            refCell.ParentRow.ParentTable.Rows.Add(newRow);
            //Move cursor to the first cell of the newly created row
            refCell = newRow.FirstCell;
            builder.MoveTo(refCell.LastParagraph);
        }
        //Remove all content from cell
        while (refCell.Paragraphs.Count > 1)
            refCell.FirstParagraph.Remove();
        refCell.LastParagraph.RemoveAllChildren();
        builder.MoveTo(refCell.LastParagraph);
        //Insert text into the cell
        builder.Write(Text);
    }
}
//Save document
doc.Save(@"Test251\out.doc");

Also please tell me which version of Aspose.Words are you using. I use the latest (5.2.0) version for testing.
Best regards.

Hi, that is working. Thanks.
Can I ask another question? Is it possible to print the document on a printer connected to the server. it is enough to give me a link to an example.
again thanks and a great product.

Hi
Thanks for your inquiry. You can use Aspose.Words.Viewer namespace for document printing. Please see the following link for more information.
https://docs.aspose.com/words/net/rendering/
Here is code example

Document doc = new Document("in.doc");
DocumentRenderer renderer = new DocumentRenderer(doc);
renderer.Print();

But note that Aspose.Words.Viewer namespace is currently in beta and limited technical support is provided for it.
Best regards.

We are happy to tell you that the new Rendering Engine has replaced the “old Viewer Beta”. The Rendering Engine can print, save as images or draw onto .NET Graphics object any document page.

Please see Aspose.Words documentation to learn more about new features.

Saving to image

In additional, new Rendering engine allows you to convert Word document to PDF directly (without using Aspose.Pdf).

Saving to Pdf

The latest version of Aspose.Words is available for download from downloads section or from NuGet

The issues you have found earlier (filed as 502) have been fixed in this update.

I think this would make a great piece in the ‘How to’ in the documentation.

The solution of how to add to an existing table is not obvious. I would not have thought of cloning rows to add to the table.
The current documentation only shows creating a new table, which has styling issues since we have no way to set the table style.

Thank you for this gem.

Hi there,
Thank you for your suggestion.
Yes, I think an example of how to clone a Row or Cell in order to easily retain formatting is a good idea. I will add it to the documentation.
Thanks,