[Bounty Won] Text Blob Line Counter Speed Challenge

Technical support and scripting issues

Moderators: Dorian (MJT support), JRL

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Apr 01, 2009 5:24 am

Hi Marcus,
jpuziano wrote:And a question for Marcus... perhaps a silly question but I'll ask anyway:

The line below from Gail did not work for me, I had to replace it with the following 2 lines instead:

//Let>nLeftOver=num_blob_chars-(10*nLength)
Let>new=10*nLength
Let>nLeftOver=num_blob_chars-new

Is something wrong with the syntax? When I added the following line after the problem line above:

MDL>nLeftOver

The MessageModal> box displayed the following:

num_blob_chars-(10*nLength)

Why wasn't the number displayed?
No need to answer the above question. :oops: In the Help File topic for the Let> command, there was this example:
  • Let>MyVal={5 * 10 + 25}
The above will set MyVal to 75. However, without the curly brackets... I see MyVal gets set to the string 5 * 10 + 25

After some testing and searching for other forum posts here about complex expressions... it seems there is a simple rule that did not sink in for me and perhaps for quite a few others as well. I can't find this rule stated in the Help File... so if its not in there... maybe you would consider adding it in to make it absolutely obvious?

Rule: When assigning a value to a variable using the Let> command, if you have more than two operands to the right of the equals sign = then you must use a complex expression by enclosing everything to the right of the equals sign = with curly brackets.
operand definition from http://www.webopedia.com/TERM/O/operand.html wrote:In all computer languages, expressions consist of two types of components: operands and operators. Operands are the objects that are manipulated and operators are the symbols that represent specific actions. For example, in the expression

5 + x

x and 5 are operands and + is an operator. All expressions have at least one operand.
So the first two lines below are OK because they have two or less operands:
  • Let>var2=2

    Let>MyVal=5*var2

    Let>MyVal=5*var2+1
The third line above has three operands so instead of setting MyVal to 11, it will set MyVal to the string 5*var2+1

We need this instead:
  • Let>MyVal={5*%var2%+1}
With the curly braces... assuming var2=2 then MyVal will be set to 11.

We need % symbols around the variables inside a complex expression too... as stated in Help:
As stated in the Help File for the Let> command wrote:The expression must be contained within curly braces "{" and "}". String literals must be delimited with double quotes ("), e.g.: "string". Variables must be delimited with % symbols, e.g.: %VarA%.
So now I see that Gail's original line:
  • Let>nLeftOver=num_blob_chars-(10*nLength)
Should have been this instead:
  • Let>nLeftOver={%num_blob_chars%-(10*%nLength%)}
I tried that and it works fine.

Sorry for belaboring the point Marcus... its clear for me now... but adding the rule "3 operands or more requires a complex expression" to the Help File might help a lot of others IMO.

Thanks and take care
Last edited by jpuziano on Wed Apr 01, 2009 6:11 am, edited 1 time in total.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Apr 01, 2009 6:01 am

Hi everyone,
JRL wrote:me_again's VBScript from the post I mentioned earlier does this in half the time of regex. I get about .53 for regex and about .28 for VBScript.

Should you decide this is the solution worthy of points, they should go to me_again. :)
Sure its worthy, it went faster... 10 points goes to Me_again.
gdyvig wrote:I updated my results in the previous post so you can compare it with the other methods.

wc.exe method:
100,000 lines: 0.3 sec (same as slice and dice)
1,000,000 lines: 1.65 sec.(twice as fast as slice and dice)

This includes the time required to write the file and read it.

This method is very scalable for large blobs.
RegEx is not scalable.

Gale
Thanks for testing that Gale. Now that we know the RegEx method is not scaleable, wc.exe is my choice where large text blobs are involved.

And thanks to the ability of Macro Scheduler to embed any kind of file, I can carry wc.exe inside a compiled maco if I want. In that case, finding the smallest free wc.exe out there would be good... as well as the fastest. Sizes were:

45KB wc.exe from http://www.softwareonline.org/winxs42.html

28KB wc.exe from http://www.highend3d.com/downloads/tool ... -v1.0-.zip

