【问题标题】:PowerShell append to first available row in a headered column in csvPowerShell 附加到 csv 标题列中的第一个可用行
【发布时间】:2022-01-27 18:38:32
【问题描述】:

对 PowerShell 相当陌生,在 csv 文件中的每个标题列的第一个可用行中附加数据时遇到了挑战。

我想将foreach 用于每一列的数据类型,这些数据类型将独立于另一列的数据。列标题为$headers = "Scope", "Drawing", "Submittal", "Database", "Estimate", "Sequence",带有foreach,用于定位它们的各个项目并将其附加到每列。当前发生的问题是,因为每个类别/列及其各自的foreach 都会将其添加到单独的行中,因为前一行已经从另一个类别/列的数据中附加了数据,从而创建了对角线附加数据。

为每个类别/列使用单独的foreach 的原因是,该类别正在为每个类别独立查找和过滤文件。

以下是 CSV 文件中发生的情况:

| Scope | Drawing | Submittal | Database | Estimate | Sequence |
| ------| ------- |---------- |--------- |--------- |--------- |
| DATA01| empty   | empty     | empty    | empty    | empty    |
| empty | DATA11  | empty     | empty    | empty    | empty    |
| empty | empty   | DATA21    | empty    | empty    | empty    |
| empty | empty   | empty     | DATA31   | empty    | empty    |
| empty | empty   | empty     | empty    | DATA41   | empty    |
| empty | empty   | empty     | empty    | empty    | DATA51   |

这是 CSV 文件的预期结果:

| Scope | Drawing | Submittal | Database | Estimate | Sequence |
| ------| ------- |---------- |--------- |--------- |--------- |
| DATA01| DATA11  | DATA21    | DATA31   | DATA41   | DATA51   |         

这是正在处理的部分代码:

# Creates the CSV if it does not already exist
$headers = "Scope", "Mechanical Drawing", "Controls Submittal", "Database", "Estimate", "Sequence of Operations"
$psObject = New-Object psobject
foreach($header in $headers)
{
 Add-Member -InputObject $psobject -MemberType noteproperty -Name $header -Value ""
}
$psObject | Export-Csv $CsvFile -NoTypeInformation

