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

RadDocument-How to insert RichTextEdit box content in middle of a section without adding a new section and without messing up table of contents?

11 Answers 733 Views
RichTextBox
This is a migrated thread and some comments may be shown as answers.
C
Top achievements
Rank 1
C asked on 01 Dec 2014, 11:01 PM
How to insert contents of a RichTextEdit box into the middle of a section in a RadDocument without adding a new section and without messing up the Table of Contents?

This will let the Table of Contents entries and page, header/footer to remain consistent throughout the document.

We've tried two ways to do this and both of them mess up the Table of Contents.  It erroneously removes entries from the Table of Contents. 

- InputDoc is the input MS Word docx document to copy from
- InputSection is the first section from InputDoc
- DestinationSection is the last Section added to the destination document.

Method 1 Tried: Use Block.DeepCopy()

Foreach (Block blk in inputSection.Blocks)
{
    Block blkTemp =blk.CreateDeepCopy() as Block;
    destinationSection.Blocks.Add(blockToInsert);
}

Method 2 Tried: Insert DocumentFragment()

inputDocument.Selection.SelectAll();
destinationDocument.CaretPosition.MoveToLastPositionInDocument();
RadDocumentEditor ed = new RadDocumentEditor(destinationDocument);
ed.InsertFragment(frag);

For method 2, how would one select  only the blocks under the first section
without selecting the first section.

.
Our application is a document assembly one which outputs a
Microsoft Word docs in the following format based on user preferences:

1. Title page
2. Table of Contents (each section has a numbered entry in the TOC, individual tables/images in the section also have numbered TOC entries)
3. One or more generated sections each containing a mix of tables and images
4. A custom section (see below)
5. One or more generated sections each containing a mix of tables and images
6. A custom section (see below)
7. One or more generated sections each containing a mix of tables and images
8. A custom section (see below)

Custom Section:

 - Each custom section is saved as docx files to disk 
 - Each custom section will be inserted back into the final output file
 - A custom section may be created days before the final document is assembled 
 - There may not be an active RichTextBox control loaded for a custom section when the final docx document is created
 - The custom section has only one section in it - it is not an arbitrary Word document
 - The custom section has a limited subset of functionality including text size, text color, bold, italic, text font, ...

The document is created in C# without any XAML.
The Table of Contents is a multi-level numbered list

Our application is a scientific one needing to output a mix of computed results as tables/graphs plus one or more user entered 1 to 2 page narratives.  Each narrative needs to support basic text formatting (font, font size, color, background color, bold/italic/etc, superscript, subscript, ...).

 

 

11 Answers, 1 is accepted

Sort by
0
C
Top achievements
Rank 1
answered on 03 Dec 2014, 10:32 PM
Here are the methods we've tried.  Each of them messes up the Table of Contents.

//Method 1 - deep copy blocks and add them to the document
Section destinationSection = destinationDocument.Sections.Last();

int blockCtr = 0;
while ((sec.Blocks.Count > 0) && (blockCtr < 5000)) //limit to 5,000 blocks
{
    ++blockCtr;
     var blockTmp = sec.Blocks.First();
     if (blockTmp != null)
    {
          Block blockToInsert = blockTmp.CreateDeepCopy() as Block; //need to create deep copy to keep block is in multiple lists exception
          sec.Blocks.Remove(blockTmp); //block cannot be in two lists at the same time
          destinationSection.Blocks.Add(blockToInsert);
     }
}

//-------------------------------------------------------------------------------------------------
//Method 2 - Select all sections in the document and insert it at the last position in the current RadDocument
doc.Selection.SelectAll();
DocumentFragment frag = new DocumentFragment(doc.Selection);
destinationDocument.CaretPosition.MoveToLastPositionInDocument();
RadDocumentEditor ed = new RadDocumentEditor(destinationDocument);
ed.InsertFragment(frag);

//-------------------------------------------------------------------------------------------------
//Method 2b - Measure document to insert, select all sections in the document and insert it at the last position in the current RadDocument
//doc.LayoutMode = DocumentLayoutMode.Paged; //may need to set layout mode to paged
doc.MeasureAndArrangeInDefaultSize();
doc.Selection.SelectAll();
DocumentFragment frag = new DocumentFragment(doc.Selection);
destinationDocument.CaretPosition.MoveToLastPositionInDocument();
RadDocumentEditor ed = new RadDocumentEditor(destinationDocument);
ed.InsertFragment(frag);


