Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Nifty line counter needed

77 views
Skip to first unread message

prebble

unread,
Aug 5, 2008, 9:58:22 AM8/5/08
to
Hi,
I hope someone can help as I need a vbscript in a hurry.


I have a number of text files in a specific folder.
I need to count the number of lines
in each text file in that folder and
create an output file with the name of the text file
and the number of lines.

Then sort the output file in alphabetical order of the text file names.

I know how to count lines in any specific file but
I'm not so good with the "for each file in this folder" business.


Here's what I did with for counting lines.
Most of it is probably copied from somewhere.
--------
'Create a File System Object
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFileContents = Nothing

Dim InputFile
InputFile = InputBox("Nom du fichier")

'Get the file contents
Dim MyFileContents
Set MyFileContents = fso.OpenTextFile(InputFile)

'Loop through counting the lines
'
Do While Not MyFileContents.AtEndOfStream
s= MyFileContents.ReadLIne

linelength = len(S)

if linelength < 10 then
msgbox ctr
end if
'msgbox "x" & x & vbcrlf &_
' "linelength " & linelength & vbcrlf
if x <= linelength then
x = linelength
end if
ctr = ctr + 1
Loop

'Return the file's line count


msgbox "File name " & InputFile & vbcrlf &_
"FileLineCount " & Ctr & vbcrlf &_
"Maximum Line length " & x

'Cleanup
MyFileContents.Close
Set MyFileContents = Nothing
Set fso = Nothing
--------
TIA
prebble


mayayana

unread,
Aug 5, 2008, 10:23:13 AM8/5/08
to
There's nothing wrong with the ReadLine method.
(It's not clear what all that "x" code is about.)
Personally it seems easier to me (and maybe
a bit quicker) to just do:

Set FileContents = fso.OpenTextFile(InputFile, 1)
s = FileContents.ReadAll
FileContents.close
Set FileContents = Nothing

A = Split(s, vbCrLf)
LineCount = UBound(A) + 1

'-- You'll need error trapping for blank files and may
want to make other minor adjustments for things like
multiple vbCrLf that may appear at end of files.

For multiple files you'll probably want to put
your counter code into a function. Then do something
like:

-----------------------------------------

Set oFol = FSO.GetFolder("folderpath")
Set oFils = oFol.Files
For Each oFil in oFils
LineCount = GetLineCount(oFil.Path)
'-- maintain a list of files and lengths:
sList = sList & oFil.Path & "Linecount: " & LineCount & vbCrLf
Next
Set oFils = Nothing
Set oFol = Nothing

Function GetLineCount(FilePath)
Dim TS, s, A
On Error Resume Next
Set TS = fso.OpenTextFile(FilePath, 1)
s = TS.ReadAll
TS.close
Set TS = Nothing

A = Split(s, vbCrLf)
GetLineCount = UBound(A) + 1
End Function

'-- At this point you have a string/list of file paths
and their line counts that you can just write to disk.

Tom Lavedas

unread,
Aug 5, 2008, 1:15:00 PM8/5/08
to

Here is my contestant for the quickest/simplest file line counter ...

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

I posted an example based on this technique a few days ago. And as I
recall, someone else showed it to me a few years back. I am told that
it is off by one count for empty files and files full of blank lines
(new line characters only - no other text).

Tom Lavedas
===========
http://members.cox.net/tglbatch/wsh/

soler

unread,
Aug 5, 2008, 3:31:01 PM8/5/08
to
try
find /c /v "" filenamehere.txt

ouput will be:
---------- filenamehere.txt: 138
--
soler


"Paul Randall" wrote:

>
> "Tom Lavedas" <tglb...@cox.net> wrote in message
> news:360fd3ac-76f8-45cc...@p10g2000prf.googlegroups.com...

> As with most things in life, perhaps we need to define what a line is (for
> counting purposes) before we can count them. If a file can contain more
> than one empty line, then an empty file must contain one empty line. And
> perhaps the definition of a line separator is necessary, such as vbLf. With
> these definitions, the following script shows that your function produces
> correct results; the script is attached also to avoid line wrap problems:
>
> Option Explicit
> MsgBox "started in " & vbCrLf & _
> WScript.CreateObject("WScript.Shell").CurrentDirectory
>
> fOverWrite "dummy.txt", ""
> MsgBox "Line count for empty file -- should be one (for one empty line): " &
> LineCount("dummy.txt")
> fOverWrite "dummy.txt", vbCrLf
> MsgBox "Line count for CrLf file -- should be two (for two empty lines): " &
> LineCount("dummy.txt")
> fOverWrite "dummy.txt", "Now is the time for all ..."
> MsgBox "Line count for one-line file -- should be one: " &
> LineCount("dummy.txt")
> fOverWrite "dummy.txt", "Now is the" & vbCrLf & " time for all ..."
> MsgBox "Line count for two-line file -- should be two: " &
> LineCount("dummy.txt")
> fOverWrite "dummy.txt", "Now is the" & vbCrLf & vbCr & " time for all ..."
> MsgBox "Line count for two-line file -- should be two: " &
> LineCount("dummy.txt")
> fOverWrite "dummy.txt", "Now is the" & vbCrLf & vbLf & " time for all ..."
> MsgBox "Line count for three-line file -- should be three: " &
> LineCount("dummy.txt")


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

> Sub fOverWrite(FilePath, sData)
> 'Try writing ASCII file.
> 'If error occurs, try writing Unicode file
> Dim objFSO 'Global file system object
> Set objFSO = CreateObject("Scripting.FileSystemObject")
> Dim oTS
> Set oTS = objFSO.OpenTextFile(FilePath, 2, true)
> On Error Resume Next
> oTS.Write sData
> If Err then
> On Error GoTo 0
> oTS.close
> Set oTS = objFSO.OpenTextFile(FilePath, 2, true, -1)
> On Error Resume Next
> oTS.Write sData
> If Err Then
> msgbox "Error in fOverWrite - tried ANSI and Unicode" & vbcrlf & _
> "FilePath = " & FilePath & vbcrlf & _
> "sData = " & sData
> wscript.quit
> End If
> End If
> On Error GoTo 0
> oTS.Close
> End Sub
>
> -Paul Randall
>
>
>

mayayana

unread,
Aug 5, 2008, 9:24:46 PM8/5/08
to

>
> Here is my contestant for the quickest/simplest file line counter ...
>
> Function LineCount(sFilespec)
> Const ForAppending = 8
> with CreateObject("Scripting.FileSystemObject")
> LineCount = .OpenTextFile(sFilespec, ForAppending).Line
> end with
> end Function
>

That is a nice method. I remember you posting
it but I didn't really pay attention. When people
start using "With CreateObject" my eyes glaze over.
It's too much trouble to decipher what their code
is actually doing. :)


