Microsoft Office Forums

Go Back   Microsoft Office Forums > >

Reply
 
Thread Tools Display Modes
  #1  
Old 07-15-2016, 01:11 PM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2003
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default Detecting that previous character doesn't exist (i.e., present character is first in document)

How do I test whether a variable I've "set" actually exists before testing it in a conditional statement?



I have a loop that iterates through every character in a selection range and performs an operation depending on the content of the previous character (for example, if the previous character is an exclamation point). This works great so long as the selection doesn't include the first character of the document, at which point the macro fails and throws a '91' error. How do I test whether a variable I've set actually exists before testing it in a conditional statement, so that I can avoid this error?

Code:
For Each strChar In Selection.Range.Characters
    Set strPrevChar = strChar.Previous(wdCharacter, 1)
    Set strNextChar = strChar.Next(wdCharacter, 1)
    If strPrevChar <> "!" Then
      ' Perform the operation
    End If
Next strChar
(The If statement throws an error when the first selected character is the first character in the document and strPrevChar is not set because there is no previous character.)
Reply With Quote
  #2  
Old 07-15-2016, 05:22 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

You can either ignore the error and then test for
strPrevChar is Nothing

or test if
Selection.Range.Start > 0

Rather than testing every character that way, it is more efficient to ensure your range won't throw that error before the loop begins.
Code:
Sub wtf()
  Dim rng As Range
  Set rng = Selection.Range
  If rng.Start = 0 Then rng.MoveStart Unit:=wdCharacter, Count:=1
  If rng.End = ActiveDocument.Range.End Then rng.MoveEnd Unit:=wdCharacter, Count:=-1
  For Each strChar In rng.Characters
      Set strPrevChar = strChar.Previous(wdCharacter, 1)
      Set strNextChar = strChar.Next(wdCharacter, 1)
      If strPrevChar <> "!" Then
        ' Perform the operation
      End If
  Next strChar
End Sub
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #3  
Old 07-18-2016, 07:25 AM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Thanks--

Follow-up question: why "declare" the rng variable rather than just always use Selection.Range? (1) It seems like extra code and (2) it actually seems to break the script.

For example, if I do this,

Code:
With Selection.Range.Find ' Get rid of any stricken-through text
    .ClearFormatting 'Is this needed?
    .Replacement.ClearFormatting 'Is this needed?
    .Text = "*"
    .MatchWildcards = True
    .Font.StrikeThrough = True
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
End With
With Selection.Range.Find ' Get rid of any underlining
    .Font.Underline = wdUnderlineSingle
    .Replacement.Font.Underline = wdUnderlineNone
    .MatchWildcards = False
    .Text = ""
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
End With
It works as expected, but if I do this:

Code:
Dim rng As Range
Set rng = Selection.Range
With rng.Find ' Get rid of any stricken-through text
    .ClearFormatting 'Is this needed?
    .Replacement.ClearFormatting 'Is this needed?
    .Text = "*"
    .MatchWildcards = True
    .Font.StrikeThrough = True
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
End With
With rng.Find ' Get rid of any underlining
    .Font.Underline = wdUnderlineSingle
    .Replacement.Font.Underline = wdUnderlineNone
    .MatchWildcards = False
    .Text = ""
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
End With
It doesn't get rid of the underlining.
Reply With Quote
  #4  
Old 07-18-2016, 04:58 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

It was declared because that same range was needed 5 times and the code was completely different to your second question. Declaring a range makes it easier to follow the code and can reduce the number of contextual jumps required by the code. For instance
Selection.Range requires Word to first find out which document is active, then determine the start and finish positions of the selection in that document and then remember that range for the next command. Using a declared range reduces the 'thinking' required by the code.
Working with ranges also reduces the ambiguity of where the 'selection' is located at any time. If your code happens to change the selection: either in the activedocument or because you have opened/activated a different document, the Selection.Range will give a very different result and is probably not what you were expecting.