//-------------------------------------------------------------------------------------------------
//Method 3 - Select all sections in the document, copies them and insert it at the last position in the current RadDocument
doc.Selection.SelectAll();
DocumentFragment frag = doc.Selection.CopySelectedDocumentElements();
destinationDocument.CaretPosition.MoveToLastPositionInDocument();
RadDocumentEditor ed = new RadDocumentEditor(destinationDocument);
ed.InsertFragment(frag);

None of these methods work.
0
C
Top achievements
Rank 1
answered on 03 Dec 2014, 10:35 PM
0
C
Top achievements
Rank 1
answered on 03 Dec 2014, 10:54 PM
We are using UI for WPF, Telerik.Windows.Documents.dll version 2014.2.617.40.

- It is a document assembly application with some machine generated sections and some user entered sections.
- All content is put together in C# code without an active RichTextBox control.
- Each section in the MS Word docx file has a header and footer and a table of contents entry
- The table of contents is a list with level 1 entries being the section names and level 2 entries being the individual items in a section
- The contents of each section may be machine generated tables or imported from word docx files.
- The imported word docx files are basic formatted text saved at an earlier time by the user (font, font color, bold/italic, font size)

We guess that the insert fragment call inserts the section from the .docx file to include instead of just the blocks within the section.  This may mess up the Table of Contents, header and footer since they are tied to the section.

What is the preferred way to do this?
0
C
Top achievements
Rank 1
answered on 03 Dec 2014, 11:25 PM
We are following this basic logic.

1. Create the RadDocument with LayoutMode = DocumentLayoutMode.Paged
2. Setup page header and footer - Creates Telerik.Windows.Documents.Header and Telerik.Windows.Documents.Footer objects but does not hook them to anything
3. Create a table of contents (TOC) section
        Section tocSection = new Section();
4. Creates a list style for the TOC
5. Create a toc list
        DocumentList tocList = new DocumentList( listStyle, document )
6. Add headers/footers to table of contents section created in step 3
        tocSection.Headers.Default = ...
  tocSection.Footers.Default = ...
7. Add TOC section to the document
       document.Sections.Add(tocSection);

