MS Office Forum / Word / Programming / January 2005
Riddle me this
|
|
Thread rating:  |
Greg Maxey - 03 Jan 2005 10:08 GMT Hi,
I have a snippet of code that applies superscript font:
oWord.SetRange Start:=oWord.Start, End:=oWord.End + 1 oWord.Select 'oWord.Font.Superscript = True Selection.Font.Superscript = True
I don't understand why I have to select the range and then apply the formatting to the selection. In another macro I have this code
ActiveDocument.Range.Font.Superscript = True
which I am using to try to solve this riddle. Isn't oWord a Range like ActiveDocument.Range? Why doesn't oWord.Font.Superscript = True work like ActiveDocument.Range.Font.Superscript = True
Here is my complete code:
Sub ScratchMacro1() Dim oPara As Paragraph Dim oWord As Range Dim i As Long Dim myWord As String Dim mySeq As String
myWord = InputBox("Enter the word to find.") mySeq = myWord For Each oPara In ActiveDocument.Paragraphs i = 0 For Each oWord In oPara.Range.Words If Right(oWord, 1) = " " Then oWord.MoveEnd Unit:=wdCharacter, Count:=-1 If LCase(oWord) = LCase(myWord) Then i = i + 1 oWord.Collapse Direction:=wdCollapseStart 'insert field, reset sequence to 1 for first occurence in paragraph If i = 1 Then oWord.Fields.Add Range:=oWord, Type:=wdFieldEmpty, Text:= _ "SEQ " & mySeq & " \r1", PreserveFormatting:=True Else 'insert field oWord.Fields.Add Range:=oWord, Type:=wdFieldEmpty, Text:= _ "SEQ " & mySeq & "", PreserveFormatting:=True End If 'superscript the sequence number oWord.SetRange Start:=oWord.Start, End:=oWord.End + 1 oWord.Select 'oWord.Font.Superscript = True Selection.Font.Superscript = True End If Next Next End Sub
Thanks
 Signature Greg Maxey/Word MVP A Peer in Peer to Peer Support