Now it just so happens that rng.Find is somewhat buggy and when something is found, the rng collapses to the found text. That is why your code doesn't 'find' anything underlined. In that case, you would need to redefine the range before doing the second find.

In answer to your question in the code - I would think that the second find is actually searching for underlined AND strikethrough text since you didn't clear the formatting after the first time. That is the point of the .clearformatting which removes any of the sticky formatting that might already be retained from a previous finds performed by the user prior to your code running. You would need to .clearformatting again to remove the strikethrough condition in the second find before applying the font.underline condition otherwise you are searching for text with both.
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #5  
Old 07-18-2016, 07:22 PM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Quote:
Originally Posted by Guessed View Post
Now it just so happens that rng.Find is somewhat buggy and when something is found, the rng collapses to the found text.
Thanks, good to know.

Quote:
Originally Posted by Guessed View Post
the second find is actually searching for underlined AND strikethrough text
You can try it--it works as desired. The second With statement only searches for underlined text, not underlined + strikethrough.

Which is why I added those comments in the code. The clearformatting statements seem unnecessary.
Reply With Quote
  #6  
Old 07-18-2016, 09:14 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

I believe that the clearformatting is necessary although that doesn't appear to be the case in this instance. Before running the macro, use the regular find/replace dialog to find something formatted a particular way such as Bold or a style perhaps. If you close that dialog and then re-open it, you will see that it remembered this in your previous find. If you then run your macro without clearing those settings the macro has the potential to include those settings in its search. This is why it is good practice to clear this.

However, now that I am testing it, the code seems to ignore those settings which surprises me. In the case of your code, I would have said that you could remove the two lines in the middle
End With
With Selection.Range.Find

since they are not strictly needed but if you do, the strikethrough is ALSO a factor in the second search.

Since you are removing underlining, I would shorten the code and ensure you remove all types of underlining regardless of type. There is no need to search to remove underlining whilst retaining the text
Code:
  With Selection.Range.Find ' Get rid of any stricken-through text
    .ClearFormatting 'Is this needed?
    .Replacement.ClearFormatting 'Is this needed?
    .Text = "*"
    .MatchWildcards = True
    .Font.StrikeThrough = True
    .Replacement.Text = ""
    .Execute Replace:=wdReplaceAll
  End With
  Selection.Range.Font.Underline = wdUnderlineNone    'remove all underlining regardless of type
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #7  
Old 07-18-2016, 09:48 PM
gmayor's Avatar
gmayor gmayor is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2016
Expert
 
Join Date: Aug 2014
Posts: 4,101
gmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud of
Default

Come to that you could simply use
Code:
    With Selection.Font
        .Underline = wdUnderlineNone
        .StrikeThrough = False
    End With
which will remove underlining and strikethough from the selected text. Or for the main story range
Code:
    With ActiveDocument.Range.Font
        .Underline = wdUnderlineNone
        .StrikeThrough = False
    End With
If you want to use .Find then note that this does not limit the search to the end of the selected text, so test for the range being in the selection e.g.
Code:
Dim oRng As Range
    Set oRng = Selection.Range
    With oRng.Find
        .Font.StrikeThrough = True
        Do While .Execute
            If oRng.InRange(Selection.Range) Then
                oRng.Font.StrikeThrough = False
                oRng.Collapse 0
            End If
        Loop
    End With
    Set oRng = Selection.Range 'Reset the range
    With oRng.Find
        .Font.Underline = wdUnderlineSingle
        Do While .Execute
            If oRng.InRange(Selection.Range) Then
                oRng.Font.Underline = wdUnderlineNone
                oRng.Collapse 0
            End If
        Loop
    End With
Or for the whole main story range the test is not required e.g.
Code:
Dim oRng As Range
    Set oRng = ActiveDocument.Range
    With oRng.Find
        .Font.StrikeThrough = True
        Do While .Execute
            oRng.Font.StrikeThrough = False
            oRng.Collapse 0
        Loop
    End With
    Set oRng = ActiveDocument.Range 'Reset the range
    With oRng.Find
        .Font.Underline = wdUnderlineSingle
        Do While .Execute
            oRng.Font.Underline = wdUnderlineNone
            oRng.Collapse 0
        Loop
    End With