They seem very similar in speed so the smaller one is a clear winner so far.

If anyone finds any other wc.exe candidates that are particularly small or fast (or hopefully both) then please post and share.

Gale, since your slice and dice method went faster than my plain regex example... 10 points goes to you as well.

Thanks for all the input and ideas... this has been fun. The only thing that could top it would be Marcus coming up with something that could beat wc.exe by a wide factor... you just never know... :D
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Apr 02, 2009 12:05 am

Hi All,

And the speed record falls again... try the following... but be sure to point filetest at an existing text file on your machine before running:

Code: Select all

VBSTART
Function LineCount(sFilespec)
 Const ForAppending = 8
 with CreateObject("Scripting.FileSystemObject")
   LineCount = .OpenTextFile(sFilespec, ForAppending).Line
 end with
end Function
VBEND

Let>filetest=%temp_dir%textblob.txt

//Method: VBScript4 ForAppending
VBEval>Timer,startSeconds
VBEval>LineCount("%filetest%"),vb4_lines_counted
VBEval>Timer-%startSeconds%,VBScript4_elapsedSeconds

//Show results
MDL>Method: VBScript4%CRLF%Lines Counted: %vb4_lines_counted%%CRLF%Elapsed time in seconds: %VBScript4_elapsedSeconds%
Here are the results of all the methods tested so far and finally this latest method:
test results on my old PC wrote:Method: plain RegEx>
Lines Counted: 100000
Elapsed time in seconds: 13.51171875

Method: Me_again's VBScript
Lines Counted: 100000
Elapsed time in seconds: 6.70703125

Method: Gail - Slice and Dice plain RegEx>
Lines Counted: 100000
Elapsed time in seconds: 2.2734375
nLeftOver = 0

Method: wc.exe from http://www.highend3d.com
Lines Counted: 100000
Elapsed time in seconds: 0.421875

Method: VBScript4 ForAppending
Lines Counted: 100001
Elapsed time in seconds: 0.2265625

I can take no credit for the above... I was lucky enough to stumble upon it here:

http://groups.google.com/group/microsof ... 572b97721f

It looks like the number it reports is +1 over... but that's easy to fix.

At .22 of a second for 100000 lines on my old machine, this method is the new speed king.. but if anyone manages to improve on it... please let us know.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

Me_again
Automation Wizard
Posts: 1101
Joined: Fri Jan 07, 2005 5:55 pm
Location: Somewhere else on the planet

Post by Me_again » Thu Apr 02, 2009 3:25 am

That is surprisingly fast, but wc.exe still beats it counting a 1.5 million line, 282 meg file on my laptop in about 5 seconds vs. 7 seconds.

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Apr 02, 2009 6:17 am

Me_again wrote:That is surprisingly fast, but wc.exe still beats it counting a 1.5 million line, 282 meg file on my laptop in about 5 seconds vs. 7 seconds.
Hi Me_again,

Thanks for posting that result.... wc.exe seems to gain a speed advantage as the file size grows. I wonder how they would compare at 1 GB and 10 GB.

Also, simply counting lines in a text file is one thing... but I am getting my input from the contents of a memo field in a dialog. The user pastes the huge text blob in there manually... but there is quite the delay before the pasted text shows up (is visible) in the memo field.

A 100000 line text blob... like the one generated by the script I've been posting here... takes about an additional 16 seconds to become visible in the memo field on my old home PC.

This should drop to about 4 or 3 seconds on the faster work PCs but I do wonder if the memo field could be made to show values pasted into it a little quicker...

...any chance for a speedup there Marcus?
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7380
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Thu Apr 02, 2009 8:34 am

This may or may not help. There's a windows message EM_GETLINECOUNT which will return the number of lines in a multi-line edit control. So if you are wanting to know how many lines are in a Memo field you can just send the EM_GETLINECOUNT message to it and you'll get it back immediately. Here's an example:

Code: Select all

VBSTART
VBEND

Dialog>Dialog1
   Caption=Dialog1
   Width=427
   Height=274
   Top=433
   Left=501
   Memo=msMemo1,13,15,388,178,line one%CRLF%line two
   Button=Get Line Count,12,204,389,25,10
