Range.Bookmarks command very slow

Hello,

I use .NET 18.2 version.
I noticed that doing a foreach cycle on a document bookmarks, using .Range.Bookmarks to determine the list of bookmark is very slow (about 500 ms for 250 bookmarks).
Since I do this operation many times in order to find particular bookmarks, the issue is critical.

Try simply this C# code:

Dictionary<string, Int32> dict_bm = new Dictionary<string, int>();
int k = 0;
foreach (Aspose.Words.Bookmark bm in wordDocument.Range.Bookmarks)
{
    dict_bm.Add(bm.Name, k)
    k++;
}

Please, do you know if this problem is solved with the newer versions?
Thx
Luca

@ceck Could you please attach your document here for testing? We will check the issue and provide you more information.

Thank you Alexey.
Please find in attachment the sample document (don’t care if doc variables won’t be populated).
Please use this program to test.
I “simulated” what I do in the real program:
a) I have a map listing bookmark names with associated True/False (depending on simulation results)
b) for each one, if it is false I search in the document bookmark list the corresponding name and remove it

In this sample, I start with 323 bookmarks and remove 224.
It takes about 11.5" on my PC.
Each time a make a foreach on the document bookmark list to find the name is about 110-130 ms, associated it seems to the foreach itself not to the instructions inside [foreach (Aspose.Words.Bookmark bm in wordDocument.Range.Bookmarks)]

Template.zip (218.9 KB)

Thanks
Luca

_____________________________________-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aspose;

namespace AsposeTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Aspose.Words.License license = new Aspose.Words.License();
            string templatePath = "Template.doc";
            license.SetLicense("Aspose.Words.lic");
            Aspose.Words.Document wordDocument = null;
            wordDocument = new Aspose.Words.Document(templatePath);

            //Create a list of the names of the bookmarks
            //In this sample program the list "replaces" a bookmark map (coupled to session variables) on a file which I use for determing if a bookmark in the doc should be removed or not
            List<string> lst_name = new List<string>();
            int k = 0;
            int size = wordDocument.Range.Bookmarks.Count;
            foreach (Aspose.Words.Bookmark bm in wordDocument.Range.Bookmarks)
            {
                lst_name.Add(bm.Name);
                k++;
            }

            //For cycle on the list of bookmarks name
            k = 0;
            for (k = 0; k < size; k++)
            {
                //Instead of the real application a bookmark map (coupled to session variables), here I decide to keep only bookmark called "Cooling", "Heating", "Cooling_???","Heating_???"
                //This removes 224 bm out of 323
                if (!(lst_name[k] == "Cooling" || lst_name[k].Contains("Cooling_") || lst_name[k] == "Heating" || lst_name[k].Contains("Heating_"))
                    || lst_name[k].Contains("Cooling_ACS") || lst_name[k].Contains("Cooling_Heating"))
                {
                    //Search inside the document bookmark list the bookmark which has the name [k]
                    foreach (Aspose.Words.Bookmark bm in wordDocument.Range.Bookmarks)
                    {
                        if (lst_name[k] == bm.Name)
                        {
                            bm.Text = "";
                            bm.Remove();
                            break;
                        }
                    }
                }
            }
            wordDocument.Save("Template_save.doc");
        }
    }
}

@ceck Thank you for additional information. I checked your code with 18.2 and the latest 22.7 versions of Aspose.Words.

  • with 18.2 it takes about 13 seconds on my side;
  • with 22.7 it takes less than 2 seconds to run the same code.

So with the latest version your code works much faster.

Also, there is still room for code optimization. Copping bookmark names to list can be optimized to the following:

List<string> lst_name = wordDocument.Range.Bookmarks.Cast<Bookmark>().Select(b => b.Name).ToList();

Code that removes bookmarks can also be optimized. Instead of looping all bookmarks in the document, you can cherry-pick the bookmarks that should be removed:

Bookmark bm = wordDocument.Range.Bookmarks[lst_name[k]];
if (bm != null)
{
    bm.Text = "";
    bm.Remove();
}

Though the mentioned optimization does not improve performance with 18.2 version much, but code becomes more readable.

Dear Alexey

thank you so much.
Today I updated to 22.7 version and now on my pc the performance changed from 16000 ms to 165 ms.
Now I’m checking the full program for understanding if the behaviour changes moving from v18 to 22.

Luca

1 Like

@ceck Please feel free to ask in case of any issues. We will be glad to help you.

Dear Alexey

I’m testing the new dll with my old program and I noticed serious differences when removing bookmarks inside a tables (I have different cases: remove bookmarks inside a single cell, full row, multiple rows or full tables).

The first problem is facing when I remove a single row or a boomark inside a cell. It seems that a lot of other bookmarks before the one I’m deleting are deleted together. Clearly with 18.2 version the program was working well.

Please consider the attached program below and the attached template, when I remove the wordDocument.Range.Bookmarks["Cooling_Capacity_ck"], bookmark wordDocument.Range.Bookmarks["Cooling_DehumCapacity_ck"] is removed (together with many others) as soon as I remove the current bm or also if I simply assign bm.Text. Put a breakpoint at the int bbb = 1 line to see.