__________________
Graham Mayor - MS MVP (Word) (2002-2019)
Visit my web site for more programming tips and ready made processes www.gmayor.com
Reply With Quote
  #8  
Old 07-18-2016, 10:03 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

Graham
The code was deleting strikethrough text and then removing single underlines (but retaining that underlined text). It appears the OP is not a fan of Words Revision Tracking so they are doing it manually.

Your first code sample retains the strikethrough text so that is probably not what they wanted.
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #9  
Old 07-19-2016, 04:26 AM
gmayor's Avatar
gmayor gmayor is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2016
Expert
 
Join Date: Aug 2014
Posts: 4,101
gmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud ofgmayor has much to be proud of
Default

Yes indeed both of my codes sets only remove the strikethrough and not the text itself. It's an easy change to delete the text.

Code:
    With oRng.Find
        .Font.StrikeThrough = True
        Do While .Execute
            oRng.Text = ""
            oRng.Collapse 0
        Loop
    End With
__________________
Graham Mayor - MS MVP (Word) (2002-2019)
Visit my web site for more programming tips and ready made processes www.gmayor.com
Reply With Quote
  #10  
Old 07-19-2016, 06:08 AM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Quote:
Originally Posted by Guessed View Post
Code:
Selection.Range.Font.Underline = wdUnderlineNone    'remove all underlining regardless of type
Haha, thanks, yes, that makes a lot more sense!
Reply With Quote
  #11  
Old 07-19-2016, 06:41 AM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Quote:
Originally Posted by Guessed View Post
It appears the OP is not a fan of Words Revision Tracking so they are doing it manually.
Yes, for certain legal document applications the revision tracking doesn't cut the mustard, and the changes have to be shown in plain old underline and strikethrough. In such a regime you generally don't want stricken-through deleted text abutting right up against underlined inserted text, thus, some whitespace has to come between, as opposed to Word's revision tracking which would not have such whitespace. To make things more complicated, certain deletions have to be denoted by double brackets, as when deleting [[-]] hyphens, dashes, etc., which wouldn't otherwise be distinguishable from deleting whitespace, or otherwise when deleting small sets of characters where strikethrough would not be noticeable (e.g., striking through a single e or 4).

I've been developing a different VBA script that converts Word's revision tracking to legal-document revision format, but it's not perfect yet. I'm particularly having trouble with the part of the script that adds and deletes spaces, as appropriate, around double brackets where they have been inserted as part of the conversion process. Here's my crummy code that doesn't work, in case anyone's really interested. I think I was trying to write this before I understood fully what could be done with wildcard search & replace and I would probably do it differently now.

Code:
    For Each strChar In Selection.Range.Characters 'Add/delete spaces around double brackets
        Set strPrevPrevChar = strChar.Previous(wdCharacter, 2) 'I don't think this works
            MsgBox "Nothing selected or no revisions in selection.", vbOKOnly
        Set strPrevChar = strChar.Previous(wdCharacter, 1)
        Set strNextChar = strChar.Next(wdCharacter, 1)
        Set strNextNextChar = strChar.Next(wdCharacter, 2) 'I don't think this works
        If strChar.Text = "[" And strNextChar.Text = "[" Then 'Opening double bracket
            If strPrevChar.Text <> Chr(32) Then 'Insert leading space before opening double bracket
                strChar.InsertBefore (" ")
            Else 'Make sure there is only one leading space before opening double bracket
                Do While strPrevChar.Text = Chr(32)
                Loop
            End If
            Do While strNextNextChar.Text = Chr(32) 'Delete leading space after opening double bracket
                
            Loop
        ElseIf strChar.Text = "]" And strNextChar.Text = "]" Then 'Closing double bracket
            If strNextNextChar.Text <> Chr(32) Then 'Insert trailing space after closing double bracket
            End If
        End If
    Next strChar