EndDialog>Dialog1

Show>Dialog1

Let>EM_GETLINECOUNT=186

Label>actionloop

  GetDialogAction>Dialog1,r
  If>r=10
    VBEval>Timer,startTime
    LibFunc>user32,SendMessageA,count,Dialog1.msMemo1.handle,EM_GETLINECOUNT,0,0
    VBEval>Timer-%startTime%,elapsedSeconds
    MessageModal>Lines: %count% (%elapsedSeconds% seconds)
    ResetDialogAction>Dialog1
  Endif
  If>r<>2
    Goto>actionloop
  Endif
Paste a large blob of text into the memo field and click the button.

I'm afraid we can't make the memo field faster. It isn't designed for editing 100s of 1000s of lines and in any case the delay is probably more down to your PC spec. If it were as simple as switching a "Go Faster" button then those clever people who spend all their time developing developer's editors like Jan at JG Software and the boys who make TextPad and Ultraedit would be out of a job.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
Marcus Tettmar
Site Admin
Posts: 7380
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Thu Apr 02, 2009 8:40 am

jpuziano wrote:Marcus, the wc.exe I used was not a free solution... but I did find a DLL called grc32v4.dll here: http://basic.wikispaces.com/DLLs
they wrote:Simple Line/Record Counting DLL by Cassio Ferreira. 7KB DLL designed to count lines/records within text files more quickly than in native Liberty BASIC (as of v4.03). The speed improvement becomes significant when the count is in the thousands.
I downloaded it and took a look but can't quite figure out how to call this DLL. Do I have to use LibLoad> first?

Can you please take a peek and let me know how I would call it from a Macro Scheduler script... if its possible?

Thanks Marcus and take care...
Like this:

Code: Select all

Let>filename=C:\Users\User\Documents\log.txt
LibFunc>%SCRIPT_DIR%\grc32v4.dll,GetRecordCount,NumLines,filename
MessageModal>NumLines
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Apr 02, 2009 7:35 pm

Hi Marcus,
mtettmar wrote:This may or may not help. There's a windows message EM_GETLINECOUNT which will return the number of lines in a multi-line edit control. So if you are wanting to know how many lines are in a Memo field you can just send the EM_GETLINECOUNT message to it and you'll get it back immediately.

Paste a large blob of text into the memo field and click the button.
Thanks Marcus, that's what I was looking for in the first place... the elusive "libfunc> method that works in the blink of an eye" that JRL also was looking for in his original post back here: Acquire line count of text file

As I tried pasting larger and larger text blobs in a memo field, I found out there is a limit above which the memo field just would not allow you to paste. The text is in the Windows Clipboard... but the memo field must see that it is above its pre-set limit and does not offer paste... CTRL V is ignored... and if you right click in the memo field, the Paste option is greyed out... however you can go paste into other editors.

I found that a text blob of 475,519 lines and 32,378 KB can be pasted directly into a memo field... but a little above this limit and the memo field is not offering paste.

Marcus, just for the record, can you tell us what you have set the size limit to for pasting into a memo field?

So I ran your macro to test it with the worse case scenario... a 32,378 KB text blob... on our work machines which are Pentium 4 - 3GHz - 1 GB ram and timed a few things:
timing results wrote:time between typing CTRL V and when the text appears in the memo field
38 seconds

move mouse pointer over button in dialog, the time it takes for the button to sense that the pointer is over it and highlight itself with a yellow border
5 seconds

time between when you click the button and the MDL> dialog shows you the timing results
9.5 seconds

The MDL> timing results on this one for me said:
Lines: 475519 (0 seconds)
While it is great that this API call can return the number of lines in the memo field so amazingly fast (and I am using your method now so thanks again)... obviously other things slow down considerably when trying to handle such large text blobs inside a memo field.
mtettmar wrote:I'm afraid we can't make the memo field faster. It isn't designed for editing 100s of 1000s of lines and in any case the delay is probably more down to your PC spec. If it were as simple as switching a "Go Faster" button then those clever people who spend all their time developing developer's editors like Jan at JG Software and the boys who make TextPad and Ultraedit would be out of a job.
OK... It may sound like I'm complaining but I'm not... just testing the limits of the tools we have.

