none
Paragraphs going over another RRS feed

  • Question

  • Hi,

    I am having some issues concerning Paragraphs.

    Here is my code.

    Range here = this.Content; Paragraph p1 = Paragraphs.Add(here); p1.ID = "p1"; p1.Range.Text = "Level 1"; Paragraph p2 = Paragraphs.Add(p1.After()); p2.ID = "p2"; p2.Range.Text = "Level 1.1"; Range res = p2.After(); Paragraph p3 = Paragraphs.Add(res); p3.ID = "p3"; p3.Range.Text = "Level 1.2";

    Paragraph p4 = Paragraphs.Add(p3.After());
                p4.ID = "p4";
                p4.Range.Text = "Level 1.3";


    I created the following Helper on the Paragraph class.

            public static Range After(this Paragraph par)
            {
                Range result = par.Range;
                result.Start = result.End;
    
                return result;
            }

    This helper is supposed to create a range so that it starts at the end of the paragraph.

    When using this code, the "Level 1.2" is overriding the "Level 1.1". Then the "Level 1.3" is overriding the "Level 1.2"...

    My final result is

    Level 1
    Level 1.3

    Would someone be able to explain me why?

    Sincerely,

    Linvi

    • Edited by linvỉ Thursday, March 28, 2013 3:24 PM
    Thursday, March 28, 2013 1:44 PM

Answers

  • Hi Linvi

    Thank you for providing additional information. Yes, Word's behavior can be odd; mostly, this is due to the Word application making the UI more "intuitive" for the user and to allow for things going on "under the covers". Examples of this are the paragraph marks just before and after tables, paragraph anchor points for graphics and paragraphs associated with section breaks (of which the last paragraph mark at the end of the document is one). All these types of paragraphs are storing additional information and are therefore "protected".

    <<The only workaround I found to do this was to create a string containing "\r: to delimit the different paragraphs and then insert it :>>

    Actually, this isn't so much a workaround as the most efficient way to insert strings of text that don't need to be broken up to accomodate formatting. Whereever you can get away with it, use it :-)

    But I think what would help you most would be to learn how to work with Word's RANGE object. Think of a Range like a Selection, except that 1) the user can't see it and 2) you can have as many Range objects as you need (there can be only one Selection object).

    There are many different ways to accomplish things with Ranges; no particular approach is right or wrong - it's what can get the job done. So you may come across more than one way to do something. I'll be showing you my preference(s)...

    Get a Range at the beginning of the document: I do it like this

      object oCollapseStart = Word.WdCollapseDirection.wdCollapseStart;
      Word.Range rngDocStart = theDocument.Content;
      rngDocStart.Collapse(ref oCollapseStart);

    Being able to return to the Range: It's not efficient to always repeat the above lines. If you know that you'll need to re-use a Range, keep the original Range and create a new Range object to do the actual work

      object oRngStart = rngDocStart.Start;
      object oRngEnd = rngDocStart.End;
      Word.Range rngWork = rngDocStart.Duplicate;
      //Do stuff with rngWork
      //Now put rngWork back to the top of the document
      rngWork = theDocument.Range(ref oRngStart, ref oRngEnd);
      //OR you can use: rngWork.Start = rngDocStart.Start;
      //rngWork.End = rngDocStart.End;

    So, if you want to repeatedly insert text at the top of the document, use a Range object for that point...


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by linvỉ Tuesday, April 2, 2013 8:37 AM
    Monday, April 1, 2013 4:36 PM
    Moderator