8. Add sections to the document
       Each section is created in the same way
            Section s = new Section()
         s.Headers.Defauilt = ...
         s.Footers.Defauilt = ...
   
         //Add heading block for the section
        Paragraph p = new Paragraph() { Sylename = RadDocumentDefaultStyles.GetHeadingStyleNameByIndex(1)  };
        p.Inlines.Add(new Span("heading text string to put into TOC");   //text depends on the section
        p.ListId = tocList.ID;
   
        s.Blocks.Add( p);
    
           //Add content to the section 
          //Add heading block for the table in the section
          Paragraph p = new Paragraph() { Sylename = RadDocumentDefaultStyles.GetHeadingStyleNameByIndex(2)  };
        p.Inlines.Add(new Span("table heading string text to put into TOC");   //text depends on the table
        p.ListId = tocList.ID;
    
     s.Blocks.Add(p);
     Table t = ... generate table for the data
     s.Blocks.Add(t);    

        ... Add more content to the section of a TOC heading string followed by a table

9. Add section to the document
...
12. Read in word docx file from disk entered by user (one section with limited formatted text), create new section with header, footer TOC entry and insert the contents of the word docx file (but not the section) into the output document.

N. Write the RadDocument to disk using word docx format provider
    
0
Petya
Telerik team
answered on 04 Dec 2014, 06:17 PM
Hello,

Could you please provide more information regarding how exactly is the table of contents affected by the insertion of DocumentFragment? I'm having a hard time understanding the exact issue that you are encountering.

Generally speaking, RadDocument can be in two states - a measured one (usually when the document is shown in RadRichTextBox) and a non-measured one. Depending on the state, you can either use the API of RadRichTextBox and RadDocumentEditor, or use the collections of document elements like Section.Blocks, Paragraph.Inlines etc.

When it comes to adding the contents of one document to another we usually advise creating a DocumentFragment and inserting it. However, with what I said in my previous reply, the API that allows inserting fragments is used for measured documents and if your document is not measured, the InsertFragment() method will do this for you. What this means is that from this point on you should not use the collections of document elements to add/remove content, as this might cause unexpected behavior including invalid document structures.

On the other hand, copying all blocks from one document and adding them to another would not work, as it would not preserve certain properties, for example lists. Please let us know precisely what are the issue you are facing with document fragments and we will do our best to assist you further.

Regards,
Petya
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
C
Top achievements
Rank 1
answered on 08 Dec 2014, 05:47 PM
Hi, 

Based on your post, thank you, there are three ways to add content to a RadDocument 

  1. Use the API of RadRichTextbox
  2. Use the API of RadDocumentEditor
  3. Use the collection of document elements (section, blocks, paragraph, span, ...)

From your post, the document mode is either measured or not measured.  
- If the document is not measured, then the collection of document elements (sections, blocks, paragraphs, ...) may be manipulated. 
- If the document  is measured, the collection of document elements (sections blocks, paragraphs, ...) may not be manipulated.

We are using the collection of document elements (#3) and need to insert a simple docx file in the middle of our document as our document is being generated. 

We cannot use the API of RadRichTextBox (#1) because the document is generated from C# code (no xaml) and has no RadRichTextBox editor control created.

- The generation order is dynamic depending on the application data and our generated document contains
    - Header section
    - Table of Contents section
    - Content section A
    - Content section B
    - Content section C
    - Content section D
    ...
    - Content section Z
    end of document

Each content section may one of two types data dependant:
   - Pre built - A canned section generated by our application (may contain tables, images, text, nested tables, images nested in tables...)
        - The table of contents header text comes from a varchar field stored in a database row
        - Tables may have nested images and nested tables with nested images
 - Custom - Comes from a docx file stored as a binary blob in a database row
        - The custom section contains notes entered by the user at an earlier time
        - The table of contents header text for a custom section comes from a varchar field stored in the same database row
        - The table of contents header text for a custom section does not come from the docx file to be inserted

The docx files to be inserted should have one section with tables, paragraphs, lists and basic text formatting.

Are the options for inserting the docx as follows?
  1. Use RadDocumentEditor API
       - Convert our other code to use RadDocumentEditor API and not use the collection of document elements (sections, blocks, paragraphs, spans, ...)
   2.  Copy the blocks over from the document fragment (docx to insert)
          - Use create deep copy
    - Updating list ID values to ensure they do not exist in the target document
   3. Copy the blocks over from the document fragment (docx to insert)
       - Loop over the objects in the document fragment and
          - Create a new object for each one in the fragment.
          - Create properties for the new object based on properties of the one in the fragment


0
C
Top achievements
Rank 1
answered on 09 Dec 2014, 05:06 PM
I've created a support ticket for this.
0
C
Top achievements
Rank 1
answered on 09 Dec 2014, 05:18 PM
Copying objects block by block, section by section, paragraph by paragraph is similar to this forum post
http://www.telerik.com/forums/paste-plain-text
​
0
Petya
Telerik team
answered on 11 Dec 2014, 04:37 PM
Hi,

Like I said in my previous reply and the support ticket you started on the topic, your best option is to create DocumentFragments from the documents you need to insert and use the API of RadDocumentEditor. There is a similar example in our SDK repository and the public item related to genuine document merging functionality is available here.

Regards,
Petya
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
vahid
Top achievements
Rank 1
answered on 07 Jun 2016, 02:22 AM

Hi

How can I add a rtf text at the beginning or any other place of an existing Rad Document?

0
Boyko
Telerik team
answered on 09 Jun 2016, 12:22 PM
Hi Vahid,

You can import an RTF document and insert it in existing RadDocument as DocumentFragment. The position of the inserted content could be changed using the DocumentPosition class. Here is a sample code how you could import a document and insert its content at the beginning of the existing RadDocument:

RtfFormatProvider provider = new RtfFormatProvider();
RadDocument importedDocument = null;
 
using (Stream str = GetStreamFromFile("RtfDocument.rtf"))
{
    importedDocument = provider.Import(str);
}
 
importedDocument.Selection.SelectAll();
DocumentFragment frag = new DocumentFragment(importedDocument.Selection);
 
RadDocumentEditor editor = new RadDocumentEditor(existingRadDocument);
DocumentPosition position = new DocumentPosition(existingRadDocument);
position.MoveToFirstPositionInDocument();
editor.InsertFragment(frag, position);

Please let me know how this fits your needs.

Regards,
Boyko
Telerik
Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
Tags
RichTextBox
Asked by
C
Top achievements
Rank 1
Answers by
C
Top achievements
Rank 1
Petya
Telerik team
vahid
Top achievements
Rank 1
Boyko
Telerik team
Share this question
or