Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
DiscussionsAccessExcelInfoPathOutlookPowerPointPublisherWord
DirectoryUser Groups
Related Topics
Outlook ExpressInternet ExplorerWindowsMS Server ProductsMore Topics ...

MS Office Forum / Word / Programming / December 2004

Tip: Looking for answers? Try searching our database.

Tech Eval

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Greg Maxey - 30 Dec 2004 04:20 GMT
Masters,

Earlier today I helped and OP looking for a way to look at each line in the
document and "If" the first character was not a space to assign a different
style.  This is what I proposed:

Sub ScratchMacro()
Dim oPar As Paragraph
Dim myRange As Range
For Each oPar In ActiveDocument.Paragraphs
 Set myRange = oPar.Range
   If Not myRange.Characters.First = " " Then
     oPar.Style = "Body Text"
   End If
Next
End Sub

I continued playing with this question and came up with this:

Sub Test()
Dim oPar As Paragraph
Dim myString As String
For Each oPar In ActiveDocument.Paragraphs
 myString = oPar.Range.Text
 If Not Left(myString, 1) = " " Then
   oPar.Style = "Body Text"
 End If
Next
End Sub

Both seem to work equally well on the limited sample text that I tested
with.  My question is which, if either, is the more appropriate and why?
Thanks.

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

Jay Freedman - 30 Dec 2004 17:37 GMT
Hi Greg,

I don't think there's any practical difference between the two approaches.
If you're processing a document with thousands of paragraphs, though, this
might be quicker:

Sub Test()
Dim oPar As Paragraph
For Each oPar In ActiveDocument.Paragraphs
 If Left(oPar.Range.Text, 1) <> " " Then
   oPar.Style = "Body Text"
 End If
Next oPar
End Sub

That is, you don't have to assign the .Text to a string before you feed it
into the Left function, as VBA will create an unnamed temporary variable for
the parameter. I've found that accessing the Characters collection of a range
is far slower than anything else.

--
Regards,
Jay Freedman
Microsoft Word MVP       FAQ: http://word.mvps.org

> Masters,
>
[quoted text clipped - 29 lines]
> with.  My question is which, if either, is the more appropriate and why?
> Thanks.
Word Heretic - 31 Dec 2004 02:20 GMT
G'day Jay Freedman <JayFreedman@discussions.microsoft.com>,

What is even faster is to use something like this

Collapse mypara to end
Extend to next para end

if one char then end of doc

it maintains a LINEAR access speed, unlike the for each which has to
dynamically calculate the next para FROM THE START.

On documents <1200 paras this makes a little difference, on large
documents it makes a HUGE difference - like HOURS quicker. 1200 real
world paras seems to be the rough point at which you can definitively
see a major slowdown in code execution iterating collections.

My reverse engineering of this thus says Word has some sort of buffer
for content, it is very large, but finite. So for 1200 paras we have
to also keep reloading the correct buffer after say 1024 paragraphs,
thus it only takes a few hundred iterations of this (1025-1200) to
show up on your performance graphs as a steeper gradient at this
point.

This makes business sense as it enables faster document processing for
the much more frequently occuring smaller documents, whilst still
allowing for the rarer large documents to exist. 80/20 right?

This has also been platform independant - in so far as different CPUs
and memory sizes on the host system made no difference to the
findings.

So, by doing it the heretical way, the number of paragraphs scanned
for their content to 'serialise' them is equivalent to the paragraphs
count, instead of the factorial of the count as is the case with any
dynamic collection based method (chars / paras / whatever).

Dynamic method:

This is my #1 trade secret for writing ultra fast macros. Don't forget
it! :-) It only takes about 30 mins for a reasonably competent user to
do a basic check of these assertions if they are so inclined.

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Jay Freedman reckoned:

>Hi Greg,
>
[quoted text clipped - 15 lines]
>the parameter. I've found that accessing the Characters collection of a range
>is far slower than anything else.
Greg Maxey - 31 Dec 2004 02:50 GMT
Steve

Do you mean something like this:
Sub Test1()
Dim myPara As Range
Set myPara = ActiveDocument.Paragraphs(1).Range
Do Until Len(myPara) = 1
 If Left(myPara.Text, 1) <> " " Then
   myPara.Style = "Body Text"
 End If
myPara.Collapse Direction:=wdCollapseEnd
myPara.Expand Unit:=wdParagraph
myPara.Select
Loop
End Sub

The only way I could figure out how to break out of the loop was an empty
paragraph at the end of the document and then the Len(myPara) condition.  I
know that there has to be a better way, but I am stumped.

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

> G'day Jay Freedman <JayFreedman@discussions.microsoft.com>,
>
[quoted text clipped - 65 lines]
>> temporary variable for the parameter. I've found that accessing the
>> Characters collection of a range is far slower than anything else.
Greg Maxey - 31 Dec 2004 03:01 GMT
Steve,

I cobbled this together.  Does it defeat the speed advantage you proposed?

Sub Test1()
Dim myPara As Range
Dim i As Long
Set myPara = ActiveDocument.Paragraphs(1).Range
i = 0
Do
 i = i + 1
 If Left(myPara.Text, 1) <> " " Then
   myPara.Style = "Body Text"
 End If
myPara.Collapse Direction:=wdCollapseEnd
myPara.Expand Unit:=wdParagraph
Loop Until i = ActiveDocument.Paragraphs.Count
End Sub

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