All replies

  • Hi Linvi,

    I think you want to add a paragraph as sub paragraph, I find the thread which show how to implement it.

    Thanks


    Thursday, March 28, 2013 4:20 PM
  • Thanks for the information. But my current concern is about learning how to create paragraphs one after another.

    I am currently not concerned by the idea of creating ListTemplates.

    Regards,
    Linvi

    Thursday, March 28, 2013 4:46 PM
  • Hi Linvi,

    You can call Range.InsertParagraphAfter method before you append a new paragraph. I create some code snippets which it can implement your task. you can according to below codes to modify your codes:

     Word.Paragraph p1 = oParas.Add();
                    p1.Range.Text = "Level 1";
                    p1.Range.InsertParagraphAfter();
                   
                    oParaRng.InsertParagraphAfter();
    
                    Word.Paragraph p2 = oParas.Add();
                    p2.Range.Text = "Level 1.1";
                    p2.Range.InsertParagraphAfter();
    
                    Word.Paragraph p3 = oParas.Add();
                    p3.Range.Text = "Level 1.2";
                    p3.Range.InsertParagraphAfter();
    
                    Word.Paragraph p4 = oParas.Add();
                    p4.Range.Text = "Level 1.3";
                    p4.Range.InsertParagraphAfter();

    The final result is :

    Level 1
    Level 1.1
    Level 1.2
    Level 1.3

    The above codes can solve your question. Thanks a lot.

     

    • Proposed as answer by Learning hard Friday, March 29, 2013 3:11 AM
    Friday, March 29, 2013 3:11 AM
  • Well thank you for your answer which is of great help.

    Question : Just one question would be why do we have to both Add a Paragraph to a document and then call InsertParagraphAfter();?

    Problem : Though I am still facing my issue. After I posted, I tried multiple solutions to this list of Paragraph at a specific position in my document. Now by using "this.Application.Selection.Range" I access the right range to insert the first elements but not the ones after.

            public void CreateParagraphs()
            {
                Word.Paragraphs oParas = this.Paragraphs;
                Word.Range oParaRng = this.Application.Selection.Range;
    
                Word.Paragraph p1 = oParas.Add(oParaRng);
                p1.Range.Text = String.Format("Level 1");
                p1.ID = "p1";
                p1.Range.InsertParagraphAfter();
    
                oParaRng.InsertParagraphAfter();
    
                Word.Paragraph p2 = oParas.Add();
                p2.Range.Text = "Level 1.1";
                p2.ID = "p2";
                p2.Range.InsertParagraphAfter();
    
                Word.Paragraph p3 = oParas.Add();
                p3.Range.Text = "Level 1.2";
                p3.ID = "p3";
                p3.Range.InsertParagraphAfter();
    
                Word.Paragraph p4 = oParas.Add();
                p4.Range.Text = "Level 1.3";
                p4.ID = "p4";
                p4.Range.InsertParagraphAfter();
            }

    While doing a first insert, this code is working well. Now if I run a second time the code this will mess up the result.

    Level 1 Level 1 Level 1.1 Level 1.2 Level 1.3 Level 1.1 Level 1.2 Level 1.3

    Thank you for your great help.

    Linvi

    Friday, March 29, 2013 12:43 PM
  • Hi Linvi

    << Just one question would be why do we have to both Add a Paragraph to a document and then call InsertParagraphAfter();?>>

    Basically, you need to do some research in order to discover what behavior the various possibilities have for adding paragraphs to a range in a document. Some commands will replace the Range's content, some will append to the Range and there are others that will prepend to the Range. You have to choose the combination that works for what you need to do. READ THE INFORMATION IN THE LANGUAGE REFERENCE!

    Since no one here can fully understand the task you need to accomplish, in full, all we can do is offer you code snippets. But we cannot solve your problem for you, nor, with our limited understanding of your project, give you "plug in" code. All we can do is provide you with possibilities that you need to adapt to your requirements.

    In this particular case, it's fairly obvious that the problem has to do with the starting point in your document. If you don't change it after the first execution it will start again from the same place. But you never tell us what you expect should happen, nor why.


    Cindy Meister, VSTO/Word MVP, my blog

    Saturday, March 30, 2013 6:52 AM
    Moderator
  • Hi Cindy,

    I am asking the question because even if I read the reference multiple times I cannot solve this issue.

    Current Problem

    Basically I start with this:

    [cursor_location]Level 1
    Level 1.1
    Level 1.2
    Level 1.3


    The cursor location is in position (0,0)

    Now I want add the same text at a specific position (0,0). Result expected being :

    Level 1
    Level 1.1
    Level 1.2
    Level 1.3
    [previous_cursor_location]Level 1
    Level 1.1
    Level 1.2
    Level 1.3

    Now, I have read the different way to insert a Paragraph, and I think I have tried most of the possible solution I have found without being able to perform this simple task. The problem is that the content is not written at the right position. This is why I sent more details in my previous post.

    Workaround

    The only workaround I found to do this was to create a string containing "\r: to delimit the different paragraphs and then insert it :

                Range current = this.Application.Selection.Range;
                List<string> paragraphs = new List<string>();
                paragraphs.Add("Level 1");
                paragraphs.Add("Level 2");
                string res = "";
                foreach (string par_text in paragraphs)
                {
                    res += String.Format("{0}\r", par_text);
                }
                current.Text = res;

    But I am trying to understand the behavior of the Paragraphs so that I do no have to use this kind of workaround.

    Documentation Issues

    Now concerning the doc I find it pretty unclear.

    Range.InsertParagraphAfter()

    For example Range.InsertParagraphAfter() is supposed to :

    "After this method is applied, the range expands to include the new paragraph."

    Well in reality it does not expand. It moves the current range to select the last "\r" character it just inserted.

    Range.Text

    Range.Text is supposed to :

    "When you set this property, the text of the range or selection is replaced."

    Well this behavior in fact depends on whether your are using the property at the end of the document or not.

    If I do change the Text at the end of the document I can do :

    Range.Text = "1";

    While if my current Range is located before another Paragraph I need to do :

    Range.Text = "1\r";

    Well I would have thought that I just needed to check whether or not the current Range is at the end of the document but I am facing some issues with the range overriding my content when setting the Text property.

    This is why I would appreciate some help as I don't understand the behavior of the different ways to insert Text as well as Paragraphs.

    Linvi



    • Edited by linvỉ Saturday, March 30, 2013 5:57 PM
    Saturday, March 30, 2013 5:51 PM
  • Hi Linvi

    Thank you for providing additional information. Yes, Word's behavior can be odd; mostly, this is due to the Word application making the UI more "intuitive" for the user and to allow for things going on "under the covers". Examples of this are the paragraph marks just before and after tables, paragraph anchor points for graphics and paragraphs associated with section breaks (of which the last paragraph mark at the end of the document is one). All these types of paragraphs are storing additional information and are therefore "protected".

    <<The only workaround I found to do this was to create a string containing "\r: to delimit the different paragraphs and then insert it :>>

    Actually, this isn't so much a workaround as the most efficient way to insert strings of text that don't need to be broken up to accomodate formatting. Whereever you can get away with it, use it :-)

    But I think what would help you most would be to learn how to work with Word's RANGE object. Think of a Range like a Selection, except that 1) the user can't see it and 2) you can have as many Range objects as you need (there can be only one Selection object).

    There are many different ways to accomplish things with Ranges; no particular approach is right or wrong - it's what can get the job done. So you may come across more than one way to do something. I'll be showing you my preference(s)...

    Get a Range at the beginning of the document: I do it like this

      object oCollapseStart = Word.WdCollapseDirection.wdCollapseStart;
      Word.Range rngDocStart = theDocument.Content;
      rngDocStart.Collapse(ref oCollapseStart);

    Being able to return to the Range: It's not efficient to always repeat the above lines. If you know that you'll need to re-use a Range, keep the original Range and create a new Range object to do the actual work

      object oRngStart = rngDocStart.Start;
      object oRngEnd = rngDocStart.End;
      Word.Range rngWork = rngDocStart.Duplicate;
      //Do stuff with rngWork
      //Now put rngWork back to the top of the document
      rngWork = theDocument.Range(ref oRngStart, ref oRngEnd);
      //OR you can use: rngWork.Start = rngDocStart.Start;
      //rngWork.End = rngDocStart.End;

    So, if you want to repeatedly insert text at the top of the document, use a Range object for that point...


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by linvỉ Tuesday, April 2, 2013 8:37 AM
    Monday, April 1, 2013 4:36 PM
    Moderator
  • Thank you for these information :)

    Linvi

    Tuesday, April 2, 2013 8:37 AM