【问题标题】:Building Excel spreadsheet from multiple CSV files从多个 CSV 文件构建 Excel 电子表格
【发布时间】:2019-04-30 23:09:15
【问题描述】:

我有 1 个 Excel 工作簿,其中包含一个工作表和 3 个 csv 文件。工作表具有固定数量的列(带有标题)和不同数量的行。一列包含一个“ID”字段,最后三列是空白的。每个 csv 都有不同数量的列,但都有一个“ID”字段,该字段应与 Excel 工作表中的“ID”字段匹配。虽然 Excel 工作表可能有多个相同 ID 的实例,但 CSV 中没有重复的 ID。例如:

Excel 文件

ID: 姓名: 颜色: 地点: 年龄: 兄弟姐妹: 123 鲍勃·雷德 234 莎莉·格林 第345章 123 鲍勃·布莱克

CSV1

ID: 姓名: 地点: 动物: 地点: 汽车: 123 Bob Here Dog Up Ferarri 234 Sally There Cat Down Porsche 345唐老鸭无处鱿鱼右雨果

CSV2

ID: 姓名: 地点: 年龄: 123 鲍勃在这里 50 第234章 45 345 唐老鸭 100

CSV3

身份证:兄弟姐妹: 123 五 234 三 345 八

目标是根据匹配的 ID 将 CSV 文件中特定列的数据添加到 excel 文件中。预期输出将是以下 Excel 文件:

ID: 姓名: 颜色: 地点: 年龄: 兄弟姐妹: 123 Bob Red Up 50 五 234 莎莉·格林 下 45 三 345 唐纳德·奥兰治 右 100 八 123鲍勃布莱克向上50五

我花了很多时间试图找出最有效(快速)的方法来做到这一点,并认为我已经碰壁了。到目前为止我所拥有的(在相关部分):

# 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 文件的行数不应超过 1000 行。

【问题讨论】:

  • 我认为您可以使用此...Merging data in PowerShell – Rambling Cookie Monster — http://ramblingcookiemonster.github.io/Join-Object/ 脚本在将文件导入 excel 之前将它们合并。您可能必须合并第一个两个,然后合并第三个,但看起来它会满足您的需要。

标签: excel powershell csv


【解决方案1】:

如果您主要关心的是性能,请考虑两件事:

将“查找表”(csv1、csv2、csv3)转换为哈希表,因此查找速度会很快(有点类似于数据库中的索引)

将所有数据保存在平面文件 (csv) 中,以避免依赖并保持脚本简单高效。然后,您可以将数据链接到电子表格作为要应用的视图 根据需要进行格式化(您可以在 MS Access 中从 csv 创建链接表和视图,然后将其提供给 Excel 中的数据表)

下面是一个示例(为简单起见,使用其他一些伪文件)。您也可以在主循环中使用工作表对象(只需循环遍历行索引并更新单元格对象)。

# generate hashtables
$person = @{}
$location = @{}
Import-Csv location.csv | foreach {$location.Add($_.id, @{zip=$_.zip; city=$_.city})}
Import-Csv person.csv | foreach {$person.Add($_.id, @{name=$_.name; age=$_.age})}

# loop through the main file
Import-Csv main.csv | foreach {
    $id = $_.id
    $_.name = $person[$id].name
    $_.age = $person[$id].age
    $_.city = $location[$id].city
    $_.zip = $location[$id].zip
    Write-Output $_ } | Convertto-Csv | Out-File mainOut.csv

【讨论】:

    【解决方案2】:

    如果您不介意安装额外的模块来简化您的工作,我强烈推荐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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-05
      • 1970-01-01
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 2012-09-05
      • 2014-10-13
      • 2023-03-27
      相关资源
      最近更新 更多