• VBA文件对话框的应用(VBA打开文件、VBA选择文件、VBA选择文件夹,VBA遍历文件夹)


    在Scripting类库中有三个可以直接使用NEW关键字实例化的类,第一个就是常用的字典,第三个是FSO。

    Dictionary

    Encoder

    FileSystemObject

    一、FSO对象引用的方法:

     前期绑定:先要引用类库文件scrrun.dll,写代码的时候有智能提示。如果程序发给别人用,就要用后期绑定方式。

     Dim fso As New Scripting.FileSystemObject 

     后期绑定:不需要引用类库文件,但没有智能提示。

     Set fso = CreateObject("Scripting.FileSystemObject")

    递归,提取文件名,office2019测试通过;

    Sub ListFilesTest()
    With Application.FileDialog(msoFileDialogFolderPicker)
    If .Show Then myPath$ = .SelectedItems(1) Else Exit Sub
    End With
    If Right(myPath, 1) <> "" Then myPath = myPath & ""
    [a:b] = ""
    Call ListAllFso(myPath, 1)
    MsgBox "OK"
    End Sub
    Function ListAllFso(myPath$, i)
    Set Fld = CreateObject("Scripting.FileSystemObject").GetFolder(myPath)
    For Each f In Fld.Files
        If f.Name Like "*.xls*" Then
            Cells(i, 2) = f.Name
            Cells(i, 1) = f.ParentFolder.path
            i = i + 1
        End If
    Next
    For Each fd In Fld.SubFolders
        Cells(i, 1) = fd.path
        i = i + 1
        Call ListAllFso(fd.path, i)
    Next
    
    End Function

     上面,根据使用略微调整

    Sub ListFilesTest()
    'With Application.FileDialog(msoFileDialogFolderPicker)
    'If .Show Then myPath$ = .SelectedItems(1) Else Exit Sub
    'End With
    Dim ws As Worksheet
    Set ws = Worksheets("File")
    With ws
        rowmax = WorksheetFunction.Max(.Cells(65536, 1).End(xlUp).Row, .Cells(65536, 2).End(xlUp).Row)
        If rowmax > 4 Then .Range(.Cells(5, 1), .Cells(rowmax, 5)).ClearContents
    End With
     myPath$ = Worksheets("Main").Cells(28, 4).Value
    If Right(myPath, 1) <> "" Then myPath = myPath & ""
    Call ListAllFso(myPath, 5, ws)
    MsgBox "OK"
    End Sub
    Function ListAllFso(myPath$, i, ws As Worksheet)
    Set Fld = CreateObject("Scripting.FileSystemObject").GetFolder(myPath)
    Set Fso = CreateObject("Scripting.FileSystemObject")
    For Each f In Fld.Files
        If f.Name Like "*.xls*" Then
            ws.Cells(i, 1) = f.ParentFolder.path
            ws.Cells(i, 2) = Fso.GetBaseName(f.Name)
            ws.Cells(i, 3) = f.DateLastModified
            ws.Cells(i, 5) = Fso.GetExtensionName(f.Name)
            ws.Cells(i, 4) = f.Size
            i = i + 1
        End If
    Next
    For Each fd In Fld.SubFolders
    '    ws.Cells(i, 1) = fd.path
    '    i = i + 1
        Call ListAllFso(fd.path, i, ws)
    Next
    
    End Function

     文件改名,然后再重新载入;

    Sub RenameFile()
    Dim ws As Worksheet
    Set ws = Worksheets("File")
    Set Fso = CreateObject("Scripting.FileSystemObject")
    With ws
        rowmax = WorksheetFunction.Max(.Cells(65536, 1).End(xlUp).Row, .Cells(65536, 2).End(xlUp).Row)
        If rowmax > 4 Then
            For i = 5 To rowmax
                If .Cells(i, 6) <> "" Then
                    oldname = .Cells(i, 1) & "" & .Cells(i, 2) & "." & .Cells(i, 5)
                    newname = .Cells(i, 1) & "" & .Cells(i, 6) & "." & .Cells(i, 5)
                    If Fso.fileexists(newname) Then
                        MsgBox i & "行,以新文件名命名的文件已存在; " & newname
                    Else
                        On Error Resume Next
                        Name oldname As newname
                    End If
    ErrorProcess:
                    If Err.Number = 58 Then
                        newname = .Cells(i, 1) & "" & .Cells(i, 6) & "_" & i & "." & .Cells(i, 5)
                        Name oldname As newname
                        Err.Clear
    '                    MsgBox Err.Number
                    End If
                Else
                    MsgBox i & "行,无新文件名,未改名;"
                End If
            Next
        End If
        ws.Select
        ws.Cells(5, 2).Activate
    End With
    Call ListFiles
    End Sub 

    Sub 提取文件夹名称()

    Dim fs As Object
    n = 1
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.getfolder("D:PersonalDownloads")
    For Each fd In f.subfolders
    Cells(n, 1) = fd.Name
    n = n + 1
    Next
    Set f = Nothing
    Set fs = Nothing
    End Sub

    如果想通过VBA代码由自己选择文件夹再执行提取文件夹名称,:

    Sub getFldList1()
    Dim Fso, Fld
    Dim Arr(1 To 999), k%
    Set Fso = CreateObject("Scripting.FileSystemObject")
    Set Fld = Fso.getfolder(CreateObject("Shell.Application").BrowseForFolder(0, "请选择文件夹", 0, "").Self.Path & "")
    For Each fd In Fld.subfolders
    k = k + 1
    Arr(k) = fd.Name
    Next
    [A1].Resize(k) = Application.Transpose(Arr)
    End Sub
    Sub 遍历文件夹()
    'On Error Resume Next
    Dim fn(1 To 10000) As String
    Dim f, i, k, f2, f3, x
    Dim arr1(1 To 100000, 1 To 1) As String, q As Integer
    Dim t
    t = Timer
    fn(1) = ThisWorkbook.Path & ""
    i = 1: k = 1
    Do While i < UBound(fn)
    If fn(i) = "" Then Exit Do
    f = Dir(fn(i), vbDirectory)
    Do
    If InStr(f, ".") = 0 And f <> "" Then
    k = k + 1
    fn(k) = fn(i) & f & ""
    End If
    f = Dir
    Loop Until f = ""
    i = i + 1
    Loop
    '*******接下来是提取各个文件夹的文件***
    For x = 1 To UBound(fn)
    If fn(x) = "" Then Exit For
    f3 = Dir(fn(x) & "*.*")
    Do While f3 <> ""
    q = q + 1
    arr1(q, 1) = fn(x) & f3
    f3 = Dir
    Loop
    Next x
    ActiveSheet.UsedRange = ""
    Range("a1").Resize(q) = arr1
    MsgBox Format(Timer - t, "0.00000")
    End Sub

    在VBA中经常要用到文件对话框来进行打开文件、选择文件或选择文件夹的操作。
    用Microsoft Office提供的文件对话框比较方便。
    用法如下
    Application.FileDialog(fileDialogType)
    fileDialogType      MsoFileDialogType 类型,必需。文件对话框的类型。

        MsoFileDialogType 可为以下 MsoFileDialogType 常量之一。
        msoFileDialogFilePicker  允许用户选择文件。
        msoFileDialogFolderPicker  允许用户选择一个文件夹。
        msoFileDialogOpen  允许用户打开文件。用Excel打开。
        msoFileDialogSaveAs  允许用户保存一个文件。
    分别举例如下:

    1、msoFileDialogFilePicker
    1)选择单个文件

    Sub SelectFile()
        '选择单一文件
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = False   '单选择

          .InitialFileName = "ok"
          .Title = "Please select folder"

            .Filters.Clear   '清除文件过滤器
            .Filters.Add "Excel Files", "*.xls;*.xlw"
            .Filters.Add "All Files", "*.*"          '设置两个文件过滤器
            If .Show = -1 Then    'FileDialog 对象的 Show 方法显示对话框,并且返回 -1(如果您按 OK)和 0(如果您按 Cancel)。
                MsgBox "您选择的文件是:" & .SelectedItems(1), vbOKOnly + vbInformation, "智能Excel"
            End If
        End With
    End sub

    2)选择多个文件

    Sub SelectFile()
        '选择多个文件
        Dim l As Long
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = True   '单选择
            .Filters.Clear     '清除文件过滤器
            .Filters.Add "Excel Files", "*.xls;*.xlw"
            .Filters.Add "All Files", "*.*"    '设置两个文件过滤器
            .Show
            'FileDialog 对象的 Show 方法显示对话框,并且返回 -1(如果您按 OK)和 0(如果您按 Cancel)。
            For l = 1 To .SelectedItems.Count
                MsgBox "您选择的文件是:" & .SelectedItems(l), vbOKOnly + vbInformation, "智能Excel"
            Next
        End With
    End Sub

    2、msoFileDialogFolderPicker

    Sub SelectFolder()
        '选择单一文件
        With Application.FileDialog(msoFileDialogFolderPicker)
            If .Show = -1 Then
            'FileDialog 对象的 Show 方法显示对话框,并且返回 -1(如果您按 OK)和 0(如果您按 Cancel)。
                MsgBox "您选择的文件夹是:" & .SelectedItems(1), vbOKOnly + vbInformation, "智能Excel"
            End If
        End With
    End Sub

    3、msoFileDialogOpen
    4、msoFileDialogSaveAs

    使用方法与前两种相同
    只是在.show可以用.Execute方法来实际打开或者保存文件

    例如:

    Sub SelectFile()
        '选择单一文件
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = False   '单选择
            .Filters.Clear   '清除文件过滤器
            .Filters.Add "Excel Files", "*.xls;*.xlw"
            .Filters.Add "All Files", "*.*"          '设置两个文件过滤器
           .Execute
        End With
    End Sub

    5. GetOpenFilename

    表达式.GetOpenFilename(FileFilterFilterIndexTitleButtonTextMultiSelect)

    参数

    名称 必选/可选 数据类型 描述
    FileFilter 可选 Variant 一个指定文件筛选条件的字符串。
    FilterIndex 可选 Variant 指定默认文件筛选条件的索引号,取值范围为 1 到由 FileFilter 所指定的筛选条件数目。如果省略该参数,或者该参数的值大于可用筛选条件数,则使用第一个文件筛选条件。
    Title 可选 Variant 指定对话框的标题。如果省略该参数,则标题为“打开”。
    ButtonText 可选 Variant 仅限 Macintosh。
    MultiSelect 可选 Variant 如果为 True,则允许选择多个文件名。如果为 False,则只允许选择一个文件名。默认值为 False。

    Sub Test() '取得文件路径及名字
       PickFile2 = Application.GetOpenFilename("xls(*.xls;*.xlsx),*.xls;*.xlsx")
    End Sub

     选择多个文件

    Sub XXX()
        Dim arr()
        arr = Application.GetOpenFilename("所有支持文件 (*.xls;*.xlsx;*.csv),*.xls;*.xlsx;*.csv,Excel 文件 (*.xls),*.xls,Excel2007 文件 (*.xlsx),*.xlsx,CSV 文件 (*.csv),*.csv", , "选择文件", , True)
        For i = LBound(arr) To UBound(arr)
            Cells(i, 1).Value = arr(i)
        Next
    End Sub
    提取指定文件夹内的所有文件名() '含所有子文件夹内的文件
    Sub 提取指定文件夹内的所有文件名() '含所有子文件夹内的文件
        Dim Fso As Object, arrf$(), mf&
        Set Fso = CreateObject("Scripting.FileSystemObject")
        Call GetFiles(CreateObject("Shell.Application").BrowseForFolder(0, "请选择文件夹", 0, "").Self.Path, Fso, arrf, mf)
        [b1].Resize(mf) = Application.Transpose(arrf)
        Set Fso = Nothing
    End Sub
    
    Private Sub GetFiles(ByVal sPath$, ByRef Fso As Object, ByRef arrf$(), ByRef mf&)
        Dim Folder As Object
        Dim SubFolder As Object
        Dim File As Object
        Set Folder = Fso.GetFolder(sPath)
        
        For Each File In Folder.Files
            mf = mf + 1
            ReDim Preserve arrf(1 To mf)
            arrf(mf) = File.Name
        Next
        For Each SubFolder In Folder.SubFolders
            Call GetFiles(SubFolder.Path, Fso, arrf, mf)
        Next
        Set Folder = Nothing
        Set File = Nothing
    End Sub

    正常情况下想要遍历文件夹和子文件夹,可以采用递归的方式

    Sub ListFilesTest()
    With Application.FileDialog(msoFileDialogFolderPicker)
    If .Show Then myPath$ = .SelectedItems(1) Else Exit Sub
    End With
    If Right(myPath, 1) <> "" Then myPath = myPath & ""
    [a:a] = ""
    Call ListAllFso(myPath)
    End Sub
    Function ListAllFso(myPath$)
    Set fld = CreateObject("Scripting.FileSystemObject").GetFolder(myPath)
    For Each f In fld.Files
    ' [a65536].End(3).Offset(1) = f.Name
    [a65536].End(3).Offset(1) = f.Path
    Next
    For Each fd In fld.SubFolders
    ' [a65536].End(3).Offset(1) = " " & fd.Name & ""
    [a65536].End(3).Offset(1) = fd.Path
    Call ListAllFso(fd.Path)
    Next
    End Function

    但用过DOS命令的都知道,DOS有个命令,一句话就可以遍历文件夹和子文件夹,下面用vba来实现DOS的dir命令,实现上面的功能

    Sub 遍历文件夹()
    Dim WSH, wExec, sCmd As String, Result As String, ar
    Set WSH = CreateObject("WScript.Shell")
    ' Set wExec = WSH.Exec("ping 127.0.0.1")
    Set wExec = WSH.exec("cmd /c dir /b /s D:lcx*.xls*")
    Result = wExec.StdOut.ReadAll
    ar = Split(Result, vbCrLf)
    For i = 0 To UBound(ar)
    Cells(i + 1, 1) = ar(i)
    Next
    Set wExec = Nothing
    Set WSH = Nothing
    End Sub

    在学习使用这个功能的时候看到一个网上的例子,写的很好,而且还让我意外的学习到一个filter的函数,这个函数的功能也是相当强大了

    Sub ListFilesDos()
    Set myfolder = CreateObject("Shell.Application").BrowseForFolder(0, "GetFolder", 0)
    If Not myfolder Is Nothing Then myPath$ = myfolder.Items.Item.Path Else MsgBox "Folder not Selected": Exit Sub
    '在这里输入需要指定的关键字,可以是文件名的一部分,或指定文件类型如 ".xlsx"
    myFile$ = InputBox("Filename", "Find File", ".xlsx")
    tms = Timer
    With CreateObject("Wscript.Shell")
    '所有文档含子文件夹 chr(34)是双引号"",因为代码中要表达"",需要写成"""" vbCrLf 回车换行
    ar = Split(.exec("cmd /c dir /a-d /b /s " & Chr(34) & myPath & Chr(34)).StdOut.ReadAll, vbCrLf)
    s = "from " & UBound(ar) & " Files by Search time: " & Format(Timer - tms, " 0.00000") & " in: " & myPath
    ' 这个filter竟然可以过滤数组,太厉害了,早知道有这个函数的话,以前写着玩的好些代码玩起来就省事多了
    tms = Timer: ar = Filter(ar, myFile)
    Application.StatusBar = Format(Timer - tms, "0.00000") & " Find " & UBound(ar) + IIf(myFile = "", 0, 1) & " Files " & s
    End With
    [a:a] = "": If UBound(ar) > -1 Then [a2].Resize(1 + UBound(ar)) = WorksheetFunction.Transpose(ar)
    End Sub

    '上例简写如下

    Sub ListFilesDos_lcx()
    Set myfolder = CreateObject("Shell.Application").BrowseForFolder(0, "GetFolder", 0)
    If Not myfolder Is Nothing Then myPath$ = myfolder.Items.Item.Path Else MsgBox "Folder not Selected": Exit Sub
    With CreateObject("Wscript.Shell")
    '所有文档含子文件夹 chr(34)是双引号"",因为代码中要表达"",需要写成"""" vbCrLf 回车换行
    ar = Split(.exec("cmd /c dir /a-d /b /s " & Chr(34) & myPath & "*.xls*" & Chr(34)).StdOut.ReadAll, vbCrLf)
    End With
    [a:a] = "": If UBound(ar) > -1 Then [a2].Resize(1 + UBound(ar)) = WorksheetFunction.Transpose(ar)
    End Sub

    shell命令也是很强大很好用了,电脑里的可执行文件,shell都可以执行,shell也是可以执行cmd的,只是无法获取到cmd控制台的数据

    Sub 打开路径()
    Shell "cmd /c ipconfig > """ & ThisWorkbook.Path & "ip.txt"""
    Shell "explorer.exe " & ThisWorkbook.Path, vbNormalFocus
    
    End Sub
  • 相关阅读:
    解决虚拟机中使用ntpdate报错:ntpdate[46700]: no server suitable for synchronization found
    Hive的三种安装方式(内嵌模式,本地模式远程模式)
    攻城狮在路上(陆)-- 提交运行MapReduce程序到hadoop集群运行
    攻城狮在路上(陆)-- 配置hadoop本地windows运行MapReduce程序环境
    攻城狮在路上(陆)-- hadoop分布式环境搭建(HA模式)
    攻城狮在路上(陆)-- hadoop单机环境搭建(一)
    Linux下Keepalived+LVS-DR模式配置高可用负载均衡集群
    Git版本控制管理学习笔记5-提交
    Git版本控制管理学习笔记4-文件管理和索引
    Git版本控制管理学习笔记3-基本的Git概念
  • 原文地址:https://www.cnblogs.com/sundanceS/p/12490853.html
Copyright © 2020-2023  润新知