1

I'm trying to write some code that will create a dropdown list that contains all files with a certain file extension in a folder. Initial code here:

Dim FSOLibrary As Object
Dim FSOFolder As Object
Dim FSOFile As Object
Dim fp As String
Dim i As Integer    

fp = Environ("UserProfile") & "\OneDrive\Desktop\Test"

Set FSOLibrary = CreateObject("Scripting.FileSystemObject")
Set FSOFolder = FSOLibrary.GetFolder(fp)
Set FSOFile = FSOFolder.Files

i = 1

For Each FSOFile In FSOFile
    If FSOFile Like "*.txt*" Then
        'just put the name into column B for testing
        Range("B" & i).Value = FSOFile.Name
        i = i + 1
    End If    
Next FSOFile

Obviously I need to add the data validation part of the code in, but I'm not sure how best to construct it. The number of files is dynamic.

I was thinking of putting all the files that match the desired file extension type into an array, and then writing each entry of the array into the data validation section?

I've seen the Dir() used quite a lot but I don't fully understand it, so have opted to use fso.

2
  • Where are you trying to create the drop-down? In a worksheet cell? In a Worksheet FormControl? In a UserForm? Commented Nov 5, 2019 at 15:31
  • Just in a worksheet cell to make it simple for the end-user. Commented Nov 5, 2019 at 15:35

1 Answer 1

1

Using Excel Range

Building dropdown usually consists of 2 things:

  • locating the range, which is used for the list of the values
  • writing these values to a string, separated with a comma

The code below, does exactly that:

  • First it loops from row 1 to row endRow, to the values in these rows. These are written to a string validationString and a comma is added after every cell value
  • the last comma is useless, thus it is removed, together with the space: validationString = Left(validationString, Len(validationString) - 2)
  • the validationString is passed to the .Validation property of the cell "A1".

Sub TestMe()

    Dim wks As Worksheet: Set wks = Worksheets(1)
    Dim endRow As Long: endRow = LastRow(wks.Name, 3)
    Dim validationString As String
    Dim i As Long

    For i = 1 To endRow
        validationString = validationString & wks.Cells(i, "C") & ", "
    Next i

    validationString = Left(validationString, Len(validationString) - 2)

    With Worksheets(1).Cells(1, "A").Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
                        Operator:=xlBetween, _
                        Formula1:=validationString
    End With

End Sub


Function LastRow(wsName As String, Optional columnToCheck As Long = 1) As Long
    Dim ws As Worksheet
    Set ws = Worksheets(wsName)
    LastRow = ws.Cells(ws.Rows.Count, columnToCheck).End(xlUp).Row
End Function

enter image description here


Without writing to a range

Here the "trick" is take the data from the loop and write it to a list, while looping through the fsoFolder.Files:

Sub TestMe()

    Dim filePath As String
    filePath = Environ("UserProfile") & "\Desktop\QA"
    Dim fsoLibrary As Object: Set fsoLibrary = CreateObject("Scripting.FileSystemObject")
    Dim fsoFolder As Object: Set fsoFolder = fsoLibrary.GetFolder(filePath)
    Dim fsoFile As Object

    Dim validationString As String
    For Each fsoFile In fsoFolder.Files
        If fsoFile Like "*.txt*" Then
            validationString = validationString & fsoFile.Name & ", "
        End If
    Next fsoFile

    validationString = Left(validationString, Len(validationString) - 2)

    With Worksheets(1).Cells(1, "A").Validation
        .Delete
        .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, _
                        Operator:=xlBetween, _
                        Formula1:=validationString
    End With

End Sub
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for the response. So would I have to write each of the file names to a range of cells, then create the data validation (similar to how you've done). Or is there some way to avoid writing the file names? Ideally the user will be able to just click the dropdown see a list of relevant files, select one, and then run a macro that takes that filename as a parameter.
Instead of worrying about how many items there are and collecting them all into a validation string I'd suggest simply using a dynamic named range. Then use the dynamic named range's name as the validation string. IOW all that would change is the list of files in the dynamic range. The validation would not need to be touched.
@AnalysisLearner - if you do not write the names, it becomes a little more "magical". In general, there is a way - concatenate the validationString from the loop in your code like this - validationString = validationString & FSOFile.Name & ", ". Then remove the last 2 signs and use the code to write the validation.
@SmileyFtW - named range is a good alternative indeed. Anyway, the string is a bit better, if the OP does not want to write anything in the Excel file (see his first comment)
Thanks, both. Some cool new ideas for me in here. (It won't let me upvote as not enough rep).
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.