Thanks also for posting how to call the grc32v4.dll DLL... I'll have to give that a try.

Take care
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7380
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Thu Apr 02, 2009 8:14 pm

Marcus, just for the record, can you tell us what you have set the size limit to for pasting into a memo field?
I haven't. The memo field is just a wrapper for Windows' own multi-line edit control. It is therefore dependent on the operating system. We have not defined a limit.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Sat Apr 04, 2009 1:22 am

mtettmar wrote:This may or may not help. There's a windows message EM_GETLINECOUNT which will return the number of lines in a multi-line edit control. So if you are wanting to know how many lines are in a Memo field you can just send the EM_GETLINECOUNT message to it and you'll get it back immediately. Here's an example:

Code: Select all

VBSTART
VBEND

Dialog>Dialog1
   Caption=Dialog1
   Width=427
   Height=274
   Top=433
   Left=501
   Memo=msMemo1,13,15,388,178,line one%CRLF%line two
   Button=Get Line Count,12,204,389,25,10
EndDialog>Dialog1

Show>Dialog1

Let>EM_GETLINECOUNT=186

Label>actionloop

  GetDialogAction>Dialog1,r
  If>r=10
    VBEval>Timer,startTime
    LibFunc>user32,SendMessageA,count,Dialog1.msMemo1.handle,EM_GETLINECOUNT,0,0
    VBEval>Timer-%startTime%,elapsedSeconds
    MessageModal>Lines: %count% (%elapsedSeconds% seconds)
    ResetDialogAction>Dialog1
  Endif
  If>r<>2
    Goto>actionloop
  Endif
I just wanted to post a warning to anyone using the above method. If your data is already in a memo field, the above method is the fastest way to get the number of lines... but if your text blob is large enough, it gives incorrect results.

I wrote a macro to take a line count two ways, one being the above LibFunc method and the other, writing the contents of the memo field to a file and then using the fastest VBScript method to count the lines.

If my lines were:

line 1
line 2
line 2
...

I had both methods giving the same counts for over a million lines.

Then I tried another test using a large text file and doubling its size each time. It went OK for a while until finally, the following results:

LibFunc> Lines: 257971 (0 seconds)
VBScript Lines: 220987 (1.015625 seconds)

The VBScript method still had the correct count but LibFunc> was way over.

Looks like we're running into a limit of some kind with that LibFunc> call. Does anyone know what that limit is?

Marcus, any idea?
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7380
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Sat Apr 04, 2009 6:07 am

Don't blame LibFunc - it is just the messenger.

LibFunc - LibFunc just calls a DLL function. In this case the Windows SendMessage function. And in this case SendMessage is sending the EM_GETLINES message. So your first port of call is the Windows SDK documentation. And we've already discussed the fact that a memo is a wrapper for a standard windows multi-line edit control. And, as far as I could determine from the docs, any "limit" is going to depend on your system and its capabilities. Again the Windows docs are the best place for info. But it is not designed for editing enormous files.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Tue Apr 14, 2009 11:03 pm

Hi Marcus.

The incorrect linecount values I've been seeing from the following call...

Code: Select all

Let>EM_GETLINECOUNT=186
LibFunc>user32,SendMessageA,count,Dialog1.msMemo1.handle,EM_GETLINECOUNT,0,0
MessageModal>Lines: %count%
...were the result of some lines of text being too long for the size of the memo field... so they would wrap and be counted as two lines not one.

One solution would be to re-size my memo field very large such that any lines pasted in would probably not be too long and wrap... but I'd like to try another way.

I want to use an API call to tell the memo field that it should have a horizontal scrollbar. Here's a web page that describes the message I want to send... the ES_AUTOSCROLL message...
http://msdn.microsoft.com/en-us/library/ms997530.aspx wrote:ES_AUTOHSCROLL

