Powershell哈希表导出到CSV

Powershell哈希表导出到CSV,powershell,csv,hashtable,export-to-csv,powershell-4.0,Powershell,Csv,Hashtable,Export To Csv,Powershell 4.0,我正在尝试创建一个CSV导出,其中包含搜索电子表格中ID显示的数据电子表格中的所有行 我现在已经通过PowerShell创建了搜索元素,但是在将数据导出为CSV格式时遇到了问题 下面是一些示例表,实际数据最多有8个值(包括ID列),但只有前三个值是保证填充的 数据电子表格 +------+---------+---------+---------+---------------------+ |ID |值1 |值2 |值3 |值4| +------+---------+---------+---

我正在尝试创建一个CSV导出,其中包含搜索电子表格中ID显示的数据电子表格中的所有行

我现在已经通过PowerShell创建了搜索元素,但是在将数据导出为CSV格式时遇到了问题

下面是一些示例表,实际数据最多有8个值(包括ID列),但只有前三个值是保证填充的

数据电子表格

+------+---------+---------+---------+---------------------+
|ID |值1 |值2 |值3 |值4|
+------+---------+---------+---------+---------------------+
|1234 |伦敦|系列1 | HP |笔记本电脑用户|
|2345 |莫斯科|系列7 | |人力资源申请|
|1234 |伦敦|系列9 | |金融应用|
|3456 |马德里|系列4 | HP |笔记本电脑用户|
+------+---------+---------+---------+---------------------+

搜索电子表格

+------+
|身份证|
+------+
| 1234 |
| 2345 |
+------+

期望结果

+------+---------+---------+---------+---------------------+
|ID |值1 |值2 |值3 |值4|
+------+---------+---------+---------+---------------------+
|1234 |伦敦|系列1 | HP |笔记本电脑用户|
|2345 |莫斯科|系列7 | |人力资源申请|
|1234 |伦敦|系列9 | |金融应用|
+------+---------+---------+---------+---------------------+

下面是我在尝试导出到CSV时删除的当前代码

$finalValues = @{}

$users = Import-Csv "SEARCH.csv"

$data = Import-Csv "DATA.csv" | Group-Object -property ID -AsHashTable

foreach ($user in $users) 
{
    If ($data.Contains($user.ID))
    {
        #write-output $data[$user.ID].ID
        $finalValues.Add($data[$user.ID].ID, $data[$user.ID])
    }
}
以下两个命令(在脚本其余部分执行后运行)具有以下输出

$finalValues.Values

ID      : 1234
Value 1 : London
Value 2 : Serial 1
Value 3 : HP
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Laptop User

ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : HR Application

ID      : 1234
Value 1 : London
Value 2 : Serial9
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Finance Application
{1234, 1234}             {@{ID=1234; Value 1=London; Value 2=Serial1; Value 3=HP; Value 4=; Value 5=; Value 6=; Value 7=Laptop User}, @{ID=1234; Value 1=London; Value 2=Serial 9... ; Value 7 =Finance Application}}

2345                        {@{ID=2345; Value 1=Moscow; Value 2=Serial7; Value 3=; Value 4=; Value 5=; Value 6=; Value 7=HR Application}}           
$finalValues

ID      : 1234
Value 1 : London
Value 2 : Serial 1
Value 3 : HP
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Laptop User

ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : HR Application

ID      : 1234
Value 1 : London
Value 2 : Serial9
Value 3 : 
Value 4 : 
Value 5 : 
Value 6 : 
Value 7 : Finance Application
{1234, 1234}             {@{ID=1234; Value 1=London; Value 2=Serial1; Value 3=HP; Value 4=; Value 5=; Value 6=; Value 7=Laptop User}, @{ID=1234; Value 1=London; Value 2=Serial 9... ; Value 7 =Finance Application}}

2345                        {@{ID=2345; Value 1=Moscow; Value 2=Serial7; Value 3=; Value 4=; Value 5=; Value 6=; Value 7=HR Application}}           
使用以下命令导出到CSV时,我得到以下结果:
$finalValues |导出csv-Path test.csv-NoTypeInformation

