You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 5.1合并DataTable后导出CSV内容不全,如何解决?

问题

环境:PowerShell 5.1

我用以下代码将两个DataTable $dt_1 和 $dt_2 合并为新的集合$merged:

$merged = $dt_1 | ForEach-Object {
$dt1Row = $_
$dt2Rows = $dt_2 | Where-Object { $_"Facility" -eq $dt1Row"Facility" -and $_"Customer" -eq $dt1Row"Customer" -and $_"Contract" -eq $dt1Row"Contract" }

$resultObject = $dt1Row | Select-Object  "Contract", "Customer ","Contract"
$Count = 1

foreach ($dt2Row in $dt2Rows) {
    $resultObject | Add-Member -MemberType NoteProperty -Name ("Material - $Count") -Value $dt2Row.Material
    $resultObject | Add-Member -MemberType NoteProperty -Name ("Material_Number - $Count") -Value $dt2Row.'Material_Number'
    $Count ++

}

$resultObject
}

其中$dt_2中每个以Facility、Customer、Contract为键的条目对应多条记录。

在控制台执行$merged | Format-Table -AutoSize时,能显示完整的目标列(包含Material - 1、Material_Number - 1等多组列),但执行$merged | Export-Csv "\Path\To\CSV.csv" -NoType -Delimiter ";" -Encoding UTF8导出CSV后,仅保留到Material - 1和Material_Number - 1列,后续列丢失。

请问该问题的原因是什么?如何实现完整导出?

原因分析

PowerShell的Export-Csv会以集合中第一个对象的属性集合作为CSV的固定表头,后续对象新增的属性会被直接忽略。

你的代码中,如果第一个生成的$resultObject只添加了Material - 1和Material_Number - 1这两组属性,那么后续对象里的Material - 2、Material_Number - 2等属性,在导出时会被丢弃——因为表头已经由第一个对象确定,Export-Csv不会再去识别后续对象的新属性。

而Format-Table能显示所有列,是因为它会遍历整个集合,收集所有对象的所有属性后再统一格式化,不会被第一个对象的属性限制。

解决方法

方法1:预先构建包含所有可能列的对象

先统计$dt_2中每个键对应的最大记录数,然后在创建$resultObject时就预先添加所有可能的Material - N和Material_Number - N属性(初始值设为$null),再填充实际数据。这样所有对象的属性集合一致,Export-Csv就能完整导出所有列:

# 先统计每个键组对应的最大记录数
$maxCount = ($dt_2 | Group-Object Facility, Customer, Contract | Select-Object -ExpandProperty Count) | Measure-Object -Maximum | Select-Object -ExpandProperty Maximum

$merged = $dt_1 | ForEach-Object {
    $dt1Row = $_
    $dt2Rows = $dt_2 | Where-Object { 
        $_.Facility -eq $dt1Row.Facility -and 
        $_.Customer -eq $dt1Row.Customer -and 
        $_.Contract -eq $dt1Row.Contract 
    }

    # 用有序哈希表预先定义所有列,确保顺序一致
    $resultProps = [ordered]@{
        Contract = $dt1Row.Contract
        Customer = $dt1Row.Customer
    }
    # 循环添加所有可能的Material相关列
    for ($i=1; $i -le $maxCount; $i++) {
        $resultProps["Material - $i"] = $null
        $resultProps["Material_Number - $i"] = $null
    }
    # 创建包含所有列的对象
    $resultObject = New-Object -TypeName PSObject -Property $resultProps

    # 填充实际数据
    $Count = 1
    foreach ($dt2Row in $dt2Rows) {
        $resultObject."Material - $Count" = $dt2Row.Material
        $resultObject."Material_Number - $Count" = $dt2Row.'Material_Number'
        $Count ++
    }

    $resultObject
}

# 导出CSV
$merged | Export-Csv "\Path\To\CSV.csv" -NoType -Delimiter ";" -Encoding UTF8

方法2:手动指定所有需要导出的列

如果能提前确定最大的记录组数(比如最多有3组Material数据),可以直接在导出时用Select-Object列出所有需要的列,强制Export-Csv包含这些列:

# 假设最多有3组Material列,按需调整数量
$merged | Select-Object Contract, Customer, `
    "Material - 1", "Material_Number - 1", `
    "Material - 2", "Material_Number - 2", `
    "Material - 3", "Material_Number - 3" |
Export-Csv "\Path\To\CSV.csv" -NoType -Delimiter ";" -Encoding UTF8

这种方法适合已知最大记录数的场景,灵活性不如方法1。

内容的提问来源于stack exchange,提问作者Peter S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:40:14