合并很多CSV文件

我有一组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 

如果所有的CSV文件都在一个文件夹中,那么:

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

分解:

  • $res = @() – 创build一个名为$ res的数组来保存所有的数据。 这不是严格要求。 你可以用直接附加到结果文件的方式来完成。

  • ls *.csv | – find文件夹中的所有CSV文件,并将它们传递给下一个命令。

  • %{$temp = Import-CSV $_; $res += $temp} %{$temp = Import-CSV $_; $res += $temp} – 获取每个文件,将CSV数据导入一个名为$temp的持有者variables。 将$temp的内容添加到收集器variables$res 。 再次,没有必要使用中间$tampvariables,我只是觉得这样做更清楚。

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

如果文件很大,那么你可以合并它们作为文本文件。 这比导入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 

你可以通过replace[System.IO.File]::ReadAllLines()Get-Content来更好地优化它,但是现在我跳过了,因为它更复杂/难以阅读。

更新:添加替代解决scheme,保存部分输出文件部分,如Ansgarbuild议。

 $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 

在你的情况下, sort name是可选的,取决于合并是否应该重新sorting内容(显然,你也可以sort在不同的参数)。 与上面相同的规定 – 一个目录中的所有.csv文件。

dir c:\directory_containing_your\*.csv | Import-Csv | sort name | Export-Csv -Path c:\output.csv -NoTypeInformation

从ScriptingGuy 。

这是一个重要的解决scheme,它使用Excel中的VBA来组合CSV。 这里的策略是这样的:

  1. 首先设置你的参考,最重要的是strDirvariables(这是一个代表所有CSV的目录的string)
  2. 循环访问目录
  3. 打开每个CSV
  4. 从每个CSV复制适当的内容
  5. 将内容粘贴到输出工作簿
  6. 重复循环直到所有文件都被迭代完成

希望这可以帮助!

 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