Al Dunbar

unread,
Aug 6, 2008, 12:05:33 AM8/6/08
to

"mayayana" <mayaX...@rcXXn.com> wrote in message
news:uWkiGM29...@TK2MSFTNGP02.phx.gbl...

I disagree. I can't live WITHOUT WITH! ;-)

/Al


prebble

unread,
Aug 6, 2008, 4:08:50 AM8/6/08
to
Thanks Guys, for all the suggestions.
They all work. I didn't do any real benchmarking but here's what it looks
like ...

Bronze medal for Mayayana.
Some of my text files are gigantic datbase migration exports. So bronze for

Silver for Soler.
Was apparently faster but also implies a read of the data. (Good old DOS.)

Al Dunbar wins Gold.
I added a Msgbox to the end to display the result and it pops up
immediately.
Even on the big big files.

Thanks again,
Prebble


Tom Lavedas

unread,
Aug 6, 2008, 8:23:35 AM8/6/08
to

Al Dunbar? I didn't see that he had a horse in the race. No offense
Al, but do we look that much alike?

mayayana

unread,
Aug 6, 2008, 9:06:09 AM8/6/08
to
> I disagree. I can't live WITHOUT WITH! ;-)
>
With the disclaimer that I realize this is all
a mostly matter of personal taste...

I'm not faulting With. It makes a lot of
sense for repeat calls to the same object.
The code doesn't have to repeatedly get a
reference to that object and the flow of the
code is more clear. But there are a few things,
like use of colons to glue lines together and
extreme "With" that, while good for writing
terse code, make it difficult to follow what
the code's doing. Tom's line counting code
is great but the way it's written "hides"
Textstream. For someone with experience it's
a bit confusing and needs to be decrypted. For
someone who's not so familiar with Textstream
it's downright confounding.


