vba, 统计一个文件夹下(含子文件夹)的所有一类文件的,某列的值统计

1 问题

1.1 问题详细分析

  • 问题来源于群里的一个玩家提问
  • 需要统计一个文件夹下的多个同类文件
  • 提问者要求的是csv,我例子里用的xlsm
  • 统计这些表某一列的值,然后显示出统计页

1.2 初期想到的难点

  • 文件夹下统计某一种文件不难,但是需要迭代子文件夹,可能需要用到递归
  • 用VBA使用文件的内容前,必须先打开文件

 

2 第一版正确代码,基础可以跑而已,未优化

2.1 代码需求点

  • 我发给那个提问者的修改点
  • 你自己改下参数
  • 1 改下你要操作的文件夹的目录 path1 = "C:\Users\Administrator\Desktop\test1"
  • 2 改下你要查的文件类型,   If f1.Name Like "*.xlsm" Then    我查的是.xlsm你估计是.csv
  • 3 改下你要统计的列 ThisWorkbook.Worksheets("sheet1").Cells(m + 1, 3).Value = Application.Average(Range("a:a").Value)  我统计的是A列

2.2 代码局限性

  • EXCEL表的后台打开我处理的不好,尝试了好久,还遇到了  active部件不能创建对象 等问题
  • 现在打开的效率有点慢,我故意加了一个延迟,避免卡死
  • 因为我这种后台打开表的方式,代码运行完后,那些表还是会一起打开,如果表数量多可能是内存卡死把。。。
  • 其他问题

2.3 代码的思路

  • 为什么再加一层调用sub?
  • 因为主体sub 是需要用到调用自身的,但是因为再次调用自身递归的时候,需要引用的不同的文件夹路径,不能重复调用老路径。所以干脆就让主体SUB也是带参数,被调用的。
  • 为什么要用模块级变量
  • 也是因为递归,自身调用自身,会导致主过程会被重复调用,但是如果是过程级变量就会每次重置变量值,这个显然是不合符需求的,而是每次递归调用自身后,值都继续累计。
  • 设计思路
  • 这段代码分层:文件层  \ wb层  \sh层  \内容层
Dim m

Sub test1()
path1 = "C:\Users\Administrator\Desktop\test1"
Call test2(path1)
End Sub
 
 
Sub test2(path1)

Dim fso1 As Object
Set fso1 = CreateObject("scripting.filesystemobject")
 
Application.ScreenUpdating = False
Dim f1 As Object
Dim sh1 As Object
 

For Each f1 In fso1.GetFolder(path1).Files
    If f1.Name Like "*.xlsm" Then
'          Debug.Print f1.Name
          Workbooks.Open (f1.Path)
          Workbooks(f1.Name).Worksheets("sheet1").Cells(1, 9) = 888
          Application.Wait (Now + TimeValue("00:00:01"))
          For Each sh1 In Workbooks(f1.Name).Worksheets
              ThisWorkbook.Worksheets("sheet1").Cells(m + 1, 1).Value = f1.Name
              ThisWorkbook.Worksheets("sheet1").Cells(m + 1, 2).Value = sh1.Name
              ThisWorkbook.Worksheets("sheet1").Cells(m + 1, 3).Value = Application.Average(Range("a:a").Value)
              m = m + 1
          Next
    End If
Next
 
Dim subfd1
For Each subfd1 In fso1.GetFolder(path1).SubFolders
    Call test2(subfd1.Path)
Next
 
 
Application.ScreenUpdating = True
End Sub

 

 

3 解决历程和学习点

3.1 sub  递归调用自己的问题

  • 递归是循环,但是一种比较特殊的循环,至少理论上是收敛的
  • 和正常的 for 上下限范围循环 或 do loop等条件一样,递归调用自己这种循环,理论上是有尽头的
  • 比如我写的这个 subfolder,总是有限数量的。
  • 递归肯定不能是无限死循环
  • 无限的循环,只能是错误的循环。

 

3.2 包含参数的sub() 不能直接运行,只能被其他sub () 或 function() 调用

  • 后来,我直接把 sub 本身带了参数(必须参数),然后递归调用自己的时候也带上path参数(子文件夹参数)
  • 然后架了一个更高层的sub,调用我这个处理数据的sub

 

3.3  参数的类型,怎么做可选参数? ---现在只会加必选参数

  • 记得参数里,有必选参数,可选参数?
  • 但是怎么设置必选参数,可选参数?还不会弄,得试试
  • 后来,我直接把 sub 本身带了参数(必须参数),然后递归调用自己的时候也带上path参数(子文件夹参数)
  • 然后架了一个更高层的sub,调用我这个处理数据的sub

 

3.4 参数的生效范围和选择使用

  • 因为我写的这段代码涉及到了,调用自身(递归)
  • 所以如果只使用 sub过程级变量,下次调用自身又会重置m变量
  • 如果使用 static m ,可以实现多次反复调用也继续计数。但坏处是,除非完全关闭全部EXCEL的application,否则即使关闭当前代码的thisworkbook,变量还是不清除。
  • 最后采用了 模块级变量 dim  m 放到了模块最前面,这样模块内调用可以传递m

 

3.5 VBA的文件处理系统-----太多,没搞明白其中的差别