Helmut Weber - 03 Jan 2005 10:33 GMT Hi Greg,
you are extending the range into the invisible field code.
Try: oWord.SetRange Start:=oWord.Start, End:=oWord.End + 20 oWord.Font.Superscript = True 'stop here
and switch "field codes on" or whatever it is called in English.
Greetings from Bavaria, Germany Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word 2002, Windows 2000
Greg Maxey - 03 Jan 2005 10:33 GMT Hmm, I now know why I am riddled. oWord.Font.Superscript is in fact superscripting the { in my field { SEQ ... } just not the whole field. Apparently oWord.Select is selecting the whole field string. Can anyone offer an explanation?
Thanks.
 Signature Greg Maxey/Word MVP A Peer in Peer to Peer Support
> Hi, > [quoted text clipped - 53 lines] > > Thanks Jonathan West - 03 Jan 2005 10:46 GMT > Hmm, I now know why I am riddled. oWord.Font.Superscript is in fact > superscripting the { in my field { SEQ ... } just not the whole field. > Apparently oWord.Select is selecting the whole field string. Can anyone > offer an explanation? Yes, a Selection cannot select just the opening field brace, so when you attempt to select a range that is defined as an opening field brace, it selects the entire field.
 Signature Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup
Greg - 03 Jan 2005 12:07 GMT Jonathan,
Thanks. So I could do this by adding *\ Charformat to my field code construction, Changing PreserveFormatting to False and extending the range three characters
oWord.SetRange Start:=oWord.Start, End:=oWord.End + 3
to include the S in SEQ then using
oWord.Font.Superscript = True followed by a ActiveDocument.Fields.Update at the end of the code
In my application (I don't really have one I was just playing around) I could use either method. The only reason that I am asking is for futher knowledge regarding efficiency.
Which method if either is more efficient? I mean is it inefficient to physically select a range vice redefining the range? Thanks
Jonathan West - 03 Jan 2005 12:28 GMT > Jonathan, > [quoted text clipped - 15 lines] > Which method if either is more efficient? I mean is it inefficient to > physically select a range vice redefining the range? Thanks Hi Greg,
It depends on what you mean by "efficient"...
The primary aim is to have the program do the required task reliably. The secondary aim is to do this as fast as possible. The reason that speed is only the secondary aim is because it is usless for a program to do the wrong thing very quickly!
Based on your description, it appears that you have two methionds of achieving the same effect. In Word, this is a very common situation, and it often happens that there are even more than two ways of doing many things. In such a situation, the following considerations are worth considering
1. Which method runs faster? 2. Do any methods result in additional side-effects? 3. Will one method work correctly in a wider range of conditions? 4. Is any method easier to code than the others?
These points are not listed in order of importance, because the order of importance will change from case to case.
Regarding speed, it might or might not be important depending on what you are doing and how often it is repeated. A routine that takes 0.1s to run is not going to benefit greatly from optimisation unless it is run repeately inside a loop.
Side-effects are hard to discuss generally, byt the most obvious one in the example you have given is that one method moves the selection point while the other does not. Only you can decide whether that is an important side-effect. If it is, and you still decide for other reasons that using the Selection is a good idea, you can always restore the selection to its original position by using code like this
Dim oStart as Range Set oStart = Selection.Range
' your code here
oStart.Select
Wider ranges of conditions are also hard to talk about, and in many cases there is no different between methods.
Ease of coding is entirely subjective, and depends on your familiarity with different objects and methods and coding styles. If you have code that works, whether written by you or someone else, it is usually easier to use it than to go in for wheel-reinvention.
 Signature Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup
Greg - 03 Jan 2005 13:39 GMT Jonathan,
Thanks for the time you spent with this explanation. You were right. Helmut provided a third solution much simpler and probably faster.
Helmut Weber - 03 Jan 2005 13:10 GMT Hi Greg,
if it comes to speed, how about this one?
Of course, I have omitted some stuff, and the variable names are really very short, ;-) as I am just playing around, too.
Sub SpeedSpeed() Dim p As Paragraph ' object paragraph Dim r As Range ' range of word Dim i As Integer ' counter of words Dim s As String ' string of word s = "let " For Each p In ActiveDocument.Paragraphs i = 0 For Each r In p.Range.Words If s = r Then i = i + 1 r.Collapse Direction:=wdCollapseStart r.Text = CStr(i) r.Font.Superscript = True End If Next Next End Sub
Greetings from Bavaria, Germany Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word 2002, Windows 2000
Greg - 03 Jan 2005 13:38 GMT Helmut,
It misses something like "To let." Changed to this is works great:
Sub SpeedSpeed() Dim p As Paragraph ' object paragraph Dim r As Range ' range of word Dim i As Integer ' counter of words Dim s As String ' string of word s = "let" For Each p In ActiveDocument.Paragraphs i = 0 For Each r In p.Range.Words If Right(r, 1) = " " Then r.MoveEnd Unit:=wdCharacter, Count:=-1 If s = r Then i = i + 1 r.Collapse Direction:=wdCollapseStart r.Text = CStr(i) r.Font.Superscript = True End If Next Next End Sub
Thanks.
Jonathan West - 03 Jan 2005 14:35 GMT > Helmut, > [quoted text clipped - 21 lines] > > Thanks. Hi Greg,
I would strongly recommend that you indent the code inside loops so that you can easily see where loops & branches begin & end. It makes code much easier to understand and follow when you are trying to debug it.
You can read more about this in the following article
The art of defensive programming http://word.mvps.org/FAQs/MacrosVBA/MaintainableCode.htm
Also, Stephen Bullen has written a wonderful free add-in called Smart Indenter which automatically applies a consistent indenting style to all the lines in a routine, module or project. You can find it here
http://www.oaltd.co.uk/Indenter/Default.htm
 Signature Regards Jonathan West - Word MVP www.intelligentdocuments.co.uk Please reply to the newsgroup
Greg - 03 Jan 2005 14:52 GMT Jonathan,
I usually do. I did here but it doesn't seem to appear that way when I cut and pasted in the message window. I have read your article repeatedly :-) I will have a look at the addin. Thanks for all of your help and patience when I sometimes ask the same question 2 or 3 times.
Greg Maxey - 04 Jan 2005 01:20 GMT Helmut,
As the two of us are just playing around, I thought I would try to expand your suggestion a bit. It is a fast and simple way to process the paragraph, but if the user then edits the paragraph (adds or removes counted words) then there is a mess. I cobbled together the following code which appears to do a decent job reproccessing the document if the macro is run a second time using the same search word. You are welcome to try to break it or offer suggestions for improvement. I don't really know what it is good for, but it was good mental exercise:
Sub FindAndNumberWords() 'Sequentially numbers each occurance of a specified word 'Resets numbering at the start of each paragraph
Dim oPara As Paragraph Dim oWord As Range Dim i As Integer Dim FindStr As String Dim RedoChk FindStr = InputBox("Type word to find") For Each oPara In ActiveDocument.Paragraphs i = 0 For Each oWord In oPara.Range.Words If Right(oWord, 1) = " " Then oWord.MoveEnd Unit:=wdCharacter, Count:=-1 If LCase(FindStr) = LCase(oWord) Then i = i + 1 oWord.Collapse Direction:=wdCollapseStart oWord.Text = CStr(i) oWord.Font.Superscript = True End If RedoChk = LCase(oWord) Like LCase("#*" & FindStr & "") If RedoChk Then i = i + 1 oWord.MoveEnd Unit:=wdCharacter, Count:=-Len(FindStr) oWord.Text = CStr(i) oWord.Font.Superscript = True End If Next Next End Sub
 Signature Greg Maxey/Word MVP A Peer in Peer to Peer Support
> Hi Greg, > [quoted text clipped - 27 lines] > "red.sys" & chr(64) & "t-online.de" > Word 2002, Windows 2000 Helmut Weber - 04 Jan 2005 09:56 GMT Hi Greg, not much to add, though I'd love to do so. The only marginal thing could be, to convert "findstr" to lowercase only once, at the very start of the sub.
Then If LCase(FindStr) = LCase(oWord) Then would become If FindStr = LCase(oWord) and RedoChk = LCase(oWord) Like LCase("#*" & FindStr & "") would become RedoChk = LCase(oWord) Like "#*" & FindStr
But I could not see any change in performance, about 20 seconds, with more then 12000 numbers to add in a 100 pages doc, containing just text only, and no tables! As to operate on ranges in tables is sometimes much slower (10 to 20 times) than using selection.
See the posting: Processing paragraphs with find by Conny Roloff.
Have a nice day.
Greetings from Bavaria, Germany Helmut Weber, MVP "red.sys" & chr(64) & "t-online.de" Word 2002, Windows 2000
Greg Maxey - 04 Jan 2005 11:01 GMT Helmut.
Thanks.
 Signature Greg Maxey/Word MVP A Peer in Peer to Peer Support
> Hi Greg, > not much to add, though I'd love to do so. [quoted text clipped - 28 lines] > "red.sys" & chr(64) & "t-online.de" > Word 2002, Windows 2000
|
|
|