foreach ($file in $ScopeList)
{
    $hash=@{
        "Scope" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

foreach ($file in $DrawingList)
{
    $hash=@{
        "Drawing" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

foreach ($file in $SubtmittalList)
{
    $hash=@{
        "Submittal" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

foreach ($file in $DatabaseList)
{
    $hash=@{
        "Database" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

foreach ($file in $EstimateList)
{
    $hash=@{
        "Estimate" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

foreach ($file in $SequenceList)
{
    $hash=@{
        "Sequence" = $file.Fullname
    }
    $NewItem = New-Object PSObject -Property $hash
    Export-Csv $CsvFile -inputobject $NewItem -append -Force
}

使用的 PowerShell 版本是 5.1。 Windows 10 操作系统。

有人可以帮助我了解如何在不删除另一列现有数据行的情况下追加到同一行但不同的列上吗?这可以通过喷溅或查看每个变量${named}List 来完成吗?

【问题讨论】:

  • 所有列表都对齐并且计数相同吗?例如。 $ScopeList 中的第 N 项对应于$SequenceList 等中的第 N 项。
  • @MathiasR.Jessen 这些列表不会相互对齐/对应,并且可能并不总是具有相同的计数。对于列表,计数可能为 0。但回到您的示例,$ScopeList 将独立于 $SequenceList;两个列表都有自己的过滤条件和脚本正在寻找的文件扩展名类型。
  • 所以它不是真正的 CSV?它更像是“6 个彼此相邻的堆叠列”-kinda 文件 :)
  • @MathiasR.Jessen 对,一个“6 列并排”类型的文件哈哈。最初脚本是在 .log 文件中输出列表,但考虑到未来的目标,输出到 CSV 有望允许以某种一致的表格/电子表格格式进行进一步的数据分析(NLP/K-clustering),这样会更容易抓取和分析。

标签: powershell csv append


【解决方案1】:

如果我正确理解了这个问题,您有 6 个“$file”数组需要组合成一个 CSV 文件。

然后不要使用 6 个foreach 循环,只需使用一个索引循环并从各种列表中创建对象

如果所有列表具有相同数量的项目

$result = for ($i = 0; $i -lt $ScopeList.Count; $i++) {
    [PsCustomObject]@{
        Scope     = $ScopeList[$i].FullName
        Drawing   = $DrawingList[$i].FullName
        Submittal = $SubtmittalList[$i].FullName
        Database  = $DatabaseList[$i].FullName
        Estimate  = $EstimateList[$i].FullName
        Sequence  = $SequenceList[$i].FullName
    }
}

# now save the result as CSV file
$result | Export-Csv -Path 'X:\Path\to\TheResult.csv' -NoTypeInformation

如果列表的长度不同,则需要做一些额外的工作:

# get the maximum number of items of your lists
$maxItems = (($ScopeList, $DrawingList, $SubtmittalList, $DatabaseList, $EstimateList, $SequenceList) | 
            Measure-Object -Property Count -Maximum).Maximum

# loop over the maximum number of items and check each list 
# if the index $i does not exceed the max number of items for that list
$result = for ($i = 0; $i -lt $maxItems; $i++) {
    [PsCustomObject]@{
        Scope     = if ($i -lt $ScopeList.Count)      {$ScopeList[$i].FullName}      else { $null}
        Drawing   = if ($i -lt $DrawingList.Count)    {$DrawingList[$i].FullName}    else { $null}
        Submittal = if ($i -lt $SubtmittalList.Count) {$SubtmittalList[$i].FullName} else { $null}
        Database  = if ($i -lt $DatabaseList.Count)   {$DatabaseList[$i].FullName}   else { $null}
        Estimate  = if ($i -lt $EstimateList.Count)   {$EstimateList[$i].FullName}   else { $null}
        Sequence  = if ($i -lt $SequenceList.Count)   {$SequenceList[$i].FullName}   else { $null}
    }
}

# now save the result as CSV file
$result | Export-Csv -Path 'X:\Path\to\TheResult.csv' -NoTypeInformation

【讨论】:

  • 昨晚我有一个类似的想法,或者,只选择排序列表的第一个/顶部文件,以便每个列表有 0 或 1 个项目。我试图调试的挑战是控制台从代码$maxItems = (($ScopeList, $DrawingList, $SubtmittalList, $DatabaseList, $EstimateList, $SequenceList) | Measure-Object -Property Count -Maximum).Maximum 返回错误Measure-Object : The property "Count" cannot be found in the input for any objects.。在每个列表上执行.count 确实会返回一个值,但不确定为什么它不会将它们视为对象。
  • @Screamcheese 所以至少有一个列表不是数组。我现在在移动设备上,但明天会编辑
  • Theo,我想通了,并对您的代码进行了修改。由于一些if 语句和过滤,我使用您的建议找到了一个替代解决方案,并根据已经建立的 6 个列表创建了一个新列表。明天不需要编辑。感谢您为我指明正确的方向!我将在下面发布部分工作代码。
【解决方案2】:

就像 Theo 发布的那样,这主要是有效的,或者使意图更接近目标。 在创建其独立列表的每个 foreach 循环中,创建了另一个列表来过滤列表,并在 Theo 的以下部分中使用。

# loop over the maximum number of items and check each list 
# if the index $i does not exceed the max number of items for that list
$result = for ($i = 0; $i -lt $maxItems; $i++) {
    [PsCustomObject]@{
        Scope     = if ($i -lt $ScopeList.Count)      {$ScopeList[$i].FullName}      else { $null}
        Drawing   = if ($i -lt $DrawingList.Count)    {$DrawingList[$i].FullName}    else { $null}
        Submittal = if ($i -lt $SubtmittalList.Count) {$SubtmittalList[$i].FullName} else { $null}
        Database  = if ($i -lt $DatabaseList.Count)   {$DatabaseList[$i].FullName}   else { $null}
        Estimate  = if ($i -lt $EstimateList.Count)   {$EstimateList[$i].FullName}   else { $null}
        Sequence  = if ($i -lt $SequenceList.Count)   {$SequenceList[$i].FullName}   else { $null}
    }
}

# now save the result as CSV file
$result | Export-Csv -Path 'X:\Path\to\TheResult.csv' -NoTypeInformation

要获得$maxItems,另一种方法是使用默认值 1,除非用户在提示输入其他信息时输入关键字“list”,这是如何将值限制为更大的另一个挑战大于等于 1...

【讨论】:

    猜你喜欢
    • 2021-02-19
    • 1970-01-01
    • 2020-02-17
    • 2019-06-19
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 2018-02-17
    • 1970-01-01
    相关资源
    最近更新 更多