Vba 合并多个CSV文件

Vba 合并多个CSV文件,vba,excel,powershell,Vba,Excel,Powershell,我有一套500个csv文件。每个文件有四列,行数可变 我想将所有这些csv合并到一个通用工作表中。如果有人能在PowerShell中帮我做这件事,那就太好了 Sample Data in Excel 1: Name Age Marks Class A 15 100 5 B 20 88 6 Sample Data in Excel 2: Name Age Marks Class C 11 99 2 Output

我有一套500个csv文件。每个文件有四列,行数可变

我想将所有这些csv合并到一个通用工作表中。如果有人能在PowerShell中帮我做这件事,那就太好了

Sample Data in Excel 1:

Name  Age  Marks  Class
A      15   100    5
B      20   88     6

Sample Data in Excel 2:
Name   Age  Marks  Class
C      11   99      2

Output :
Name   Age   Marks   Class
A      15    100      5
B      20     88      6
C      11     99      2

在您的情况下,
sort name
是可选的,这取决于合并是否也应该对内容进行重新排序(显然,您也可以对不同的参数进行
sort
)。与上述规定相同-所有.csv文件都在一个目录中

dir c:\directory\u包含\*.csv |导入csv |排序名称|导出csv-路径c:\output.csv-NoTypeInformation


如果所有CSV文件都在一个文件夹中,则:

$res = @()
ls *.csv | %{
  $temp = Import-CSV $_
  $res += $temp
}
$res | Export-CSV .\ALLINFO.csv -NoTypeInformation
细分:

  • $res=@()
    -创建一个名为$res的数组,该数组将保存所有数据。这不是严格要求的。您可以通过直接附加到结果文件的方式来完成

  • ls*.csv |
    找到文件夹中的所有csv文件,并将其传递给下一个命令

  • %{$temp=Import CSV$\$res+=$temp}
    -获取每个文件,将CSV数据导入名为
    $temp
    的holder变量。将
    $temp
    的内容添加到收集器变量
    $res
    。同样,不必使用中间
    $tamp
    变量,我只是觉得这样做更清楚

  • $res |导出CSV。\ALLINFO.CSV-NoTypeInformation
    -现在所有文件的数据都在
    $res
    中,将
    $res
    导出到新文件