PS
Thanks everybody for your help. Really fantastic answers here.
Reply With Quote
  #12  
Old 07-19-2016, 04:30 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

Unfortunately, with the wonder of hindsight, just about everybodies code could be improved once its been created. Looping through every character is horrendously slow and it appears you are probably doing this more than once so that magnifies it.

It might be worth taking a step back and looking at your requirements once again to see how to make the code really efficient. I would recommend getting away from Selections and strings in favour of ranges.

For the job you describe here it would be WAY faster to do find/replaces instead of looping characters.
eg with wildcards on find "([! ])\[\[" and replace with "\1 [[" to ensure there is always a space in front of any opening double square brackets
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #13  
Old 07-20-2016, 05:02 AM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Quote:
Originally Posted by Guessed View Post
For the job you describe here it would be WAY faster to do find/replaces instead of looping characters.
eg with wildcards on find "([! ])\[\[" and replace with "\1 [[" to ensure there is always a space in front of any opening double square brackets
That's great advice. Thank you!

EDIT: but it adds a space between deleted content and punctuation outside the deleted content, so I might end up with, for example, [[4]] , instead of [[4]], which is what is desired.

Maybe a cheap fix would be to only add whitespace (where it doesn't exist) between underlined text and [[, or between ]] and underlined text? That way it would at least fix [[this]]sort of thing when [[this]] sort of thing is desired.

Last edited by Robert K S; 07-20-2016 at 07:55 AM.
Reply With Quote
  #14  
Old 07-20-2016, 05:39 PM
Guessed's Avatar
Guessed Guessed is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 10 Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2013
Expert
 
Join Date: Mar 2010
Location: Canberra/Melbourne Australia
Posts: 3,969
Guessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant futureGuessed has a brilliant future
Default

To avoid finding closing double braces followed by punctuation you could search for
"\]\]([a-zA-Z0-9])"

Using Find to hit only braces followed by underlined text won't work because you can't specify which parts of the found string need the underline - its all or nothing.
__________________
Andrew Lockton
Chrysalis Design, Melbourne Australia
Reply With Quote
  #15  
Old 07-20-2016, 06:35 PM
Robert K S Robert K S is offline Detecting that previous character doesn't exist (i.e., present character is first in document) Windows 7 64bit Detecting that previous character doesn't exist (i.e., present character is first in document) Office 2007
Novice
Detecting that previous character doesn't exist (i.e., present character is first in document)
 
Join Date: Jul 2016
Location: Cleveland, Ohio
Posts: 10
Robert K S is on a distinguished road
Default

Quote:
Originally Posted by Guessed View Post
Using Find to hit only braces followed by underlined text won't work because you can't specify which parts of the found string need the underline - its all or nothing.
Yeah, that's what I figured. Thanks for taking a look. You're the best.
Reply With Quote
Reply



Similar Threads
Thread Thread Starter Forum Replies Last Post
Detecting that previous character doesn't exist (i.e., present character is first in document) Macro to list all character styles in a document ljd108 Word VBA 8 10-06-2022 01:56 PM
Detecting that previous character doesn't exist (i.e., present character is first in document) Replace a random character with the same character RickLegrand Word 7 07-23-2015 06:35 PM
Detecting that previous character doesn't exist (i.e., present character is first in document) How can select from a specific character to another character mohsen.amiri Word 2 02-19-2015 11:38 PM
Detecting that previous character doesn't exist (i.e., present character is first in document) Regular (roman) character style doesn't change text to roman kcbenson Word 2 10-16-2014 01:31 PM
Detecting that previous character doesn't exist (i.e., present character is first in document) Finding or searching ^ character in word document shahin3121 Word 2 03-05-2012 06:16 PM

Other Forums: Access Forums

All times are GMT -7. The time now is 07:56 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Search Engine Optimisation provided by DragonByte SEO (Lite) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
MSOfficeForums.com is not affiliated with Microsoft