Could you please help me? I used 4.6.1 Aspose dll version. I removed the licence from the zip.

Template.zip (218.9 KB)
AsposeTest.zip (6.8 MB)

Thanks!
Luca


@ceck Thank you for additional information. I have managed to reproduce the problem with table bookmarks and nested bookmarks on my side. For a sake of correction it has been logged as WORDSNET-24087. We will keep you informed and let you know once it is resolved.

Perfect Alexey. I’ll be anxiously waiting. I hope the correction won’t slow down the bookmark list access as in version 18.2

Thanks
Luca

1 Like

The issues you have found earlier (filed as WORDSNET-24087) have been fixed in this Aspose.Words for .NET 22.8 update also available on NuGet.

Dear Alexey,

I tested version 22.8.
Unfortunately the problem is not fully fixed. In particular, bookmarks containing more rows in the same table are not correctly removed, at least considering my code working properly with version 18.1.

Please find an attachment:

  • a word document where I fully detail the problem and show the result and also give an hint for a possible cause
  • the sample c# program from which you can replicate the issue (I removed licence files)

Let me know

Luca

Aspose_22_8_nestedBookmark_error.docx (968.8 KB)

https://www.dropbox.com/s/ktea0ddebzza0hh/AsposeTest.zip?dl=0

@ceck Thank you for your feedback and additional information. I have created another defect WORDSNET-24206 for this issue. We will investigate it and let you know once it is resolved or we have more information for you.

Hi Alexey

we are worried because the support period will expire next July.
We updated the license because it should have solved our problems but unfortunately it is not there.
Do you think it is possible to solve the bug 24206 before the support expiring. We hope so!
Thanks!
Luca

@ceck We have completed the analysis of the issue and seems it’s not a bug. Aspose.Words follows MS Word behavior here. For example, please try the following VBA snippet:

ActiveDocument.Bookmarks("Cooling_Sorgente_Acqua").Range.text = ""
MsgBox (ActiveDocument.Bookmarks("Cooling_Sorgente_Acqua").Range.text) 

It produces the same output as Aspose.Words does. So we are going to close this defect as not a bug.

Thanks Alexey.
The problem was that bookmarks containing more rows in the same table are not correctly removed. Are you telling me that also VBA can’t remove correctly this kind of bookmarks?

Please find in attachment a word with a VBA macro. I added two bk in the table, the first one is not deleted using Range.Delete command, while the second is correctly removed using Range.Cells.Delete.

Finally why version 18.1 that I stil use is working perfectly with the same code? I think you should investigate it…

Tomorrow we will test the same remove command with Aspose on this file with version 18.1 and 22.

Let me know

Test_RemoveMultipleRowsTable.docx (17.5 KB)

@ceck I have forwarded the provided information to the development team. We will let you know once there is more information for you.

Hi Alexey

please find a definitive example of the bug in the linked C# project (I removed the licence files, please re-add it) to be supplied to your team.

There are only 4 bookmark. Please look at “table3” bookmark which should remove 4 rows in a table which are orange highlighted.
If you use Aspose 22.8, the bookmark is removed but the rows are not. Instead, using Aspose 18.1, all is working and the rows are removed. Please check the resulting files Test_RemoveMultipleRowsTable_save_v18.docx and Test_RemoveMultipleRowsTable_save_v22.docx in the Debug folder.

I analyzed the code and I noticed that for this bookmark

Aspose.Words.Node.NodeTypeToString(bm.BookmarkStart.ParentNode.ParentNode.ParentNode.NodeType = “Selection” for Aspose 22.8 and “Row” for 18.1. This I think is part of the bug.

I can also observe that the problem does not occur for “table2” bookmark, which is apparently rather similar (two rows in a table). In this case, also for versione 22.8 the NodeType = “Row”. Strange, but I found out the difference and demonstrated that:

  • if I create the bookmark clicking+shift on the cell and then out of the table on the right of the last table row selecting the rows (as in “table3” bookmark) the rows are not canceled,

  • instead if I create the bookmark clicking not on the cell but on the left+shift of the first row and then out of the table on the right of the last table row selecting the rows (as in “tablee2” bookmark), the rows are correctly removed.

This is true only for version 22.8 (version 18.1 works independently from how I create the bookmark).

This is the link to the project

https://www.dropbox.com/s/9npvmlfb51oqj52/AsposeTest_simple.zip?dl=0

Please contact me if needed, we can also organize a meeting to show you, if something is not clear.

Best regards

@ceck Thank you for additional information. We will investigate the described behavior and provide you more information.

Forgot to tell you, that VBA works as Aspose 18.1 and removes the bookmark independently from how I create it

1 Like

Hi Alexey,

any news about this bug? Was your team able to isolate the bug I pointed out or do they need more help from my side?
Could you give an hint for a possible date for the version with the bug fixed?
Luca