> Steve
>
[quoted text clipped - 87 lines]
>>> temporary variable for the parameter. I've found that accessing the
>>> Characters collection of a range is far slower than anything else.
Word Heretic - 31 Dec 2004 06:22 GMT
G'day "Greg Maxey" <gmaxey@mvps.OscarRomeoGolf>,

Yes - it does. However, it is no good for when you are EDITING content
and the length or number of paragraphs may change. Which is why your
base 'marker' has to be a range. I have sent an article submission
directly to you in explanation.

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Greg Maxey reckoned:

>Steve,
>
[quoted text clipped - 14 lines]
>Loop Until i = ActiveDocument.Paragraphs.Count
>End Sub
Greg Maxey - 31 Dec 2004 03:04 GMT
P.S.

I am not yet a reasonably competent user.

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

> Steve
>
[quoted text clipped - 87 lines]
>>> temporary variable for the parameter. I've found that accessing the
>>> Characters collection of a range is far slower than anything else.
Word Heretic - 31 Dec 2004 06:22 GMT
G'day "Greg Maxey" <gmaxey@mvps.OscarRomeoGolf>,

At least you are making considerable progress and efforts :-) It is
the next best thing.

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Greg Maxey reckoned:

>P.S.
>
>I am not yet a reasonably competent user.
Word Heretic - 31 Dec 2004 06:25 GMT
G'day "Greg Maxey" <gmaxey@mvps.OscarRomeoGolf>,

I was misleading in my len=1, any blank para will stop that loop. I
test the range end against the current storyrange end.

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Greg Maxey reckoned:

>Steve
>
[quoted text clipped - 15 lines]
>paragraph at the end of the document and then the Len(myPara) condition.  I
>know that there has to be a better way, but I am stumped.
Greg Maxey - 31 Dec 2004 04:59 GMT
Well I must be missing something Steve.  I tried both of my attempts to use
your suggestions on a several thousand paragraph document and the result was
an order of magnitude slower.  I suppose it has something to do with my exit
strategy.

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

> G'day Jay Freedman <JayFreedman@discussions.microsoft.com>,
>
[quoted text clipped - 65 lines]
>> temporary variable for the parameter. I've found that accessing the
>> Characters collection of a range is far slower than anything else.
Word Heretic - 31 Dec 2004 06:25 GMT
G'day "Greg Maxey" <gmaxey@mvps.OscarRomeoGolf>,

See previous reply.

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Greg Maxey reckoned:

>Well I must be missing something Steve.  I tried both of my attempts to use
>your suggestions on a several thousand paragraph document and the result was
>an order of magnitude slower.  I suppose it has something to do with my exit
>strategy.
Greg Maxey - 31 Dec 2004 12:17 GMT
Steve,

I see your point.  I ran the following two macros on a document containing
100,000 single line paragraphs.  Your method was over 20% faster:

Sub UsualWay()
'Time to process 100,000 single line paragraphs 85.79 seconds
Dim StartTime As Single
Dim aPara As Paragraph
StartTime = Timer
With ActiveDocument.StoryRanges(wdMainTextStory)
 For Each aPara In .Paragraphs
   aPara.Range.HighlightColorIndex = HColor
   Select Case HColor
     Case wdRed
       HColor = wdNoHighlight '0
     Case wdNoHighlight
       HColor = wdBlue '2
     Case wdBlue
       HColor = wdRed '6
   End Select
 Next aPara
End With
Set aPara = Nothing
MsgBox "Time taken was: " & (Timer - StartTime) & " seconds"
End Sub

Public Sub FasterWay()
'Time to process 100,0000 single line paragraphs 69.45 seconds
Dim StartTime As Single
Dim aPara As Range
StartTime = Timer
With ActiveDocument.StoryRanges(wdMainTextStory)
 Set aPara = .Paragraphs(1).Range
 Do
   aPara.HighlightColorIndex = HColor
   Select Case HColor
     Case wdRed
       HColor = wdNoHighlight '0
     Case wdNoHighlight
       HColor = wdBlue '2
     Case wdBlue
       HColor = wdRed '6
   End Select
   aPara.Collapse wdCollapseEnd
   aPara.MoveEnd wdParagraph, 1
 Loop Until aPara.End = .End
End With
Set aPara = Nothing
MsgBox "Time taken was: " & (Timer - StartTime) & " seconds"

End Sub

Signature

Greg Maxey/Word MVP
A Peer in Peer to Peer Support

> G'day Jay Freedman <JayFreedman@discussions.microsoft.com>,
>
[quoted text clipped - 65 lines]
>> temporary variable for the parameter. I've found that accessing the
>> Characters collection of a range is far slower than anything else.
Word Heretic - 31 Dec 2004 15:03 GMT
G'day "Greg Maxey" <gmaxey@mvps.OscarRomeoGolf>,

I can assure Real Life documents are even more dramatic for the
reasons explained in the article :-)

By the way Greg - you have just demonstrated your competency as the
article claims a reasonably competent user can easily prove the
principles inside half an hour...

<evil grins>

We will learns ya!

Steve Hudson - Word Heretic

steve from wordheretic.com (Email replies require payment)
Without prejudice

Greg Maxey reckoned:

>Steve,
>
[quoted text clipped - 48 lines]
>
>End Sub

Rate this thread:






 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.