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

12 posts, 0 answers
  1. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 01 Dec 2014 Link to this post

    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, ...).

     

     

  2. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 03 Dec 2014 Link to this post

    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.
  3. UI for WPF is Visual Studio 2017 Ready
  4. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 03 Dec 2014 Link to this post

  5. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 03 Dec 2014 Link to this post

    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?
  6. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 03 Dec 2014 Link to this post

    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
        
  7. Petya
    Admin
    Petya avatar
    975 posts

    Posted 04 Dec 2014 Link to this post

    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.

     
  8. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 08 Dec 2014 Link to this post

    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


  9. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 09 Dec 2014 in reply to C Link to this post

    I've created a support ticket for this.
  10. C
    C avatar
    43 posts
    Member since:
    Jul 2014

    Posted 09 Dec 2014 in reply to C Link to this post

    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
  11. Petya
    Admin
    Petya avatar
    975 posts

    Posted 11 Dec 2014 Link to this post

    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.

     
  12. vahid
    vahid avatar
    7 posts
    Member since:
    May 2016

    Posted 06 Jun in reply to Petya Link to this post

    Hi

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

  13. Boyko
    Admin
    Boyko avatar
    17 posts

    Posted 09 Jun Link to this post

    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.
Back to Top
UI for WPF is Visual Studio 2017 Ready