ES_AUTOHSCROLL tells the edit control to scroll the text horizontally, when necessary, as the user enters text. However, if ES_AUTOHSCROLL is not specified, the edit control cannot scroll horizontally. For single-line edit controls without ES_AUTOHSCROLL, only the characters that fill the visible area of the control are accepted. For multiple-line edit controls without ES_AUTOHSCROLL, the text wraps to the next line when the user enters more text than can be displayed on a single line. If ES_AUTOHSCROLL is specified for a multiple-line edit control, the control scrolls horizontally when the user enters more text than can be displayed on a single line; the text will not wrap.

ES_AUTOHSCROLL is automatically applied to an edit control that has a WS_HSCROLL style. In other words, any edit control that has a horizontal scroll bar automatically scrolls horizontally.

ES_AUTOHSCROLL is ignored when an edit control is not left-aligned. Centered and right-aligned multiple-line edit controls cannot be horizontally scrolled.
I tried this... but it doesn't work:
Let>ES_AUTOHSCROLL=128
LibFunc>user32,SendMessageA,unknown_var,Dialog1.msMemo1.handle,ES_AUTOHSCROLL,0,0
Marcus... is this possible and if so... what should the LibFunc> line look like?

Thanks for your help
Last edited by jpuziano on Wed Apr 15, 2009 3:53 pm, edited 1 time in total.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Apr 15, 2009 3:51 pm

For those who may be following this post... here is the macro I used to compare two of the fastest methods I could find to get a linecount on the text in a memo field on a dialog. It compares the following two methods:

- fastest VBScript method (text must be in a file)
- LibFunc> API call (file not needed)

Code: Select all

VBSTART
Function LineCount_vb4(sFilespec)
 Const ForAppending = 8
 with CreateObject("Scripting.FileSystemObject")
   LineCount_vb4 = .OpenTextFile(sFilespec, ForAppending).Line
 end with
end Function
VBEND

Let>WLN_NOCRLF=1
Let>EM_GETLINECOUNT=186

Dialog>Dialog1
   Caption=Dialog1
   Width=829
   Height=279
   Top=104
   Left=16
   Max=1
   Min=1
   Close=1
   Resize=1
   Memo=msMemo1,13,15,796,178,line one%CRLF%line two%CRLF%
   Button=Get Line Count via LibFunc> API call and via fast VBScript method and compare,12,204,413,25,10
   Button=Add a Line that is wider than the Memo field,518,204,227,25,5
   Button=Double it,438,204,67,25,7
   Button=Exit,758,204,51,25,2
EndDialog>Dialog1

Show>Dialog1

Label>actionloop

GetDialogAction>Dialog1,r

//Count the lines via two methods and compare results
If>r=10
  Let>filetest=%TEMP_DIR%test_blob.txt
  //delete old blob file if it exists
  DeleteFile>%filetest%
  //save the input text blob to a file
  WriteLn>%filetest%,result,%Dialog1.msMemo1%

  //Get linecount via fastest VBScript file method
  //http://groups.google.com/group/microsoft.public.scripting.vbscript/msg/599821572b97721f
  VBEval>Timer,startSeconds
  VBEval>LineCount_vb4("%filetest%"),vb4_lines_counted
  VBEval>Timer-%startSeconds%,vb4_elapsedSeconds

  //Get linecount via API call (no file necessary)
  VBEval>Timer,startTime
  LibFunc>user32,SendMessageA,count,Dialog1.msMemo1.handle,EM_GETLINECOUNT,0,0
  VBEval>Timer-%startTime%,elapsedSeconds

  If>vb4_lines_counted=count
    Let>Flag=THEY ARE EQUAL - WE ARE OK
  Else
    Let>Flag=****UNEQUAL ERROR ERROR****
  EndIf

  MessageModal>LibFunc Lines: %count% (%elapsedSeconds% seconds)%CRLF%VBScript Lines: %vb4_lines_counted% (%vb4_elapsedSeconds% seconds)%CRLF%%CRLF%%Flag%

  ResetDialogAction>Dialog1
Endif

//add a line that is wider than the memo field
If>r=5
  Let>lc=0
    Repeat>lc
      Let>lc=lc+1
      ConCat>Dialog1.msMemo1,a long line with no CRLF at the end%SPACE%
    Until>lc=5
  ResetDialogAction>Dialog1