这里有一个备受评论的解决方案,它使用Excel中的VBA来组合CSV。这里的策略是:

  • 提前设置引用,最重要的是
    strDir
    变量(这是一个表示保存所有CSV的目录的字符串)
  • 循环浏览目录
  • 打开每个CSV
  • 从每个CSV复制适当的内容
  • 将内容粘贴到输出工作簿
  • 重复循环,直到所有文件都被迭代
  • 希望这有帮助

    Option Explicit
    Public Sub CombineCSVsInFolder()
    
    Dim strFile As String, strDir As String
    Dim wbkSource As Workbook, wbkOutput As Workbook
    Dim wksSource As Worksheet, wksOutput As Worksheet
    Dim lngLastRowSource As Long, lngLastRowOutput As Long
    Dim rngSource As Range, rngOutput As Range
    Dim blnFirst As Boolean
    
    'Set references up-front
    strDir = "c:\stack\my_csvs\" '<~ edit this line with the CSV directory
    strFile = Dir(strDir)
    blnFirst = True
    Set wbkOutput = Workbooks.Add
    Set wksOutput = wbkOutput.ActiveSheet
    Application.ScreenUpdating = False
    
    'Loop through the CSV directory
    While (strFile <> "")
    
        'Assign source CSV files
        Set wbkSource = Workbooks.Open(strDir & strFile)
        Set wksSource = wbkSource.ActiveSheet
    
        'Assign boundaries of area to copy and output
        lngLastRowSource = LastRowNum(wksSource)
        lngLastRowOutput = LastRowNum(wksOutput)
        With wksOutput
            Set rngOutput = .Cells(lngLastRowOutput + 1, 1)
        End With
    
        'If this is the first time through, include headers, otherwise do not
        If blnFirst = False Then
            With wksSource
                Set rngSource = .Range(.Cells(2, 1), .Cells(lngLastRowSource, 4))
            End With
        'Special case for first iteration to correct source and output ranges
        Else
            With wksSource
                Set rngSource = .Range(.Cells(1, 1), .Cells(lngLastRowSource, 4))
            End With
            With wksOutput
                Set rngOutput = .Cells(1, 1)
            End With
            blnFirst = False
        End If
    
    
        'Execute copy, close source and repeat
        rngSource.Copy rngOutput
        wbkSource.Close
        strFile = Dir
    Wend
    
    'Turn screen updates back on
    Application.ScreenUpdating = True
    
    End Sub
    
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'INPUT       : Sheet, the worksheet we'll search to find the last row
    'OUTPUT      : Long, the last occupied row
    'SPECIAL CASE: if Sheet is empty, return 1
    Public Function LastRowNum(Sheet As Worksheet) As Long
        If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
            LastRowNum = Sheet.Cells.Find(What:="*", _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlPrevious).Row
        Else
            LastRowNum = 1
        End If
    End Function
    
    选项显式
    公用子组合csvsinfolder()
    Dim strFile作为字符串,strDir作为字符串
    将WBK源设置为工作簿,将WBK输出设置为工作簿
    将wksSource设置为工作表,将wksOutput设置为工作表
    暗lngLastRowSource尽可能长,LNGlastrowOut尽可能长
    调暗RNG源作为范围,RNG输出作为范围
    Dim blnFirst作为布尔值
    “在前面设置引用
    
    strDir=“c:\stack\my_csvs\”如果文件较大,则可以将其合并为文本文档。这比导入csv对象快得多,但它要求所有文件中的属性及其放置顺序相等。例如:

    $files = Get-ChildItem "*.csv"
    #Get header
    $text = @(Get-Content -Path $files[0].FullName -TotalCount 1)
    
    $files | ForEach-Object {
        #Get text but skip header
        $text += Get-Content -Path $_.FullName | Select-Object -Skip 1
    }
    
    #Save merged csv
    $text | Set-Content Output.csv
    
    Output.csv

    Name;Age;Marks;Class
    A;15;100;5
    B;20;88;6
    C;11;99;2
    
    您可以通过替换
    [System.IO.File]:ReadAllLines()
    等的
    Get Content
    对其进行更多优化。但我现在跳过了它,因为它更复杂/更难阅读

    更新:添加了替代解决方案,按照Ansgar的建议,为每个零件保存输出文件

    $outputfile = "Output.csv"
    
    $files = Get-ChildItem "*.csv"
    
    #Get header
    Get-Content -Path $files[0].FullName -TotalCount 1 | Set-Content -Path $outputfile
    
    $files | ForEach-Object {
        #Get text but skip header
        Get-Content -Path $_.FullName | Select-Object -Skip 1
    } | Add-Content -Path $outputfile
    

    您是否为此任务与powershell结婚,或者是否可以使用Excel?您曾提到CSV,但称之为Excel工作表。他们都是CSV吗?或者它们实际上是Excel表格?都是CSV的。很抱歉。虽然excel也可以。op询问多个文件。不只是one@Matt这个命令接受*输入la
    c:\*.csv
    ,可以处理多个文件。我知道这一点。op可能不是。由于该问题是专门针对多个文件提出的,因此答案也应针对多个文件。我在使用上述解决方案导入Csv时遇到此错误:您必须指定-Path或-LiteralPath参数,但不能同时指定这两个参数。我想这一解决方法会使问题变得更好。Get ChildItem-filter*.csv | Select-expandProperty Name | Import csv在变量中收集整个数据可能会出现问题,尤其是对于大型文件。我会做
    获取内容-TotalCount 1 |设置内容输出.csv
    $files | ForEach对象{…}|改为添加内容输出.csv
    。为True,答案已更新。我还没有处理足够大的文件来解决问题,但按照您的建议,一次只保存一部分,这样您就安全了。我的尝试更多的是“概念证明”。在实际场景中,我可能还会使用
    [System.IO.File]
    :)