Clutch
Clutch

Reputation: 189

vbscript divide files into four groups

I am developing a script to divide the number of files in a folder into four groups. These will be turned into four batch files but for now the issue is dividing them up as evenly as possible.

The script below will work somewhat - if I have a Count that will be divided by 4 evenly but if I have an odd number, no go and less than four will crash. You can run the script just replace the "C:\1_SourceData\Section_16\" with your own path of files. If you un-comment the section 'Add remainder to front', it was to thow any extra files, like an odd number, to the first batch but that does not quite work. The number of files in the folder will range from 1 to 25.

Any help would be most appreciated.

Option Explicit 
Dim fileList : Set fileList = GetFileList("C:\1_SourceData\Section_16\") 
Dim NumOfFiles : NumOfFiles = fileList.Count - 1 
Dim modNumber : modNumber = NumOfFiles/4 
Dim remainder : remainder = NumOfFiles Mod modNumber 

Dim string1 : string1 = "batch" & batchCounter 
Dim string2 : string2 = "" 

'Add remainder to front 
'Dim i : i = 0 
'For i = NumOfFiles - remainder To NumOfFiles 
' string2 = string2 & vbTab & fileList(i) & vbNewLine 
'Next 

Dim batchCounter : batchCounter = 1 
Dim file 
Dim j : j = 0 
For Each file In fileList  
string2 = string2 & vbTab & file & vbNewLine 
  j = j + 1   

If j Mod modNumber = 0 Then 
    WScript.Echo string1 & vbNewLine & string2 
    batchCounter = batchCounter + 1 
    string1 = "batch" & batchCounter 
    string2 = ""  
End If 
Next 

Public Function GetFileList(path)  
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
Dim fileList : Set fileList = CreateObject("System.Collections.ArrayList")  
Dim InfFolder : Set InfFolder = objFSO.GetFolder(path)  
Dim File   

For Each File In objFSO.GetFolder(path).Files  
    fileList.Add File  
    Next  Set GetFileList = fileList 
End Function

Upvotes: 0

Views: 170

Answers (2)

Tomalak
Tomalak

Reputation: 338228

You could structure your loop differently.

There are F files that should be devided into B batches of X files each. Two things can happen:

  1. F is an exact multiple of B, in which case X = F / B
  2. F is not an exact multiple of B, in which case X = (F / B) + 1

Therefore we can write two loops that (together) count from 1 to F:

Option Explicit

Const BATCHES = 4
Const PATH = "C:\1_SourceData\Section_16"

Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")  
Dim fileList : Set fileList = GetFileList(PATH)
Dim b, i, f, x

f = fileList.Count
x = CInt(f / BATCHES)
If x * BATCHES < f Then x = x + 1

For b = 0 To BATCHES - 1
    If (b * x < f) Then WScript.Echo "batch" & (b + 1)
    For i = b * x To (b + 1) * x - 1
        If (i < f) Then WScript.Echo vbTab & fileList(i)
    Next
Next

Function GetFileList(path)
    Dim file
    Set GetFileList = CreateObject("System.Collections.ArrayList")
    For Each file In FSO.GetFolder(path).Files
        GetFileList.Add File
    Next 
End Function

Upvotes: 0

Ekkehard.Horner
Ekkehard.Horner

Reputation: 38755

The problem is: the .Files collection is accessible via For Each only. A 'distribution by number' (think modulo) needs an extra counter. Demo script:

Option Explicit

ReDim a(3) ' 4 groups/collections
Dim i
For i = 0 To UBound(a)
    Set a(i) = CreateObject("System.Collections.ArrayList")
Next
i = 0
Dim f
' fake a list of elms accessible via For Each only
For Each f In Split("a b c d e f g h i j k l m n")
    a(i Mod 4).Add f ' use Mod to determine the 'bucket'
    i = i + 1 ' counter needed for Mod
Next
For i = 0 To UBound(a)
    WScript.Echo i, Join(a(i).ToArray())
Next

output:

cscript 40639293.vbs
0 a e i m
1 b f j n
2 c g k
3 d h l

Upvotes: 2

Related Questions