Endif

//double it button - doubles the entered text
If>r=7
  ConCat>Dialog1.msMemo1,Dialog1.msMemo1
  ResetDialogAction>Dialog1
Endif

If>r=2,Exit

Goto>actionloop

Label>Exit
The LibFunc> API call was the undisputed fastest way (here's a recent result)...
timing run wrote:LibFunc Lines: 542688 (0.03125 seconds)
VB Lines: 542688 (54.40625 seconds)

THEY ARE EQUAL - WE ARE OK
...however I had been seeing inconsistent results from the LibFunc> API call... sometimes the linecount was off.

If you try the above macro... you will see that as long as you use short lines.. shorter than the width of the memo field... the two methods give the same linecount.

However as soon as you have a line that wraps... the LibFunc> API call will be counting that as two lines (because visually in the dialog, it is two lines) however the VBScript method counts it as one line because lines to it are text terminated with CRLF.

What I need is a memo field with a horizontal scroll bar... however Marcus has informed me that there's no way for us to add a memo field to a dialog and specify that it should have the ES_AUTOHSCROLL style attribute... as those properties are not exposed (at present).

There still may be hope... I've asked Marcus about a possible workaround method of creating a memo field with a horizontal scrollbar on a dialog using more API calls... stay tuned.

Or, if there are any other API call wizards out there that might know how to do this, please jump in.

Thanks and take care
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Apr 15, 2009 5:45 pm

jpuziano wrote:Marcus, could you (or any other person skilled in converting dialogs to v12) assist with the changes required to make this work with a v12 dialog?
I just stumbled across this open question I had left to the forums... and since I now know how to do this... I thought I'd post the converted script, see below.

This shows the raw speed of a single LibFunc> call to count lines in a Memo field in a Dialog compared to using VBScript to count those sames lines in a file.

It also shows how to use the VBScript Timer function to time a section of your code... useful for comparing different sections for speed as this example does. Here's the bit that does that:

Code: Select all

VBSTART
VBEND

VBEval>Timer,startTime
...these are the lines of code you are timing
VBEval>Timer-%startTime%,elapsedSeconds
MDL>elapsedSeconds=%elapsedSeconds%
Note that if you don't already have a VBSTART / VBEND section in your macro, you'll need to add it to use VBScript... as shown above.

Anyway, the converted script is below, I hope some of you will find this helpful... take care.

Code: Select all

VBSTART
Function LineCount_vb4(sFilespec)
 Const ForAppending = 8
 with CreateObject("Scripting.FileSystemObject")
   LineCount_vb4 = .OpenTextFile(sFilespec, ForAppending).Line
 end with
end Function
VBEND

Let>WLN_NOCRLF=1
Let>EM_GETLINECOUNT=186

Dialog>Dialog1
object Dialog1: TForm
  Left = 251
  Top = 97
  HelpContext = 5000
  BorderIcons = [biSystemMenu]
  Caption = 'Dialog1'
  ClientHeight = 252
  ClientWidth = 821
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  ShowHint = True
  OnTaskBar = False
  PixelsPerInch = 96
  TextHeight = 13
  object msMemo1: tMSMemo
    Left = 13
    Top = 15
    Width = 796
    Height = 178
    Lines.Strings = (
      'line one'
      'line two')
    ScrollBars = ssBoth
    TabOrder = 0
    Text = 'line one'#13#10'line two'#13#10
  end
  object msButton1: tMSButton
    Left = 12
    Top = 204
    Width = 413
    Height = 25
    Caption =
      'Get Line Count via LibFunc> API call and via fast VBScript metho' +
      'd and compare'
    DoubleBuffered = True
    ParentDoubleBuffered = False
    ParentShowHint = False
    ShowHint = False
    TabOrder = 1
    DoBrowse = False
    BrowseStyle = fbOpen
  end
  object msButton2: tMSButton
    Left = 518
    Top = 204
    Width = 227
    Height = 25
    Caption = 'Add a Line that is wider than the Memo field'
    DoubleBuffered = True
    ParentDoubleBuffered = False
    ParentShowHint = False
    ShowHint = False
    TabOrder = 2
    DoBrowse = False
    BrowseStyle = fbOpen
  end
  object msButton3: tMSButton
    Left = 438
    Top = 204
    Width = 67
    Height = 25
    Caption = 'Double it'
    DoubleBuffered = True
    ParentDoubleBuffered = False
    ParentShowHint = False
    ShowHint = False
    TabOrder = 3
    DoBrowse = False
    BrowseStyle = fbOpen
  end
  object msButton4: tMSButton
    Left = 758
    Top = 204
    Width = 51
    Height = 25
    Caption = 'Exit'
    DoubleBuffered = True
    ModalResult = 2
    ParentDoubleBuffered = False
    ParentShowHint = False
    ShowHint = False
    TabOrder = 4
    DoBrowse = False
    BrowseStyle = fbOpen
  end
end
EndDialog>Dialog1

AddDialogHandler>Dialog1,msButton1,OnClick,Do_Count_the_lines_via_two_methods_and_compare_results

SRT>Do_Count_the_lines_via_two_methods_and_compare_results

Let>filetest=%TEMP_DIR%test_blob.txt
//delete old blob file if it exists
DeleteFile>%filetest%
//save the input text blob to a file
GetDialogProperty>Dialog1,msMemo1,Text,strTheText
WriteLn>%filetest%,result,strTheText

//Get linecount via fastest VBScript file method
//http://groups.google.com/group/microsoft.public.scripting.vbscript/msg/599821572b97721f
VBEval>Timer,startSeconds
VBEval>LineCount_vb4("%filetest%"),vb4_lines_counted
VBEval>Timer-%startSeconds%,vb4_elapsedSeconds

//Get linecount via API call (no file necessary)
VBEval>Timer,startTime
LibFunc>user32,SendMessageA,count,Dialog1.msMemo1.handle,EM_GETLINECOUNT,0,0
VBEval>Timer-%startTime%,elapsedSeconds

If>vb4_lines_counted=count
  Let>Flag=THEY ARE EQUAL - WE ARE OK
Else
  Let>Flag=****UNEQUAL ERROR ERROR****
EndIf

MessageModal>LibFunc Lines: %count% (%elapsedSeconds% seconds)%CRLF%VBScript Lines: %vb4_lines_counted% (%vb4_elapsedSeconds% seconds)%CRLF%%CRLF%%Flag%

END>Do_Count_the_lines_via_two_methods_and_compare_results



AddDialogHandler>Dialog1,msButton2,OnClick,Do_add_a_line_that_is_wider_than_the_memo_field

SRT>Do_add_a_line_that_is_wider_than_the_memo_field

GetDialogProperty>Dialog1,msMemo1,Text,strTheText

Let>lc=0
Repeat>lc
  Let>lc=lc+1
  ConCat>strTheText,a long line with no CRLF at the end%SPACE%
Until>lc=5

SetDialogProperty>Dialog1,msMemo1,Text,strTheText

END>Do_add_a_line_that_is_wider_than_the_memo_field



AddDialogHandler>Dialog1,msButton3,OnClick,Do_double_it_button_doubles_the_entered_text

SRT>Do_double_it_button_doubles_the_entered_text

GetDialogProperty>Dialog1,msMemo1,Text,strTheText
ConCat>strTheText,strTheText
SetDialogProperty>Dialog1,msMemo1,Text,strTheText

END>Do_double_it_button_doubles_the_entered_text



Show>Dialog1,r

Label>actionloop
If>r=2,Exit
Goto>actionloop

Label>Exit
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

davedavydave
Newbie
Posts: 16
Joined: Mon Dec 01, 2008 3:56 pm

Re: [Bounty Won] Text Blob Line Counter Speed Challenge

Post by davedavydave » Mon Mar 14, 2016 7:00 am

For anyone still looking for the free wc.exe utility mentioned earlier in previous posts (the links are no longer working) you can find it here:

http://www.tawbaware.com/wc.htm
Cheers,
Dave

Hill Running...... Beats work!

Post Reply
Sign up to our newsletter for free automation tips, tricks & discounts