none
Preventing range boundaries from shifting on edit RRS feed

  • Question

  • Hi there,

    I am having problems with Word.Range boundaries sometimes shifting without warning.  If I have two ranges, one of which contains an entire phrase and one of which contains a word at one end, thus:

    [This is a sentence ending in a [word]]

    and I edit the text of [word] to be something else, say [string], what I appear to get as a result is

    [This is a sentence ending in a ][string]

    In other words, the outer range has jumped "out of the way".  This only happens when one range is at the edge of another.  Is there a way to prevent this from happening?

    Thanks!


    Andrew
    _|_.
    |..|
    |_.|_/
    Sunday, February 13, 2011 1:06 PM

Answers

  • Hi Andrew

    When you "edit a range" by changing the characters it contains in the background a Delete is being performed, then an Insert. So, in essence, the End point of the larger range (that you're not addressing) is being deleted - that moves the End point back to the last character before the range being edited.

    That means you need a work-around. Either the one Doug suggests or, if you can anticipate this is going to happen, by extending the End point of the outside range by one character (so that it won't be deleted when you assign new text to the inside range).

    Ranges are very tricky and volatile things... <sigh>


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by Bruce Song Tuesday, March 8, 2011 3:30 AM
    Monday, February 14, 2011 3:52 PM
    Moderator
  • Ultimately I have been forced to reassert the .End and .Start properties manually; fortunately I only ever create these smaller ranges using a method call on a larger one (inside my wrapper object) so I can detect identical .Start and .End properties then and link the objects so one updates the other.  It won't currently deal with my three-range problem but fortunately, at least at the moment, it never has to; I can't think of a way to do that without creating circular references though!

    Thanks all :)


    Andrew
    _|_.
    |..|
    |_.|_/
    • Marked as answer by Bruce Song Tuesday, March 8, 2011 3:30 AM
    Tuesday, February 15, 2011 9:56 AM

All replies

  • Use code like:

    Dim range1 As Range, range2 As Range
    With ActiveDocument
       Set range1 = .Paragraphs(1).Range
       Set range2 = range1.Duplicate
       range2.Start = range2.Start + InStrRev(range2, " ")
       range2.End = range2.End - 1
       range2.Text = "some new text"
       range1.End = range2.End
       range1.Select
    End With
     -- Hope this helps.

    Doug Robbins - Word MVP,
    dkr[atsymbol]mvps[dot]org
    Posted via the Community Bridge

    "andrewwyld" wrote in message news:deca7c07-46e2-440f-b9be-1e35eb83c3a5@communitybridge.codeplex.com...

    Hi there,

    I am having problems with Word.Range boundaries sometimes shifting without warning.  If I have two ranges, one of which contains an entire phrase and one of which contains a word at one end, thus:

    [This is a sentence ending in a [word]]

    and I edit the text of [word] to be something else, say [string], what I appear to get as a result is

    [This is a sentence ending in a ][string]

    In other words, the outer range has jumped "out of the way".  This only happens when one range is at the edge of another.  Is there a way to prevent this from happening?

    Thanks!


    Andrew

    _|_.
    |..|
    |_.|_/

    Doug Robbins - Word MVP dkr[atsymbol]mvps[dot]org
    Sunday, February 13, 2011 8:23 PM
  • That isn't quite what I meant; for a start I might want to select

    [This sentence ends with a [noun phrase]]

    and in any case I am getting it to select the areas I want without any difficulty (well ... not without any difficulty but that's a different story for a different time).

    Secondly, I know I could always set the .End property of the outer Range to be the same as the inner one, but the two are pretty remote from each other in my code and in fact I want to make sure any Word.Range whose .End property is the same as another's, should have the .End property update to surround whatever I put in any of those Word.Range elements.  Taking a concrete example, suppose I have a document with four selected Word.Range objects:

    [This is the first sentence.  ][This is the second sentence and it ends in [boldface and the last word is [chicken] ]]

    So here I have a range around the whole second sentence, the boldface region, and the last word (chicken).  All of these have the same .End property.

    If I change the first sentence to [This is the first sentence and it's quite dull.  ] I would obviously expect all the .Start and .End properties of these Word.Range objects to update automatically, as indeed I find they do.  However, if I change [chicken] to [wood-pigeon] the .End property of the former Sentence range and the boldface range will change to

    [This is the second sentence and it ends in [boldface and the last word is ]][wood-pigeon]

    Having said that, if two .Ranges overlapped [like [ these] two] I can understand why the .End of the first would jump out of the way if you edited the second, but this is not the case here: the two have the same .End property.  If what I would like is impossible, I will of course work around it ....


    Andrew
    _|_.
    |..|
    |_.|_/
    Monday, February 14, 2011 10:39 AM
  • Hi Andrew

    When you "edit a range" by changing the characters it contains in the background a Delete is being performed, then an Insert. So, in essence, the End point of the larger range (that you're not addressing) is being deleted - that moves the End point back to the last character before the range being edited.

    That means you need a work-around. Either the one Doug suggests or, if you can anticipate this is going to happen, by extending the End point of the outside range by one character (so that it won't be deleted when you assign new text to the inside range).

    Ranges are very tricky and volatile things... <sigh>


    Cindy Meister, VSTO/Word MVP
    • Marked as answer by Bruce Song Tuesday, March 8, 2011 3:30 AM
    Monday, February 14, 2011 3:52 PM
    Moderator
  • OK, that makes sense.  Currently I am just doing

    Range.Text = someStringIFoundLyingAround;
    

    but suppose I replaced this with

    int Start = Range.Start + someStringIFoundLyingAround.Length;
    int End = Range.End + someStringIFoundLyingAround.Length;
    object length = someStringIFoundLyringAround.Length;
    Range2 = Range.Duplicate;
    Range.InsertBefore(someStringIFoundLyingAround);
    Range2.End = End;
    Range2.Start = Start;
    Range2.Delete(ref WdUnits.wdCharacter, length);
    

    which is a horrible piece of code but I sort of worked it out on the fly.  What it's intended to do is insert the new text before the range end, then delete the text from the other side.

    Would an InsertBefore method create problems if the inner range and outer range were aligned at the start, though? Perhaps the best approach is to insert padding before and after, insert the interior text, then remove the padding?

     


    Andrew
    _|_.
    |..|
    |_.|_/
    Monday, February 14, 2011 4:11 PM
  • Well what I tried was

        public override void setstring(string newstring)
        {
          object unity = 1;
          object character = Word.WdUnits.wdCharacter;
          //add spacers to make sure things work
          data.InsertBefore("["); //operation one
          data.InsertAfter("]"); //operation two
    
          //mark the spacers
          Word.Range First = data.Duplicate;
          Word.Range Last = data.Duplicate;
    
          //move data inside the spacers
          data.Start++;
          data.End--;
    
          //set the data text
          data.Text = newstring; //operation three
    
          //shift and empty the spacers
          First.End = First.Start + 1;
          Last.Start = Last.End - 1;
          First.Text = ""; //operation four
          Last.Text = ""; //operation five
    
          storedstring = newstring;
          storedXMLstring = data.WordOpenXML;
        }
    

    and it did not work.  No.  Although it does mean I would have to call Word.Undo five times every time I undo an edit from our tool, and anyone manually undoing our changes would notice a lot of volatile square brackets.

    I guess it's manually adjusting Start and End properties or nothing!

    Thanks anyway though ....


    Andrew
    _|_.
    |..|
    |_.|_/
    Monday, February 14, 2011 5:45 PM
  • Oh, for context data is the Word.Range inside my object and I wrote this class with the intention of porting it to lots of versions of Word, hence the "override".  storedstring and storedXMLstring are probably self-explanatory!

    Andrew
    _|_.
    |..|
    |_.|_/
    Monday, February 14, 2011 5:46 PM
  • Ultimately I have been forced to reassert the .End and .Start properties manually; fortunately I only ever create these smaller ranges using a method call on a larger one (inside my wrapper object) so I can detect identical .Start and .End properties then and link the objects so one updates the other.  It won't currently deal with my three-range problem but fortunately, at least at the moment, it never has to; I can't think of a way to do that without creating circular references though!

    Thanks all :)


    Andrew
    _|_.
    |..|
    |_.|_/
    • Marked as answer by Bruce Song Tuesday, March 8, 2011 3:30 AM
    Tuesday, February 15, 2011 9:56 AM