Home » excel » arrays – Excel VBA Multiselect and Set Workbooks as Variables

arrays – Excel VBA Multiselect and Set Workbooks as Variables

Posted by: admin April 23, 2020 Leave a comment

Questions:

Previously I had a block of code that would use GetOpenFilename for a single file, set variables, ask if you wanted to select another file(Y/N), execute more code to open 2nd file, etc. If user selected ‘NO’ at any point, it would skip remaining code.

What I am attempting to do is have a macro stored within a workbook open up to 3 files. It then needs to make each workbook it’s own variable because it needs to find a string in each of the workbooks before passing those variables onto another Module. I can’t figure how for the code to Set each workbook. Appreciate any help.

Dim files As Variant
Dim i As Integer
Dim WBtemp1 As Workbook
Dim WBtemp2 As Workbook
Dim WBtemp3 As Workbook
Dim RF As String

    files = Application.GetOpenFilename(FileFilter:="Excel workbooks (*.xls*),*.xls*", Title:="Please select up to 3 Files", MultiSelect:=True)

    If Not IsArray(files) Then Exit Sub

    If UBound(files) < 3 Then
        MsgBox "You have selected more than 3 files."

    End If



    For i = 1 To UBound(files)

    Workbooks.Open files(i)

    Next

    Set WBtemp1 = Workbooks(1)
    Set WBtemp2 = Workbooks(2)
    Set WBtemp3 = Workbooks(3)


    RF = WBtemp1.Worksheets(1).Range("V3")
    RF1 = Mid(RF, 12, 8)
    RF = WBtemp2.Worksheets(1).Range("V3")
    RF2 = Mid(RF, 12, 8)
    RF = WBtemp3.Worksheets(1).Range("V3")
    RF3 = Mid(RF, 12, 8)



        Call Macro2(WBtemp1, WBtemp2, WBtemp3, RF1, RF2, RF3)
How to&Answers:

To set your variables to point to the 3 selected workbooks, you need to use the values stored in the files array and extract the filename without the folder path and then use it to refer to the workbook:

Dim filenames(1 To 3) As String
For i = 1 To 3
    filenames(i) = Right(files(i), Len(files(i)) - InStrRev(files(i), "\"))
Next i
Dim WBtemp1, WBtemp2, WBtemp3

Set WBtemp1 = Workbooks(filenames(1))
Set WBtemp2 = Workbooks(filenames(2))
Set WBtemp3 = Workbooks(filenames(3))

Or instead, even better, you can assign each workbook to a variable as you open then by doing:

Set WBtemp1 = Workbooks.Open(files(1))
Set WBtemp2 = Workbooks.Open(files(2))
Set WBtemp3 = Workbooks.Open(files(3))

Answer:

Here is code that I think you can actually use. It shows how to create and handle the array of workbooks and creates a similar array for Rf. I have added a Macro2 sub which takes the arrays as argument as well as a function which takes only one of the array members (a Sub would be called in the same manner).

Option Explicit

Sub SelectFiles()

    Dim Files As Variant
    Dim WbTempl() As Workbook
    Dim Tmp As String
    Dim Rf() As String
    Dim i As Integer

    Files = Application.GetOpenFilename(FileFilter:="Excel workbooks (*.xls*),*.xls*", _
                                        Title:="Please select up to 3 Files", _
                                        MultiSelect:=True)

    If IsArray(Files) Then                  ' avoid jumps: let the code flow
        For i = 1 To UBound(Files)
            If i > 3 Then
                MsgBox "You selected " & UBound(Files) & " files." & vbCr & _
                       "Only the first 3 will be processed.", _
                       vbInformation, "Too many files selected"
                ReDim Preserve Files(1 To 3)
                Exit For
            Else
                ReDim Preserve WbTempl(1 To i)
            End If
            Set WbTempl(i) = Workbooks.Open(Files(i))
        Next i

        ReDim Rf(1 To UBound(WbTempl))
        For i = 1 To UBound(WbTempl)
            Tmp = WbTempl(i).Worksheets(1).Range("V3").Value
            If Len(Tmp) < 20 Then
                Tmp = String(20, "R")
            End If
            Rf(i) = Mid(Tmp, 12, 8)
            If IsTemplate(WbTempl(i), Rf(i)) = True Then
                Tmp = " "
            Else
                Tmp = " not "
            End If
            MsgBox WbTempl(i).Name & " is" & Tmp & "a template", vbInformation
        Next i

        ' using meaningful names isn't a useless exercise
        ' using nondescript names will cost you much more time eventually
        Macro2 WbTempl, Rf
    End If
End Sub

Private Sub Macro2(Wb() As Workbook, _
                   Rf() As String)

    Dim i As Integer

    For i = 1 To UBound(Wb)
        Debug.Print Rf(i), Wb(i).Name
    Next i
End Sub

Private Function IsTemplate(Wb As Workbook, _
                           ByVal Rf As String) As Boolean

    Debug.Print "Here is Function 'IsTemplate'. Current Rf = "; Rf
    IsTemplate = (Wb.FileFormat = xlTemplate)
End Function

Answer:

Amended to this. Added an On Error Resume Next in the module.

On Error Resume Next
Dim MyFiles As Variant
Dim i As Integer
Dim WBtemp1 As Workbook
Dim WBtemp2 As Workbook
Dim WBtemp3 As Workbook

    MyFiles = Application.GetOpenFilename(FileFilter:="Excel workbooks(*.xls*),*.xls*", Title:="Please select up to 3 Files", MultiSelect:=True)

    If Not IsArray(MyFiles) Then Exit Sub

    If UBound(MyFiles) > 3 Then
        MsgBox "You have selected more than 3 files."

    End If

    For i = 1 To UBound(MyFiles)

    Workbooks.Open MyFiles(i)

    Next i


    Set WBtemp1 = Workbooks.Open(MyFiles(1))

    If UBound(MyFiles) < 2 Then GoTo Sng Else GoTo Mult

Mult:
    Set WBtemp2 = Workbooks.Open(MyFiles(2))
    Set WBtemp3 = Workbooks.Open(MyFiles(3))

        RF = WBtemp1.Worksheets(1).Range("V3")
        RF1 = Mid(RF, 12, 8)

        RF = WBtemp2.Worksheets(1).Range("V3")
        RF2 = Mid(RF, 12, 8)

        RF = WBtemp3.Worksheets(1).Range("V3")
        RF3 = Mid(RF, 12, 8)

Sng:
    Set wb1 = ActiveWorkbook


        Call Macro2(WBtemp1, WBtemp2, WBtemp3, RF1, RF2, RF3)