如下这些到底什么情况下用什么,感觉每种都有其适用条件

  • createobject(file.path)
  • fso 和 fso.opentextfile()
  • fso 和  fso.getfile()
  • fso 和 fso.getfolder()

 

  • 尝试过各种后台打开表格的方法----差别很大
  • Set wb1 = fso1.getfile(f1.Name)
  • Set wb1 = fso1.opentextfile(f1.path, 2)
  •  Set wb1 = CreateObject(f1.path)
  • Set wb1 = Workbooks.Open(f1.path)

 

  • Set objFSO = CreateObject("Scripting.FileSystemObject")
  • Set objFile = objFSO.CreateTextFile("c:\windows\xxwl.ini")  
  • Set wb1 = CreateObject(f1.path)

 

3.6 文件的类别识别

  • 如果文件有多种类型,这下面的写法有时候有差别,原因未知
  • wb1.worksheets
  • workbooks(wb1.name).worksheets

 

3.7 处理EXCEL文件,必须先打开对应的文件---否则会报错

  • 如果对应的EXCEL文件没有先在后台打开,经常报错:下标越界,其实是表没打开

 

3.8 EXCEL表这类文件的后台打开

  • 为什么要后台打开?
  • 因为如果前台打开表格,会打断当前表的代码运行。
  • 方法1: application.screenupdating=false/true  + workbooks.open()
  • 方法2: createobject(file.path)  这次不好用,以前是可以的,不知道为啥
  • 方法3: 还有些,开启一个新的 application(EXCEL)
  • 等等

 

3.9  vba activeX部件不能创建对象?

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用VBA打印文件夹下的所有文件,可以通过FileSystemObject对象和Folder对象来实现。具体步骤如下: 1. 首先,需要引用Microsoft Scripting Runtime库,以便使用FileSystemObject对象。在VBA编辑器中,点击"工具" -> "引用",勾选"Microsoft Scripting Runtime"。 2. 声明并创建FileSystemObject对象和Folder对象,用于操作文件夹文件。 3. 使用GetFolder方法指定文件夹路径,创建Folder对象。 4. 使用Folder对象的Files属性获取文件夹下的所有文件集合。 5. 使用For Each循环遍历文件集合中的每个文件。 6. 对于每个文件,可以使用PrintOut方法来实现打印。可以根据需要设置打印属性,如打印份数、打印机名称等。 一个简单的示例代码如下: ``` Sub PrintFilesInFolder() Dim fso As FileSystemObject Dim folderPath As String Dim folder As Folder Dim file As File '指定文件夹路径 folderPath = "C:\TestFolder" '创建文件系统对象和文件夹对象 Set fso = New FileSystemObject Set folder = fso.GetFolder(folderPath) '遍历文件夹中的每个文件 For Each file In folder.Files '打印文件 file.PrintOut Next file '释放对象 Set file = Nothing Set folder = Nothing Set fso = Nothing MsgBox "打印完成!" End Sub ``` 以上代码将打印指定文件夹中的所有文件。你可以根据实际需求修改文件夹路径和其他打印属性。 ### 回答2: 在VBA中,我们可以使用FileSystemObject对象来实现打印文件夹下所有文件的功能。 首先,我们需要引入"Microsoft Scripting Runtime"库。在VBA编辑器中,点击工具 -> 引用,然后勾选"Microsoft Scripting Runtime",点击确定。 下面是一个示例代码,演示如何打印文件夹下所有文件文件名: ```vba Sub 打印文件夹下所有文件() Dim FSO As New FileSystemObject Dim 文件夹路径 As String Dim 文件夹 As Folder Dim 文件 As File ' 设置文件夹路径 文件夹路径 = "C:\文件夹的路径" ' 获取文件夹对象 Set 文件夹 = FSO.GetFolder(文件夹路径) ' 遍历文件夹下所有文件 For Each 文件 In 文件夹.Files Debug.Print 文件.Name Next 文件 ' 释放对象 Set 文件夹 = Nothing Set FSO = Nothing End Sub ``` 请将"文件夹的路径"替换为你想要打印文件文件夹路径。运行该VBA代码后,文件夹下所有文件文件名将以文本形式输出到"立即窗口"。你可以通过按下"Ctrl + G"快捷键打开"立即窗口"。 注意:在使用FileSystemObject对象之前,确保你已经引入了正确的库。如果你还没有引入"Microsoft Scripting Runtime"库,请按照前面的步骤进行引入。 ### 回答3: 在VBA中,我们可以使用FileSystemObject对象来打印文件夹下所有的文件。下面是一个简单的代码示例: ```vba Sub PrintFilesInFolder() Dim fso As Object Dim folderPath As String Dim folder As Object Dim file As Object ' 设置文件夹路径 folderPath = "C:\YourFolderPath" ' 创建FileSystemObject对象 Set fso = CreateObject("Scripting.FileSystemObject") ' 获取文件夹对象 Set folder = fso.GetFolder(folderPath) ' 遍历文件夹下的所有文件 For Each file In folder.Files ' 打印文件名 Debug.Print file.Name Next file ' 清除对象变量 Set file = Nothing Set folder = Nothing Set fso = Nothing End Sub ``` 上述代码中,我们首先声明了所需的变量,包括`fso`(FileSystemObject对象),`folderPath`(文件夹路径),`folder`(文件夹对象),`file`(文件对象)。然后我们使用`CreateObject`函数创建了一个`fso`对象,并使用`GetFolder`方法获取了指定路径下的文件夹对象。接着我们使用`For Each`循环来遍历文件夹下的所有文件,通过`Debug.Print`语句打印文件名。最后,我们清除了所有对象变量。请注意替换`folderPath`为实际的文件夹路径。 使用上述代码,您可以打印出指定文件夹下的所有文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值