【问题标题】:VBA For Excel (CSV), Looping through files to get row, then appending rows into one ListVBA For Excel (CSV),循环文件以获取行,然后将行附加到一个列表中
【发布时间】:2019-01-29 05:17:20
【问题描述】:

我在为一堆 CSV 文件 (10000) 编写此 VBA 宏时遇到问题。搜索后,我发现/将其用于我的代码: Loop through files in a folder using VBA? 。它似乎不起作用,我不知道为什么......我已经尝试过 While 循环,但它非常慢我不知道它是否可以完成运行。

Sub LoopThroughFiles()
Dim MyObj As Object, MySource As Object, file As Variant
file = Dir("C:\Users\me\Desktop\test")
While (file <> "")
  If InStr(file, "test") > 0 Then
        '// my macro code is here
     Exit Sub
  End If
 file = Dir
Wend
End Sub

我还应该尝试改变什么?我哪里做错了?我也尝试过使用此代码https://www.thespreadsheetguru.com/the-code-vault/2014/4/23/loop-through-all-excel-files-in-a-given-folder,但我不确定除了目录和'更改第一个工作表的背景填充蓝色之外还有什么要更改的。

还尝试了这个http://www.ozgrid.com/VBA/loop-through.htm,这看起来很简单,但我无法让它工作......

来自 L8N 的更新

Option Explicit

Sub looper()
Dim fso As Scripting.FileSystemObject
Dim aFolder As Scripting.Folder
Dim aFile As Scripting.file
Dim aText As Scripting.TextStreame
Dim singleLine As String

Set fso = New FileSystemObject
Set aFolder = fso.GetFolder("C:\Users\ME\Desktop\test") 'set path to the folder that contains the files

For Each aFile In aFolder.Files 'loops through every file in the top level of the folder
    If InStr(1, vbBinaryCompare) > 0 Then
        Range("A2:D200210").Clear   'what i want to happen to every file
        Set aText = fso.OpenTextFile(aFile.Path, ForReading)
        Do Until aText.AtEndOfStream
            singleLine = aText.ReadLine 'read line into string, every call advances the line counter by one, this prevents skipping lines
            If InStr(1, singleLine, vbBinaryCompare) > 0 Then Debug.Print singleLine ' in line case, prints line if target value is found
        Loop
    End If
Next aFile
Debug.Print "finished"

结束子

它运行,但似乎没有对每个文件实现我想要的更改 (Range("A2:D200210").Clear )。我的代码的字符串名称也无关紧要,工作表中的信息也不重要。我的原始代码是为了测试它是否循环。

【问题讨论】:

    标签: vba excel csv excel-2010


    【解决方案1】:

    我不确切知道您要做什么,您拥有的代码执行以下操作:

    file = Dir("C:\Users\me\Desktop\test") 如果文件“test”存在,则将文件名写入file,如果您使用Dir("C:\Users\me\Desktop\test\"),该函数将返回它找到的第一个文件的名称。
    在随后的运行中,它将返回文件夹中的下一个文件,请记住这是一个全局调用,因此如果您在其他地方调用该函数,它可能会干扰。在大多数情况下,除了快速检查文件是否存在之外,最好使用 Microsoft 脚本引擎运行时。

    If InStr(file, "test") &gt; 0 Then您测试“test”是否是文件名的一部分,到目前为止一切顺利,但请记住告诉 InStr 它应该如何比较两个字符串。 InStr 接受四个参数(都是可选的),一定要传递正确的参数。 microsoft documentation 其实还不错。

    这是你想要的吗?我想你可能正在.csv 文件中寻找一些东西,如果是这样,我可以扩展下面的脚本。

    下面附上了一个循环遍历文件夹中所有文件的简单方法:

    Option Explicit
    
    Sub looper()
        Dim fso As Scripting.FileSystemObject
        Dim aFolder As Scripting.Folder
        Dim aFile As Scripting.file
        Dim aText As Scripting.TextStream
        Dim targetName As String 'string that identifies files
        Dim targetWord As String 'string that identifies line inside csv file
        Dim singleLine As String 
    
        Set fso = New FileSystemObject
        Set aFolder = fso.GetFolder("C:\Users\Me\Desktop\test") 'set folder that contains the files
        targetName = "someFileName"
        targetWord = "someString"
    
        For Each aFile In aFolder.Files 'loops through every file in the top level of the folder
            If InStr(1, aFile.Name, targetName, vbBinaryCompare) > 0 Then
                Debug.Print "Found a matching File: "; aFile.Name
                Set aText = fso.OpenTextFile(aFile.Path, ForReading)
                Do Until aText.AtEndOfStream 
                    singleLine = aText.ReadLine 'read line into string, every call advances the line counter by one, this prevents skipping lines
                    If InStr(1, singleLine, targetWord, vbBinaryCompare) > 0 Then Debug.Print singleLine ' in line case, prints line if targer value is found
                Loop
            End If
        Next aFile
        Debug.Print "finished"
    End Sub
    

    奖金信息: 使用选项显式确保正确声明所有变量


    编辑:

    目前还无法将 cmets 添加到您的帖子中,所以我将在此处回复。

    If InStr(1, vbBinaryCompare) &gt; 0 Then 这条线现在被破坏了,因为它总是返回 0。如果你想循环遍历每个文件,只需省略 IF-Contitional 或将其设置为 If True Then

    Range("A2:D200210").Clear 是所谓的隐式引用,范围对象指的是“全局”工作表。每次执行这段代码时,都会在“全局”工作表a nice answer by Mathieu Guindon from just recently explains this上发生更改。

    它运行,但似乎没有对每个文件实现我想要的更改 (Range("A2:D200210").Clear )。我的代码的字符串名称也无关紧要,工作表中的信息也不重要。我的原始代码是为了测试它是否循环。

    因此,据我所知,您尝试删除 .csv 文件中除第一行之外的所有内容。 .csv 文件不是工作表(即使您可以将其导入 excel),因此您不能使用 Range 属性。
    幸运的是,有一种更简单的方法可以做到这一点,只需使用 Microsoft Scripting Runtime 来编辑 .csv 文件。

    Set aText = aFile.OpenAsTextStream(ForReading) ' open file in read mode
    singleLine = aText.ReadLine ' read the first line and store it
    Set aText = aFile.OpenAsTextStream(ForWriting) ' open file in write mode
    aText.Write (singleLine) 'write the line you saved before
    

    或者更紧凑:

    aFile.OpenAsTextStream(ForWriting).Write aFile.OpenAsTextStream(ForReading).ReadLine 'overwrites the file with what was written in the first line.
    

    较长代码的优点是能够在其他地方使用字符串,例如将其存储在工作簿中的某个地方。

    【讨论】:

    • 嘿 L8n,我已经用你的编辑更新了我的问题。太感谢了!维伦丹克!我不是在文件中寻找东西。只想对文件夹中的所有文件执行相同的宏,无论名称或内容。
    • @lex Bittesehr,用所需的代码更新了我的答案,您可以在for each 子句中使用上面的代码
    猜你喜欢
    • 2021-01-16
    • 2017-02-25
    • 2019-05-15
    • 2018-12-06
    • 2021-09-21
    • 2018-04-06
    • 2023-04-05
    • 2018-12-11
    • 2022-12-10
    相关资源
    最近更新 更多