Excel VBA efficient get file names function

后端 未结 3 642
太阳男子
太阳男子 2021-01-12 05:46

I need to get a collection of file names from a folder on a remote server using VBA in excel 2010. I have a function that works and in the majority of cases it would do the

3条回答
  •  被撕碎了的回忆
    2021-01-12 06:07

    Ok, I have found a solution that works for my situation and perhaps others will find it useful too. This soution uses the windows API and gets me the filenames in 1 second or less where as the FSO method was taking several minutes. It still involves a loop so i'm not certain why it is so much faster but it is.

    This takes a path like "c:\windows\" and returns a collection of all the files (and directories) in that folder. The exact parameters I have used require windows 7 or newer, see the comments in the declarations.

    'for windows API call to FindFirstFileEx
    Private Const INVALID_HANDLE_VALUE = -1
    Private Const MAX_PATH = 260
    
    Private Type FILETIME
        dwLowDateTime   As Long
        dwHighDateTime  As Long
    End Type
    
    Private Type WIN32_FIND_DATA
        dwFileAttributes    As Long
        ftCreationTime      As FILETIME
        ftLastAccessTime    As FILETIME
        ftLastWriteTime     As FILETIME
        nFileSizeHigh       As Long
        nFileSizeLow        As Long
        dwReserved0         As Long
        dwReserved1         As Long
        cFileName           As String * MAX_PATH
        cAlternate          As String * 14
    End Type
    
    Private Const FIND_FIRST_EX_CASE_SENSITIVE  As Long = 1
    'MSDN: "This value is not supported until Windows Server 2008 R2 and Windows 7."
    Private Const FIND_FIRST_EX_LARGE_FETCH     As Long = 2
    
    Private Enum FINDEX_SEARCH_OPS
        FindExSearchNameMatch
        FindExSearchLimitToDirectories
        FindExSearchLimitToDevices
    End Enum
    
    Private Enum FINDEX_INFO_LEVELS
        FindExInfoStandard
        FindExInfoBasic 'MSDN: "This value is not supported until Windows Server 2008 R2 and Windows 7."
        FindExInfoMaxInfoLevel
    End Enum
    
    Private Declare Function FindFirstFileEx Lib "kernel32" Alias "FindFirstFileExA" ( _
    ByVal lpFileName As String, ByVal fInfoLevelId As Long, lpFindFileData As WIN32_FIND_DATA, _
        ByVal fSearchOp As Long, ByVal lpSearchFilter As Long, ByVal dwAdditionalFlags As Long) As Long
    Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" ( _
        ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
    Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
    
    
    Private Function GetFiles(ByVal sPath As String) As Collection
    
        Dim fileInfo    As WIN32_FIND_DATA  'buffer for file info
        Dim hFile       As Long             'file handle
        Dim colFiles    As New Collection
    
        sPath = sPath & "*.*"
    
        hFile = FindFirstFileEx(sPath & vbNullChar, FindExInfoBasic, fileInfo, FindExSearchNameMatch, 0&, FIND_FIRST_EX_LARGE_FETCH)
    
        If hFile <> INVALID_HANDLE_VALUE Then
            Do While FindNextFile(hFile, fileInfo)
                colFiles.Add Left(fileInfo.cFileName, InStr(fileInfo.cFileName, vbNullChar) - 1)
            Loop
    
            FindClose hFile
        End If
    
        Set GetFiles = colFiles
    
    End Function
    

提交回复
热议问题