Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > VB Script

Vista - Sort files collection ?

Reply
 
Old 08-20-2009   #1 (permalink)
Vilius Mockûnas


 
 

Sort files collection ?

Hello,

I use FileSystemObject to get files collection for some folder( Files
property )
How do I sort this collection by name by date and etc.
I can build sort logic of course but maybe there are easy standard ways ?

thanks
Vilius



My System SpecsSystem Spec
Old 08-20-2009   #2 (permalink)
ekkehard.horner


 
 

Re: Sort files collection ?

Vilius Mockûnas schrieb:
Quote:

> Hello,
>
> I use FileSystemObject to get files collection for some folder( Files
> property )
> How do I sort this collection by name by date and etc.
> I can build sort logic of course but maybe there are easy standard ways?
>
> thanks
> Vilius
>
(1) use .Run or .Exec to do a "dir /O ..." command and use its
output: simple, fast, but not very flexible (what hides behind
your "and etc"?)

(2) put the objects of the files collection in an array, write a
sort sub/function that uses the relevant property/ies for
comparison: a lot of work

(3) put the properties of the objects in the files collection in
a disconnected ADO recordset, use its .Sort method to solve
your problem: easy and flexible

My System SpecsSystem Spec
Old 08-20-2009   #3 (permalink)
mayayana


 
 

Re: Sort files collection ?

Here's a basic script that alphabetizes all file
names in C:\Windows. It's not terribly complex,
but it would get more tricky if you want to sort
by date. This particular QuickSort sorts non-case-
sensitive. (Otherwise you get all capitalized
names first.) For dates, as an offhand guess, I
think you'd want to convert the dates to numeric
and then use another version of QuickSort in
which you drop the Ucase operation. (The sorting
uses > comparison, so it can be adapted to both
words and numbers.)

I was actually just exploring sort routines a few
days ago. Interesting stuff. On my old Win98SE
machine with a Sempron 1,800 Mhz CPU, a basic
QuickSort can sort close to 30,000 words per second
in a VBScript, and it doesn't seem to slow down with
increasing size. (The more well known bubble sort,
by comparison, is lucky to do 1,000 in a second and
quickly slows to the point of unusability as the array to
sort gets bigger.

'--------------------------------------------------
Sort all files in C:\Windows alphabetically
'------------------------------

Dim FSO, oFol, oFils, oFil, AFils(), i2
Set FSO = CreateObject("Scripting.FileSystemObject")
Set oFol = FSO.GetFolder("C:\Windows")
Set oFils = oFol.Files
ReDim AFils(oFils.count - 1)
i2 = 0
For Each oFil in oFils
AFils(i2) = oFil.Name
i2 = i2 + 1
Next
Set oFils = Nothing
Set oFol = Nothing
Set FSO = Nothing

QuickSort AFils, 0, 0

Dim S2
S2 = Join(AFils, vbCrLf)

'-- watch out for this. An oversize message box
'-- sometimes puts the close button offscreen.
MsgBox S2


Sub QuickSort(AIn, LBeg, LEnd)
Dim LBeg2, vMid, LEnd2, vSwap
If (LEnd = 0) Then LEnd = UBound(AIn)
LBeg2 = LBeg
LEnd2 = LEnd
vMid = UCase(AIn((LBeg + LEnd) \ 2))
Do
Do While UCase(AIn(LBeg2)) < vMid And LBeg2 < LEnd
LBeg2 = LBeg2 + 1
Loop
Do While vMid < UCase(AIn(LEnd2)) And LEnd2 > LBeg
LEnd2 = LEnd2 - 1
Loop
If LBeg2 <= LEnd2 Then
vSwap = AIn(LBeg2)
AIn(LBeg2) = AIn(LEnd2)
AIn(LEnd2) = vSwap
LBeg2 = LBeg2 + 1
LEnd2 = LEnd2 - 1
End If
Loop Until LBeg2 > LEnd2
If LBeg < LEnd2 Then QuickSort AIn, LBeg, LEnd2
If LBeg2 < LEnd Then QuickSort AIn, LBeg2, LEnd
End Sub



Quote:

>
> I use FileSystemObject to get files collection for some folder( Files
> property )
> How do I sort this collection by name by date and etc.
> I can build sort logic of course but maybe there are easy standard ways ?
>
> thanks
> Vilius
>
>

My System SpecsSystem Spec
Old 08-20-2009   #4 (permalink)
Eric


 
 

Re: Sort files collection ?

If .NET is installed, use the .Sort method of a
CreateObject("System.Collections.ArrayList") object.
If not, do the ugly vbscript sort junk.
If you can get a directory listing to a file, use the directory options /OD
to sort.
If not, sorting by file date could get ugly.

"mayayana" <mayaXXyana@xxxxxx> wrote in message
news:uOpH2baIKHA.4436@xxxxxx
Quote:

> Here's a basic script that alphabetizes all file
> names in C:\Windows. It's not terribly complex,
> but it would get more tricky if you want to sort
> by date. This particular QuickSort sorts non-case-
> sensitive. (Otherwise you get all capitalized
> names first.) For dates, as an offhand guess, I
> think you'd want to convert the dates to numeric
> and then use another version of QuickSort in
> which you drop the Ucase operation. (The sorting
> uses > comparison, so it can be adapted to both
> words and numbers.)
>
> I was actually just exploring sort routines a few
> days ago. Interesting stuff. On my old Win98SE
> machine with a Sempron 1,800 Mhz CPU, a basic
> QuickSort can sort close to 30,000 words per second
> in a VBScript, and it doesn't seem to slow down with
> increasing size. (The more well known bubble sort,
> by comparison, is lucky to do 1,000 in a second and
> quickly slows to the point of unusability as the array to
> sort gets bigger.
>
> '--------------------------------------------------
> Sort all files in C:\Windows alphabetically
> '------------------------------
>
> Dim FSO, oFol, oFils, oFil, AFils(), i2
> Set FSO = CreateObject("Scripting.FileSystemObject")
> Set oFol = FSO.GetFolder("C:\Windows")
> Set oFils = oFol.Files
> ReDim AFils(oFils.count - 1)
> i2 = 0
> For Each oFil in oFils
> AFils(i2) = oFil.Name
> i2 = i2 + 1
> Next
> Set oFils = Nothing
> Set oFol = Nothing
> Set FSO = Nothing
>
> QuickSort AFils, 0, 0
>
> Dim S2
> S2 = Join(AFils, vbCrLf)
>
> '-- watch out for this. An oversize message box
> '-- sometimes puts the close button offscreen.
> MsgBox S2
>
>
> Sub QuickSort(AIn, LBeg, LEnd)
> Dim LBeg2, vMid, LEnd2, vSwap
> If (LEnd = 0) Then LEnd = UBound(AIn)
> LBeg2 = LBeg
> LEnd2 = LEnd
> vMid = UCase(AIn((LBeg + LEnd) \ 2))
> Do
> Do While UCase(AIn(LBeg2)) < vMid And LBeg2 < LEnd
> LBeg2 = LBeg2 + 1
> Loop
> Do While vMid < UCase(AIn(LEnd2)) And LEnd2 > LBeg
> LEnd2 = LEnd2 - 1
> Loop
> If LBeg2 <= LEnd2 Then
> vSwap = AIn(LBeg2)
> AIn(LBeg2) = AIn(LEnd2)
> AIn(LEnd2) = vSwap
> LBeg2 = LBeg2 + 1
> LEnd2 = LEnd2 - 1
> End If
> Loop Until LBeg2 > LEnd2
> If LBeg < LEnd2 Then QuickSort AIn, LBeg, LEnd2
> If LBeg2 < LEnd Then QuickSort AIn, LBeg2, LEnd
> End Sub
>
>
>
>
Quote:

>>
>> I use FileSystemObject to get files collection for some folder( Files
>> property )
>> How do I sort this collection by name by date and etc.
>> I can build sort logic of course but maybe there are easy standard ways ?
>>
>> thanks
>> Vilius
>>
>>
>
>

My System SpecsSystem Spec
Old 08-20-2009   #5 (permalink)
mayayana


 
 

Re: Sort files collection ?

> If .NET is installed, use the .Sort method of a
Quote:

> CreateObject("System.Collections.ArrayList") object.
> If not, do the ugly vbscript sort junk.
That's an interesting logic: Loading a 200MB+
dependency, that won't be on all machines, is
less "ugly" than 20-odd lines of VBScript "junk"?


My System SpecsSystem Spec
Old 08-20-2009   #6 (permalink)
ekkehard.horner


 
 

Re: Sort files collection ?

Eric schrieb:
Quote:

> If .NET is installed, use the .Sort method of a
> CreateObject("System.Collections.ArrayList") object.
AFAIK, you can use the ArrayList only with one-dimensional arrays (with
items of the same type). So sorting a file collection (essentially a
table) will be difficult, perhaps even ugly in the sense that you
have to do silly things - like putting the sizes right aligned in the
front of the strings or formatting the m/d/y dates to make them
sortable.
Quote:

> If not, do the ugly vbscript sort junk.
Why do you say that? What is wrong with mayayana's quicksort?
Quote:

> If you can get a directory listing to a file, use the directory options /OD
> to sort.
> If not, sorting by file date could get ugly.
Using dir will force you to shell out for each order you need.

The best method - in my opinion - would be the ADO approach.

[...]
My System SpecsSystem Spec
Old 08-20-2009   #7 (permalink)
Richard Mueller [MVP]


 
 

Re: Sort files collection ?


"ekkehard.horner" <ekkehard.horner@xxxxxx> wrote in message
news:4a8db4bd$0$31331$9b4e6d93@xxxxxx-online.net...
Quote:

> Eric schrieb:
Quote:

>> If .NET is installed, use the .Sort method of a
>> CreateObject("System.Collections.ArrayList") object.
>
> AFAIK, you can use the ArrayList only with one-dimensional arrays (with
> items of the same type). So sorting a file collection (essentially a
> table) will be difficult, perhaps even ugly in the sense that you
> have to do silly things - like putting the sizes right aligned in the
> front of the strings or formatting the m/d/y dates to make them
> sortable.
>
Quote:

>> If not, do the ugly vbscript sort junk.
>
> Why do you say that? What is wrong with mayayana's quicksort?
>
Quote:

>> If you can get a directory listing to a file, use the directory options
>> /OD to sort.
>> If not, sorting by file date could get ugly.
>
> Using dir will force you to shell out for each order you need.
>
> The best method - in my opinion - would be the ADO approach.
>
> [...]
I would use the ADO disconnected recordset and the Sort method provided with
that object. I use it often. However, I don't know if it is faster than
mayayana's sort.

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--


My System SpecsSystem Spec
Old 08-21-2009   #8 (permalink)
mayayana


 
 

Re: Sort files collection ?

> Even though I hate to require .NET, I found
Quote:

> a .NET function that was faster than other methods I tried by a factor of
at
Quote:

> least 2 (and sometimes 10).
.....
Quote:

> ' List object available to scripting from .Net framework
> Set aDataList = CreateObject("System.Collections.ArrayList")
>
I'd be interested in .Net if it were all scriptable
COM, and if the runtime were not so gigantic. But as
it is, like Java, .Net seems to have very little purpose
outside of corporate intranet applet writing. I don't
have either the JVM or the .Net runtime installed
myself. I've never had any reason to do so, so it
would just be adding extra bloat and security risks
for no reason. And I wouldn't assume that others have
it installed. ...Which is not even getting into the
gargantuan resource load and initial lagtime that
System.Collections.ArrayList must be involve. (I
assume the whole 200+ MB of the .Net runtime
gets loaded for that call; and .Net software is
notoriously slow to get started because of that.)

But I suppose if one is writing only to a known
target audience that's known to be running .Net
software, then there's no reason not to
use what's available.

----------

With the code below: I don't do much with databases
and have never used ADO. So I find it hard to make
sense of what you wrote. The idea here is that you
have to create a record with several fields for each
item? And create a database for those records? In my
own sort tests I've been dropping a text file onto a script,
which uses Split(filetext, " ") to create an array of words
to sort. How does such an array get put into records?
Would it be something like:

For i = 0 to UBound(a)
objDataList.AddNew
objDataList("Word") = a(i)
objDataList.Update
Next

OR

For each fil in oFils
objDataList.AddNew
objDataList("Word") = Fil.Name
objDataList.Update
Next

Does that make sense? I'm not clear
about which fields are required or what
"Number" and "Index" are for.

And what do you mean by, "generally
you already have a recordset"? I was assuming
that the point was that ADO sorting could be
used to sort something like an array efficiently,
without necessarily having a database. Can it
really be more efficient to create a database
to be sorted, rather than just sorting an array?
The QuickSort I posted is virtually instant up
to several thousand items. It only took about
2 1/2 seconds to sort 70,000+ words.

Quote:

> An simple example using ADO and a disconnected recordset follows:
> ===============
> Const adVarChar = 200
> Const adSmallInt = 2
> Const adDBTimeStamp = 135
> Const MaxCharacters = 255
>
> ' Setup disconnected recordset.
> Set objDataList = CreateObject("ADODB.Recordset")
> objDataList.Fields.Append "Description", adVarChar, MaxCharacters
> objDataList.Fields.Append "Number", adSmallInt
> objDataList.Fields.Append "Index", adSmallInt
> objDataList.Fields.Append "Date", adDBTimeStamp, MaxCharacters
> objDataList.Open
>
> ' Create a few records.
> objDataList.AddNew
> objDataList("Description") = "Start"
> objDataList("Number") = 4
> objDataList("Index") = 3
> objDataList("Date") = #8/15/2007#
> objDataList.Update
>
> objDataList.AddNew
> objDataList("Description") = "Start"
> objDataList("Number") = 4
> objDataList("Index") = 2
> objDataList("Date") = #8/18/2007#
> objDataList.Update
>
> objDataList.AddNew
> objDataList("Description") = "Start"
> objDataList("Number") = 4
> objDataList("Index") = 1
> objDataList("Date") = #8/17/2007#
> objDataList.Update
>
> objDataList.AddNew
> objDataList("Description") = "Middle"
> objDataList("Number") = 2
> objDataList("Index") = 3
> objDataList("Date") = #8/15/2007#
> objDataList.Update
>
> objDataList.AddNew
> objDataList("Description") = "End"
> objDataList("Number") = 3
> objDataList("Index") = 3
> objDataList("Date") = #8/15/2007#
> objDataList.Update
>
> objDataList.Sort = "Number,Index"
>
> ' Display sorted values.
> objDataList.MoveFirst
> Do Until objDataList.EOF
> Wscript.Echo objDataList.Fields.Item("Description") _
> & "," & objDataList.Fields.Item("Number") _
> & "," & objDataList.Fields.Item("Index") _
> & "," & objDataList.Fields.Item("Date")
> objDataList.MoveNext
> Loop
> objDataList.Close
> ==========
> Generally you already have a recordset and you populate the diconnected
> recordset in a loop, so you don't have so much code.
>
> --
> Richard Mueller
> MVP Directory Services
> Hilltop Lab - http://www.rlmueller.net
> --
>
>

My System SpecsSystem Spec
Old 08-21-2009   #9 (permalink)
mayayana


 
 

Re: Sort files collection ?

> There are a lot of other sources on sorting algorithms and their benefits
Quote:

> and shortcomings and formulas on how the time for sorting similar sets of
> objects varies with the number of items being sorted. Some algoriths have
> widely varying execution times for a given number if items, depending on
how
Quote:

> they are initially ordered. Other algorithms, such as Shell sort, have
> similar execution times no matter what the initial order is.
>
Yes. I didn't do very extensive testing myself but
I did notice that. Bubble sort, especially, seems to get
slower and slower as the number of items increases.
Though with the exception of bubble sort, the methods I
was testing don't seem to matter all that much until one
gets into the hundreds of thousands or millions
of items. If a sort routine can sort, say, 10,000 items
in 150 ms, it may take 300 ms on the second run and
220 ms on the third. VBScript is just too crude to get
high accuracy in tests on that scale. But even though
there's a 200% difference in the range of results, they're
all essentially instant for most purposes. It's unlikely
that I'll ever need to sort more than a few hundred items.



My System SpecsSystem Spec
Old 08-22-2009   #10 (permalink)
Richard Mueller [MVP]


 
 

Re: Sort files collection ?

mayayana wrote:
Quote:

> ----------
>
> With the code below: I don't do much with databases
> and have never used ADO. So I find it hard to make
> sense of what you wrote. The idea here is that you
> have to create a record with several fields for each
> item? And create a database for those records? In my
> own sort tests I've been dropping a text file onto a script,
> which uses Split(filetext, " ") to create an array of words
> to sort. How does such an array get put into records?
> Would it be something like:
>
> For i = 0 to UBound(a)
> objDataList.AddNew
> objDataList("Word") = a(i)
> objDataList.Update
> Next
>
> OR
>
> For each fil in oFils
> objDataList.AddNew
> objDataList("Word") = Fil.Name
> objDataList.Update
> Next
>
> Does that make sense? I'm not clear
> about which fields are required or what
> "Number" and "Index" are for.
>
> And what do you mean by, "generally
> you already have a recordset"? I was assuming
> that the point was that ADO sorting could be
> used to sort something like an array efficiently,
> without necessarily having a database. Can it
> really be more efficient to create a database
> to be sorted, rather than just sorting an array?
> The QuickSort I posted is virtually instant up
> to several thousand items. It only took about
> 2 1/2 seconds to sort 70,000+ words.
I use ADO to sort recordsets resulting from queries of Active Directory or
of SQL Server databases. You are correct that if the data is in an array,
you have the extra step of looping through the array and adding the values
to a disconnected recordset. Yes, this recordset is like a database, but it
is in memory and is much faster to work with than any database residing in a
file system. If you are sorting an array, I'm thinking the data came from
somewhere, and it might be possible to read the data into a disconnected
recordset in the first place instead of an array. I think it would be almost
as fast to populate a recordset as the array.

Following are two examples using disconnected ADO recordsets to sort. The
first converts an array of string values into a disconnected recordset to
sort. The second example retrieves all user names from Active Directory in
an ADO recordset, disconnects the recordset, and then sorts the values
before displaying. The example I posted earlier might have been confusing.
The "Number" and "Index" fields were just examples. My example below has
just one field.

This first example is one I used when I was comparing the performance of
several sort methods, including bubble sort (slowest), something called a
Benny sort (Benny Pedersen was active in the newsgroups), and using .NET to
sort (I have to admit the fastest method I found). This script shows that
the sort takes almost no time, but a fraction of a second is required to
setup the recordset and read the array values into it. It requires MDAC on
the client, but I believe any version will do:
==============
' ArraySort.vbs
' VBScript program to test several methods to sort.
Option Explicit

Dim arrAscending, adoDataList, strValue, intCount
Dim dtmT1, dtmT2, dtmT3

Const adVarChar = 200
Const MaxCharacters = 255

arrRandom = Array("Potato", "Lettuce", "Onion", "Bread", _
"Apple", "Orange", "Cherry", "Pear", "Milk", "Eggs", _
"Hamburger", "Ham", "Corn", "Beans", "Soup", "Pepper", _
"Salt", "Cornmeal", "Swiss Cheese", "Cheddar", "Basil", _
"Paprika", "Oregano", "Chili Powder", "Cottage Cheese", _
"French Fries", "Onion Rings", "Cola", "Waffles", "Peas", _
"Baked Beans", "Chili", "Pinto Beans", "Black Eyed Peas", _
"15 Bean Soup", "Cream", "Cream Cheese", "Yogurt", _
"Cake", "Ice Cream", "Cookies", "Butter", "Rye Bread", _
"Rice Cakes", "Whole Wheat Bread", "Butter Cookies", _
"Green Onion", "Celery", "Garlic Bread", "Pizza", _
"Tomato", "Grapes", "Black Beans", "Pancakes", "Red Beans", _
"Frozen Yogurt", "Tomato Paste", "Yeast", "Stewed Tomatoes", _
"French Toast", "Ginger Snaps", "Candy", "Chocolate", _
"Raisins", "Bay Leaves", "Rosemary", "Garlic Powder", _
"Thyme", "Macaroni", "Clam Chowder", "Split Pea")

dtmT1 = Timer()

' Setup disconnected recordset.
Set adoDataList = CreateObject("ADODB.Recordset")
adoDataList.Fields.Append "Value", adVarChar, MaxCharacters
adoDataList.Open

For Each strValue In arrRandom
adoDataList.AddNew
adoDataList("Value") = strValue
adoDataList.Update
Next

dtmT2 = Timer()

adoDataList.Sort = "Value"

dtmT3 = Timer()

' Display sorted values.
intCount = 0
adoDataList.MoveFirst
Do Until adoDataList.EOF
Wscript.Echo adoDataList.Fields.Item("Value")
intCount = intCount + 1
adoDataList.MoveNext
Loop
adoDataList.Close

Wscript.Echo "Number of values: " & CStr(intCount)
Wscript.Echo "ADO Sort setup: " & FormatNumber(dtmT2 - dtmT1, 4)
Wscript.Echo "ADO Sort : " & FormatNumber(dtmT3 - dtmT2, 4)
Wscript.Echo "ADO Sort total: " & FormatNumber(dtmT3 - dtmT1, 4)
==========
This second example shows how to sort all user names retrieved from Active
Directory. The trick is to specify the CursorLocation, CursorType, and
LockType to allow the recordset to be disconnected and sorted.
==========
Option Explicit

Dim objRootDSE, strDNSDomain, adoConnection
Dim strBase, strFilter, strAttributes, strQuery, adoRecordset
Dim strDN, intCount, strName

Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adUseClient = 3

' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use ADO to search Active Directory.
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"

Set adoRecordset = CreateObject("ADODB.Recordset")
adoRecordset.ActiveConnection = adoConnection
adoRecordset.CursorLocation = adUseClient
adoRecordset.CursorType = adOpenStatic
adoRecordset.LockType = adLockOptimistic

' Search entire domain.
strBase = "<LDAP://" & strDNSDomain & ">"

' Filter on all user objects.
strFilter = "(&(objectCategory=person)(objectClass=user))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName,sAMAccountName"

' Construct the LDAP query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"

' Run the query.
adoRecordset.Source = strQuery
adoRecordset.Open

' Disconnect the recordset.
Set adoRecordset.ActiveConnection = Nothing
adoConnection.Close

' Sort the recordset.
adoRecordset.Sort = "sAMAccountName"
adoRecordset.MoveFirst

' Enumerate the resulting recordset.
intCount = 0
Do Until adoRecordset.EOF
' Retrieve values.
strDN = adoRecordset.Fields("distinguishedName").Value
strName = adoRecordset.Fields("sAMAccountName").Value
Wscript.Echo strName & ": " & strDN
intCount = intCount + 1
adoRecordset.MoveNext
Loop

' Clean up.
adoRecordset.Close

Wscript.Echo "Number of objects: " & CStr(intCount)
--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--


My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
Collection of Batch files for everyone to use! General Discussion
Sort by date? And Folder missing files General Discussion
Re: Can I sort within a sort, in folder view (eg., Name, Date) Live Mail
Sort by name doesnt sort correctly in my opinion Vista file management
Disabling auto alphabetical order sort in start / program files Vista General


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46