prebble

unread,
Aug 6, 2008, 9:31:00 AM8/6/08
to
I don't know what the With does exactly,
but I tell myself that it's a function that allows Al to grab file info
variables
(or a VBS variable) that already belong to that file.
Including the number of lines.

And that allows us to dispense with re-calculating it using some other
method.
So for big files it is understandably faster.

Thanks for all your help.
Truly Olympian.

Prebble

mayayana

unread,
Aug 6, 2008, 10:14:13 AM8/6/08
to
With is a way to hold an object reference in
a block of code:

With Obj
.height = 10
.width = 10
.size = 10
End With

The hypothetical Obj object has height, width
and size properties. Rather than referencing Obj
for each property call, by putting all calls inside
With...End With it looks cleaner and is potentially
more efficient because the variable Obj only has
to be resolved once.

We were just discussing the pros and cons of
using With in conjunction with CreateObject. In
other words, Tom's code (it was Tom's, not Al's)
goes like so:

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

That's a code contraction that obscures the creation
of a Textstream object. Nothing wrong with it. It's just
that by contracting the code that way it becomes
potentially confusing. The function works by opening the
file for appending as a Textstream and using the Textstream
Line property to get the number of lines. Since the file
was opened "for appending" the insertion point is at the end
of the file, and since the Line property returns the current
line number the function is a clever way to get the line count
of the file without needing to handle the content. My criticism
wasn't with the function but with the code contraction.
One has to decipher what it's doing. Another way to do it, so
that one can easily see what the code is doing, is like so:

Function LineCount(sFilespec)
Dim FSO, TS
Set FSO = CreateObject("Scripting.FileSystemObject")
Set TS = FSO.OpenTextFile(sFilespec, 8)
LineCount = TS.Line
TS.Close
Set TS = Nothing
Set FSO = Nothing
End Function

(Which brings up another popular topic of debate -
whether one should set objects to nothing in script. :)

You could also use With in the code above:

With TS
LineCount = .Line
.Close
End With

Since there are only 2 calls to TS it's not worth
the trouble, but that sample shows how With works.
Anything starting with "." within the With block
refers to the referenced object. With is often handy
when working with IE or a document object, since the
object hierarchy for those is so extensive.

That all may be more than you care to know.
Personally I don't like to use code unless I understand
what it's doing.

Al Dunbar

unread,
Aug 8, 2008, 1:40:13 AM8/8/08
to

"Tom Lavedas" <tglb...@cox.net> wrote in message
news:a1958b7a-c2e3-4395...@l42g2000hsc.googlegroups.com...

I have no idea. I just like collecting unearned thanks because I don't have
to work so hard to get it.

But seriously, my first impression on reading the "gold" post was that I was
having an alzheimer's moment, as I had no clue what my contribution might
have been - ;-)

/Al


Al Dunbar

unread,
Aug 8, 2008, 1:45:57 AM8/8/08
to

"mayayana" <mayaX...@rcXXn.com> wrote in message
news:ee0FCU89...@TK2MSFTNGP02.phx.gbl...

>> I disagree. I can't live WITHOUT WITH! ;-)
>>
> With the disclaimer that I realize this is all
> a mostly matter of personal taste...
>
> I'm not faulting With. It makes a lot of
> sense for repeat calls to the same object.
> The code doesn't have to repeatedly get a
> reference to that object and the flow of the
> code is more clear.

Definitely an advantage when the code is written unambiguously...

> But there are a few things,
> like use of colons to glue lines together and
> extreme "With" that, while good for writing
> terse code, make it difficult to follow what
> the code's doing.

That's not a fault of the tools you mention, but of their misuse. Do you
blame the REM statement for poorly written comments? Or the DIM statement
for poorly named variables?

> Tom's line counting code
> is great but the way it's written "hides"
> Textstream. For someone with experience it's
> a bit confusing and needs to be decrypted. For
> someone who's not so familiar with Textstream
> it's downright confounding.

You may be right. But that is no reason not to illustrate its use where it
makes sense.

/Al


0 new messages