0

I know that this question was asked before, but I can't find the answer I'm looking for. I want to iterate through a directory and read all the files into an array. I don't know how many files the directory contains, therefore I don't know the size of the array. What is the best way for me to achieve this? I read "ReDim" is a performance killer, but I don't find any list-like collection available...

Am I missing something?

Community
  • 1
  • 1
user429400
  • 3,145
  • 12
  • 49
  • 68

2 Answers2

3

Either

Redim arr(0) as String

then

arr(ubound(arr)) = "newFilename"
ReDim Preserve arr(ubound(arr)+1)

then after the loop

ReDim Preserve arr(ubound(arr)-1)

to shrink it by the last empty element.


As alternative to using an array. You can use Collection or Dictionary.

Collections do not need to know their size at initialization. You add items using their Add() method.

To see a real example of implementation see this and that


If you do decide to go with the Dir() function and iterate to see how many files there are here's a sample function

Sub Main()

    ReDim arr(FilesInDirectoryCount("C:\...")) As String

End Sub

Function FilesInDirectoryCount(path As String)
  Dim f As String, c As Long
  f = Dir$(path)
  Do While Len(f) <> 0
    c = c + 1
    f = Dir$
  Loop
  FilesInDirectoryCount = c
End Function

or use this

Sub CountFiles()
    Dim strDir As String
    Dim fso As Object
    Dim objFiles As Object
    Dim obj As Object
    Dim lngFileCount As Long

    strDir = "C:\path..."

    Set fso = CreateObject("Scripting.FileSystemObject")

    Set objFiles = fso.GetFolder(strDir).Files

    lngFileCount = objFiles.count

    MsgBox lngFileCount

    Set objFiles = Nothing
    Set fso = Nothing
    Set obj = Nothing

End Sub
Community
  • 1
  • 1
  • 2
    No. No. No. **Never** iteratively grow an array by 1. But I like your collection idea. So think of this as +-INT_MAX – Bathsheba Oct 22 '13 at 12:42
  • @Bathsheba I have never noticed any significant difference or performance drop in VBA growing the array size by one. Any links I can read more about it? –  Oct 22 '13 at 12:52
  • 1
    I wanted to add as an answer your last idea. +1 for you for being first! – Kazimierz Jawor Oct 22 '13 at 12:53
  • Thanks, I feel really weird using a dictionary or a collection as they use a key, and I don't really have a key here. Just wanted a simple list (I know that many list implementations use ReDim, it's just funny that I have to write it myself) – user429400 Oct 22 '13 at 13:03
  • @Bathsheba You'd be absolutely right if this were an array of 10 million integers, but this is more likely to be an array of 100 strings of length 100k. `ReDim Preserve` isn't adding that much overhead in that case. – Chel Oct 22 '13 at 13:14
2

Method 1

One way (and standard insofar that it crops up a lot) is to dimension the array somewhat arbitrarily but based on the average use case.

When you're about to exceed the array size, redimension doubling the number of elements.

Then at the end, resize it down to the actual required size.

Method 2 (Bunk)

Traverse the directory to get the size. Then run your code with the array sized correctly. Not feasible for file systems though due to the lack of atomicity. The approach can work well though in other use cases; don't use it here though.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Yes, thanks, I wanted to avoid traversing the directory twice. If I won't find another way, I will go with method 1 :) – user429400 Oct 22 '13 at 12:40