简体   繁体   中英

Using excel VBA open file based on cell value with path composed on the fly from same value

This is the goal. User open's read only workbook from network drive. Selects a cell with the file name and clicks on macro button which will find and open how every many files there are that match the cell value.

What's the most efficient method of achieving that result? Keeping in mind that:

  • User's don't want to wait for excel to compile a directory structure with files every time they open the workbook.
  • file names will always match some portion of the containing folder name
    • file 135A1200 would be in folder 135A12XX
  • dozens of folders/subfolders with varying levels of subfolders
  • thousands of files with constant changes
  • folder hierarchy is semi-permanent
  • consistent file/folder naming format in that:
    • will always start with three numbers
    • followed by one to three letters
    • then four to seven numbers eg, 135A1200 or 246FP317101
  • didn't want to use collections, etc. because of so many unknowns

I was thinking of having a loop of sorts that will take the value, build a path from that value while also verifying that the path exists before moving on, and then when the final sub-folder is reached, locate however many files that match the value and do whatever. I'm having trouble with looping and adding the X's in the sub-folders because they don't match the selected value and it's not always known where the X's will be in a different sub-folder set.

135A1200-101 would equal \\path\\135\\135A\\135A1XXX\\135A12XX\\135A1200_S_01.file

Or

246FP317101-31 would equal \\path\\246\\246F\\246FP\\246FP317101.file

  • \\\\path\\135\\
    • 135A\\
      • 135A0XXX\\
      • 135A1XXX\\
      • 135A10XX\\
      • 135A11XX\\
      • 135A12XX\\
        • 135A1200_S_01.file
        • 135A1200_S_02.file
        • 135A1200_S_03.file
      • 135A13XX\\
      • 135A3XXX\\
      • 135ASKXXX\\
    • 135D\\
    • 135F\\
    • 135GGG\\
    • 135LL\\
  • \\\\path\\321\\
  • \\\\path\\246\\
    • 246F\\
      • 246F13\\
      • 246F14\\
      • 246F15\\
      • 246F16\\
      • 246FF\\
      • 246FP\\
        • 246FP317101.file

This is what I have which works ok for a simpler set of files and folders.

Public Sub pickFiles()
    Dim File As Variant
    Dim subPath As String

    File = Selection(1, 1).Value

    Select Case Left(File, 1)
    Case "Q"
        If Left(File, 6) = "Q11-12" Then
            subPath = "folder\QXX\Q11\" & Left(File, 6)
        ElseIf Left(File, 6) = "Q11-14" Then
            subPath = "folder\QXX\Q11\" & Left(File, 6)
        ElseIf Left(File, 6) = "Q11-22" Then
             subPath = "folder\QXX\Q11\" & Left(File, 6)
        Else
            subPath = "folder\QXX\" & Left(File, 3)
        End If
            openCompFile File, subPath
    Case "P"
        subPath = "folder\PXX\" & Left(File, 3)
        openCompFile File, subPath
    Case Else
        msgbox "That's not a valid file number", vbInformation
    End Select
End Sub

Private Sub openCompFile(ByRef File As Variant, ByRef subPath As String)
    Dim mainPath As String
    Dim fso As New FileSystemObject
    Dim Folder As Folder
    'Dim File As Variant
    Dim FileCollection As New Collection

    mainPath = "X:\folder\" & subPath

    Set Folder = fso.GetFolder(mainPath)

    For Each File In Folder.Files
        If Left(File.Name, 9) = Left(File, 9) Then FileCollection.Add File
    Next File

    If FileCollection.Count = 0 Then
        msgbox Left(File, 9) & " was not found.", vbInformation
    Else
        For Each File In FileCollection
            ShellExecute 0, "Open", File.Path, vbNullString, vbNullString, 1
        Next
    End If
End Sub

I'm not sure how fast this will be since it appears you are using a networked drive, but my thought would be to use Command's built in DIR function to find all the files. (Don't confuse this with VBA's built in DIR command. VBA DIR will not search subfolders. CMD's DIR will.)

I'm not 100% certain I know exactly what all your file names look like, but it appears that based on the sample data, that the portion of the filename to the left of the hyphen is always part of the filename for each file to be opened. for example: 135A1200-101 should always open the 3 files: 135A1200_S_01.file , 135A1200_S_02.file , and 135A1200_S_03.file whereas 246FP317101-3 will open 246FP317101.file . Assuming I understand the file naming conventions, is it true that 359AS12005-33 would open these files 359AS12005_S_05 and 359AS12005.file ?

If so, try out this code:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Function RunCMD(ByVal strCMD As String) As String
    'Runs the provided command
    Dim oShell As Object 'New wshShell
    Dim cmd As Object 'WshExec
    Dim x As Integer
    Const WshRunning = 0

    On Error GoTo wshError

    x = 0
    RunCMD = "Error"
    Set oShell = CreateObject("Wscript.Shell")
    Set cmd = oShell.Exec(strCMD)
    'Debug.Print strCMD
    'Stop
    Do While cmd.Status = WshRunning
        Sleep 100 'for 1/10th of a second
        x = x + 1
        If x > 1200 Then 'We've waited 2 minutes so kill it
            cmd.Terminate
            RunCMD = "Error: Timed Out"

        End If
    Loop

    RunCMD = cmd.StdOut.ReadAll & cmd.StdErr.ReadAll
    Set oShell = Nothing
    Set cmd = Nothing
    Exit Function

wshError:
    RunCMD = cmd.StdErr.ReadAll
    Resume Next
End Function

Sub FindFiles()
    Dim strSearchResults As String
    Dim strBaseFileName As String
    Dim strFileName As Variant
    Dim arrFileNames As Variant

    strBaseFileName = Left(Selection(1, 1).Value, InStr(1, Selection(1, 1).Value, "-", vbTextCompare))
    strSearchResults = RunCMD("cmd /c ""Dir X:\folder\" & strBaseFileName & "* /a:-d /b /d /s""")
    Debug.Print strSearchResults
    'Split the results into an array the can be looped through
    arrFileNames = Split(strSearchResults, vbCrLf, -1, vbTextCompare)
    Debug.Print UBound(arrFileNames)
    For Each strFileName In arrFileNames
        Debug.Print strFileName
    Next
End Sub

Caveats: The FindFiles sub gets all the text up to the first hyphen and uses that to search EVERY subdirectory for ANY file starting with that string of text. If that's not what you're looking for, then hopefully this can point you towards a relatively efficient method of using the Windows DIR command (as opposed to VBA's DIR command which does NOT work in this case!) to find a solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM