我有 1 个带有单张工作表和 3 个 csv 文件的 Excel 工作簿。工作表具有固定数量的列(带有标题)和不同数量的行。一列包含一个“ID”字段,最后三列是空白的。每个 csv 都有不同数量的列,但都有一个“ID”字段,该字段应与 Excel 工作表中的“ID”字段匹配。虽然 Excel 工作表可能有多个相同 ID 的实例,但 CSV 中没有重复的 ID。例如:
Excel文件
ID: Name: Color: Location: Age: Siblings: 123 Bob Red 234 Sally Green 345 Donald Orange 123 Bob Black
CSV1
ID: Name: Place: Animal: Location: Car: 123 Bob Here Dog Up Ferarri 234 Sally There Cat Down Porsche 345 Donald Nowhere Squid Right Yugo
CSV2
ID: Name: Place: Age: 123 Bob Here 50 234 Sally There 45 345 Donald Nowhere 100
CSV3
ID: Siblings: 123 Five 234 Three 345 Eight
The goal is to add the data from specific columns in the CSV files to the excel file based on matching IDs. Expected output would be the following Excel file:
ID: Name: Color: Location: Age: Siblings: 123 Bob Red Up 50 Five 234 Sally Green Down 45 Three 345 Donald Orange Right 100 Eight 123 Bob Black Up 50 Five
I have spent quite a bit of time trying to figure the most efficient (fast) method for doing this and think I've hit a brick wall. What I have so far (in relevant part):
# Pull relevant data from csv files together #
$rtFile = $selectedDirectory + "\\" + "*RT*.csv"
$seFile = $selectedDirectory + "\\" + "*SE*.csv"
$lmFile = $selectedDirectory + "\\" + "*LM*.csv"
$rtCSV = Import-Csv $rtFile | select ID, LOCATION
$seCSV = Import-Csv $seFile | select ID, AGE
$lmCSV = Import-Csv $lmFile | select ID, SIBLINGS
$rtCSV | ForEach {$_ | Add-Member 'AGE' $null}
$rtCSV | ForEach {$_ | Add-Member 'SIBLINGS' $null}
foreach ($record in $rtCSV) {
$record.'AGE' = $seCSV | Where {$_.ID -eq $record.ID} | Select -Expand 'AGE'
$Record.'SIBLINGS' = $lmCSV | Where {$_.ID -eq $record.ID} | Select -Expand 'SIBLINGS'
}
# Add Data to Excel Sheet #
$WorkSheet.Activate()
$range = $WorkSheet.Range("C1").EntireColumn
foreach ($searchStr in $rtCSV.ID) {
$search = $range.Find($searchStr)
if ($search -ne $null) {
$firstAdr = $search.Address(0, 0, 1, 0)
do {
$WorkSheet.Cells.Item($search.row,17).Value() = $rtCSV[$search.row].LOCATION
$WorkSheet.Cells.Item($search.row,18).Value() = $rtCSV[$search.row].AGE
$WorkSheet.Cells.Item($search.row,19).Value() = $rtCSV[$search.row].SIBLINGS
$search = $range.FindNext($search)
} while ($search -ne $null -and $search.Address(0, 0, 1, 0) -ne $firstAdr)
}
}
我花了一段时间,但我终于弄清楚了为什么上面的方法不起作用。而
$search.row
确实返回 Excel 文档中的匹配行(因此可以很好地用于确定在哪个单元格中插入数据)它没有为 $rtCSV
中的相应值返回适当的索引(?) .那么,如何确保每次 ID 匹配时插入正确的 LOCATION、AGE 和 SIBLINGS 值?如果在当前的结构下不可能,是否还有另一种(也许更好,更有效)的方法?一般来说,Excel 文件的行数不应超过 1,000 行。
最佳答案
如果你不介意安装额外的模块来简化你的工作,我强烈推荐 dfinke's Import Excel module .安装 if 后,实现目标的代码将很简单:
# cd C:\SO\53529676
$rtCSV = Import-Csv .\csv1.csv | select ID, LOCATION
$seCSV = Import-Csv .\csv2.csv | select ID, AGE
$lmCSV = Import-Csv .\csv3.csv | select ID, SIBLINGS
$excel = Import-Excel .\Excel1.xlsx
foreach ($record in $excel) {
$record.'LOCATION' = ($rtCSV | Where {$_.ID -eq $record.ID}).LOCATION
$record.'AGE' = ($seCSV | Where {$_.ID -eq $record.ID}).AGE
$Record.'SIBLINGS' = ($lmCSV | Where {$_.ID -eq $record.ID}).SIBLINGS
}
$excel | Export-Excel .\Excel2.xlsx
关于excel - 从多个 CSV 文件构建 Excel 电子表格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53529676/