+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| IsReadOnly | IsFixedSize | IsSynchronized |                    Keys                    |                    Values                    |   SyncRoot    | Count |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| FALSE      | FALSE       | FALSE          | System.Collections.Hashtable+KeyCollection | System.Collections.Hashtable+ValueCollection | System.Object |    14 |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
+-------+------------+-------------+---------------+----------------+
| Count | IsReadOnly | IsFixedSize |   SyncRoot    | IsSynchronized |
+-------+------------+-------------+---------------+----------------+
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     3 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
+-------+------------+-------------+---------------+----------------+
使用以下命令导出到CSV时,我得到以下结果:

$finalValues.Values |导出csv-Path test.csv-NoTypeInformation

+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| IsReadOnly | IsFixedSize | IsSynchronized |                    Keys                    |                    Values                    |   SyncRoot    | Count |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
| FALSE      | FALSE       | FALSE          | System.Collections.Hashtable+KeyCollection | System.Collections.Hashtable+ValueCollection | System.Object |    14 |
+------------+-------------+----------------+--------------------------------------------+----------------------------------------------+---------------+-------+
+-------+------------+-------------+---------------+----------------+
| Count | IsReadOnly | IsFixedSize |   SyncRoot    | IsSynchronized |
+-------+------------+-------------+---------------+----------------+
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     3 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     2 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
|     1 | FALSE      | FALSE       | System.Object | FALSE          |
+-------+------------+-------------+---------------+----------------+

这可以通过使用过滤器然后使用导出来简化

显然是一种更好的实现方法,但我只是想解释一下您的原始代码有什么问题。问题是
$data
是一个
哈希表
字符串(用户
ID
)映射到数组(实际上它是一个数组,但出于我们的目的,它的行为是相同的)。即使在只有一条匹配记录的
ID
'2345'
情况下,
$data
仍将其存储为一个包含一个元素的数组:

PS> $data['2345'].GetType().Name
Collection`1
PS> $data['2345'].Count
1
PS> $data['2345']    # Returns the array of values


ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 :
Value 4 : HR Application


PS> $data['2345'][0] # Returns the first element of the array of values


ID      : 2345
Value 1 : Moscow
Value 2 : Serial7
Value 3 :
Value 4 : HR Application
因此,当这行执行时

$finalValues.Add($data[$user.ID].ID, $data[$user.ID])
…您正在向
$data
添加一个新项,其中键和值都是数组。这就是为什么管道
$finalValues
$finalValues.Values
导出Csv
的输出行为与值是数组一样;因为他们是

为了解决这个问题,当访问
$data
中的项目时,我们需要一个内部循环来“展开”每个值。此外,我们不能对
$finalValues
使用
哈希表
,因为您使用
ID
作为键,但结果中存在重复的
ID
s(
'1234'
)。由于我们所需要的只是一个最终传递到
导出Csv
的记录的平面列表,因此我们可以使用数组来代替。这里有一些修改过的代码

$finalValues = @() # Cannot be a HashTable because there may be multiple results with the same ID

$users = Import-Csv "SEARCH.csv"

$data = Import-Csv "DATA.csv" | Group-Object -property ID -AsHashTable

foreach ($user in $users)
{
    If ($data.Contains($user.ID))
    {
        # "Unwrap" the array stored at $data[$user.ID]
        foreach ($dataRecord in $data[$user.ID])
        {
            $finalValues += $dataRecord
        }
    }
}

$finalValues | Export-Csv -Path test.csv -NoTypeInformation
…生成此CSV的

"ID","Value 1","Value 2","Value 3","Value 4"
"1234","London","Serial1","HP","Laptop User"
"1234","London","Serial9","","Finance Application"
"2345","Moscow","Serial7","","HR Application"

$finalValues.Values |导出Csv…
你好,Mathias,感谢您的回复。我以前试过,但以前没提过。我已经用这个命令更新了帖子的输出。哇,谢谢你的评论。它解决了我的问题,并大量减少了代码。我将用此更新主要帖子。感谢您花时间解释解决方案如何与原始尝试一起工作。我仍在熟悉PowerShell中的数据结构,这非常有用。