This is a migrated thread and some comments may be shown as answers.

RadFlowDocumenteditor: Delete everything between two bookmarks

7 Answers 795 Views
WordsProcessing
This is a migrated thread and some comments may be shown as answers.
Manu
Top achievements
Rank 1
Manu asked on 30 Dec 2018, 02:45 PM

Hi,

I import an existing word-doc that contains several bookmarks:

// import word-doc to RadFlowDocument
RadFlowDocument templateDocument = provider.Import(fileMemoryStream);
// edit RadFlowDocument
RadFlowDocumentEditor editor = new RadFlowDocumentEditor(templateDocument);

 

Then I modify the RadFlowDocument (inserting text, tables, ... at certain positions) by using the RadFlowDocumentEditor.

Finally, I need to remove/delete some parts of the document that are between two bookmarks. I have searched the documentation and forums but could not find a way how to do this.

Any help would be appreciated.

Regards, Manu

 

7 Answers, 1 is accepted

Sort by
0
Tanya
Telerik team
answered on 02 Jan 2019, 03:44 PM
Hello Manu,

To achieve that, you will need to obtain the start of the bookmark and start deleting the following elements until you reach the start of the next bookmark. Here is a sample code of how this could be achieved:
RadFlowDocumentEditor editor = new RadFlowDocumentEditor(this.document);
editor.DeleteBookmark("_GoBack"); // When working in MS Word, an additional bookmark is inserted in the document to preserve the caret position and restore it the next time the users open the document. This line removes this bookmark.
var bookmarkStart = this.document.EnumerateChildrenOfType<BookmarkRangeStart>().First();
InlineBase currentElement = bookmarkStart;
var currentParagraph = currentElement.Paragraph;
 
var currentIndex = currentParagraph.Inlines.IndexOf(currentElement) + 1;
currentElement = currentParagraph.Inlines[currentIndex];
 
while (!(currentElement is BookmarkRangeStart))
{
    currentIndex = currentParagraph.Inlines.IndexOf(currentElement);
    if (!(currentElement is AnnotationMarkerBase))
    {
 
        currentElement.Paragraph.Inlines.Remove(currentElement);
        if (currentParagraph.Inlines.Count == 0)
        {
 
            var currentSection = currentParagraph.Parent as Section;
            var nextParagraphIndex = currentSection.Blocks.IndexOf(currentParagraph);
            currentSection.Blocks.Remove(currentParagraph);
            currentParagraph = currentSection.Blocks[nextParagraphIndex] as Paragraph;
            currentElement = currentParagraph.Inlines.First();
            currentIndex = 0;
            continue;
        }
    }
    else
    {
        currentIndex++;
    }
 
    if (currentIndex < currentParagraph.Inlines.Count)
    {
        currentElement = currentParagraph.Inlines[currentIndex];
    }
    else
    {
        var currentSection = currentParagraph.Parent as Section;
        currentParagraph = currentSection.Blocks[currentSection.Blocks.IndexOf(currentParagraph) + 1] as Paragraph;
        currentElement = currentParagraph.Inlines.First();
    }
 
}
 
Please, note that the sample removes the content between the first and the second bookmarks in a document and you would most probably need to adjust the code according to the specific requirements of the scenario.

Hope this is helpful. 

Regards,
Tanya
Progress Telerik
Get quickly and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Manu
Top achievements
Rank 1
answered on 02 Jan 2019, 09:28 PM

Hi Tanya,

thank you for your help. Since there are a few other bookmarks between the starter- (first in your code) and the terminal-bookmark (second in your code) in my word-doc, I have to adjust your code.

However, I do not completely understand your code yet. I know how to set the variable for the bookmarkStart (which is the starter-bookmark), but I do not understand with what part(s) of your code the terminal-bookmark is represented.

Could you please help me with this again.

Regards, Manu

 

 

0
Tanya
Telerik team
answered on 07 Jan 2019, 09:09 AM
Hi Manu,

I am sorry if I wasn't clear enough in my previous reply.

The execution of the while-loop is terminated when the logic finds the next BookmarkRangeStart object. This is defined in the condition of the while-loop:
while (!(currentElement is BookmarkRangeStart))

In other words, the code begins executing with the bookmark start which is passed to it as the first bookmark and ends the removing of content when it gets to the next bookmark start. If you pass the fourth bookmark start, the logic should remove the content up to the next (fifth) bookmark start.

Hope this makes things clear.

Regards,
Tanya
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Manu
Top achievements
Rank 1
answered on 07 Jan 2019, 02:08 PM

Hi Tanya,

