Vba 合并多个CSV文件
我有一套500个csv文件。每个文件有四列,行数可变 我想将所有这些csv合并到一个通用工作表中。如果有人能在PowerShell中帮我做这件事,那就太好了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
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=@()
找到文件夹中的所有csv文件,并将其传递给下一个命令ls*.csv |
-获取每个文件,将CSV数据导入名为%{$temp=Import CSV$\$res+=$temp}
的holder变量。将$temp
的内容添加到收集器变量$temp
。同样,不必使用中间$res
变量,我只是觉得这样做更清楚$tamp
-现在所有文件的数据都在$res |导出CSV。\ALLINFO.CSV-NoTypeInformation
中,将$res
导出到新文件$res
strDir
变量(这是一个表示保存所有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这个命令接受*输入lac:\*.csv
,可以处理多个文件。我知道这一点。op可能不是。由于该问题是专门针对多个文件提出的,因此答案也应针对多个文件。我在使用上述解决方案导入Csv时遇到此错误:您必须指定-Path或-LiteralPath参数,但不能同时指定这两个参数。我想这一解决方法会使问题变得更好。Get ChildItem-filter*.csv | Select-expandProperty Name | Import csv在变量中收集整个数据可能会出现问题,尤其是对于大型文件。我会做获取内容-TotalCount 1 |设置内容输出.csv
和$files | ForEach对象{…}|改为添加内容输出.csv
。为True,答案已更新。我还没有处理足够大的文件来解决问题,但按照您的建议,一次只保存一部分,这样您就安全了。我的尝试更多的是“概念证明”。在实际场景中,我可能还会使用[System.IO.File]
:)