I almost got it to work. In my test document I have 5 bookmarks (each on an extra row at the left page margin followed by some text and a paragraph marker).

Below my code for removing everything between the first and fith bookmark:

var bookmarkFirst = editor.Document.EnumerateChildrenOfType<BookmarkRangeStart>().Where(rangeStart => rangeStart.Bookmark.Name == "First").FirstOrDefault();
var bookmarkLast = editor.Document.EnumerateChildrenOfType<BookmarkRangeStart>().Where(rangeStart => rangeStart.Bookmark.Name == "Fith").FirstOrDefault();
 
InlineBase currentElement = bookmarkFirst;
var currentParagraph = currentElement.Paragraph;
var currentIndex = currentParagraph.Inlines.IndexOf(currentElement) + 1;
currentElement = currentParagraph.Inlines[currentIndex];
 
InlineBase lastElement = bookmarkLast;
var lastParagraph = lastElement.Paragraph;
var lastIndex = lastParagraph.Inlines.IndexOf(lastElement) + 1;
lastElement = lastParagraph.Inlines[lastIndex];
 
 
//while (!(currentElement is BookmarkRangeStart))
while ((currentElement != lastElement))
 
    {
        currentIndex = currentParagraph.Inlines.IndexOf(currentElement);
    if (!(currentElement is AnnotationMarkerBase))
    {
 
        currentElement.Paragraph.Inlines.Remove(currentElement);
        if (currentParagraph.Inlines.Count == 0)
        {
 
            var currentSection = currentParagraph.Parent as Section;
            var nextParagraphIndex = currentSection.Blocks.IndexOf(currentParagraph);
            currentSection.Blocks.Remove(currentParagraph);
            currentParagraph = currentSection.Blocks[nextParagraphIndex] as Paragraph;
            currentElement = currentParagraph.Inlines.First();
            currentIndex = 0;
            continue;
        }
    }
    else
    {
        currentIndex++;
    }
 
    if (currentIndex < currentParagraph.Inlines.Count)
    {
        currentElement = currentParagraph.Inlines[currentIndex];
    }
    else
    {
        var currentSection = currentParagraph.Parent as Section;
        currentParagraph = currentSection.Blocks[currentSection.Blocks.IndexOf(currentParagraph) + 1] as Paragraph;
        currentElement = currentParagraph.Inlines.First();
    }
}

 

I have several issues left:

  • The code removes all text between bookmarkFirst and bookmarkLast, but the bookmarks in between (2nd,3rd and 4th) including the corresponding empty paragraphs are left. I need to remove 'everything' (tables, paragraphs, text, ...) in between.
  • When a table or an empty paragraph is in between bookmarkFirst and bookmarkLast I get an error at:
else
{
    var currentSection = currentParagraph.Parent as Section;
    currentParagraph = currentSection.Blocks[currentSection.Blocks.IndexOf(currentParagraph) + 1] as Paragraph;
    currentElement = currentParagraph.Inlines.First(); // here the error happens
}

 

I also tested your original code and obtained the same errors when a table or an empty paragraph is in between bookmarkStarter and the next bookmark.

I hope, you can find a fix for these issues.

Regards, Manu

 

0
Tanya
Telerik team
answered on 10 Jan 2019, 12:03 PM
Hi Manu,

The error you are getting is as a result of the fact that the Inlines collection of the paragraph is empty and an element cannot be obtained from it. The other error is thrown because the element being currently iterated is not a Paragraph but a Table, resulting in a null value for the currentParagraph variable. I modified the code a bit to avoid similar issues. You can find it attached to this reply.

Hope this helps.

Regards,
Tanya
Progress Telerik
Get quickly and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Manu
Top achievements
Rank 1
answered on 11 Jan 2019, 11:08 AM

Hi Tanya,

thank you again. Now it works.

As a side-note:

editor.DeleteBookmark("_GoBack")

always gives an error with my Word-doc template (that I import to RadFlowEditor) regardless of how often I have modified/saved it.

Regards, Manu

0
Tanya
Telerik team
answered on 15 Jan 2019, 01:45 PM
Hi Manu,

Thank you for writing back - I am happy to hear that everything is now working as expected.

I added the invocation of the DeleteBookmark() at the beginning just to ensure there are no additional bookmarks added by MS Word. In case the documents you are working with don't include such objects, you can remove this line. Or, if you would like to preserve it, you can check if such a bookmark is available before trying to delete it.

Hope this is helpful.

Regards,
Tanya
Progress Telerik
Get quickly and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
WordsProcessing
Asked by
Manu
Top achievements
Rank 1
Answers by
Tanya
Telerik team
Manu
Top achievements
Rank 1
Share this question
or