好的。。。所以我有一个System.Data.DataRow对象。我已经把列名放到了一个字符串集合中。然后我想将相应的值放入第二个集合中。
我确信我只是在做一些愚蠢的事情,但我一辈子都无法弄清楚这一点。取以下代码。。。
$cols = $drFrom.Table.Columns
$colNames = $cols | Where-Object { $_.ColumnName -ne "ROWID" } | Select-Object $_.ColumnName
Write-Host $colNames
$colValues = $colNames | Select-Object $drFrom.Item($_).ToString()
注意,Write-Host
显示$colNames
包含预期的列名,并在控制台中输出:
CLIENTID MESSAGE AMOUNT PAIDBY PAIDBYEMAIL ACTIVE
因此,这样做的目的是将$colNames
管道传输到Select-Object
中,并为每个列名从DataRow中获取值。但由于某种原因,当它在Select-Object
中运行时,$_
似乎返回为空,而不是已知存在于$colNames
集合中的字符串值。当它运行第4行时,为了进行管道,它抛出了这个异常:
Exception getting "Item": "Exception calling "get_Item" with "1" argument(s): "'column' argument cannot be null.
Parameter name: column""
At D:MyScriptsMyScript.ps1:145 char:5
+ $colValues = $colNames | Select-Object $drFrom.Item($_).ToString( ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], GetValueInvocationException
+ FullyQualifiedErrorId : CatchFromBaseParameterizedPropertyAdapterGetValue
我还尝试过将迭代变量嵌入引号中,比如…
$colValues = $colNames | Select-Object $drFrom.Item("$_").ToString()
然后异常相应地改变,但仍然反映$_
:的空值
Exception getting "Item": "Exception calling "get_Item" with "1" argument(s): "Column '' does not belong to table .""
+ $colValues = $colNames | Select-Object $drFrom.Item("$_").ToStrin ...
如何使迭代变量实际反映管道时$colNames
中的字符串值?
要通过Select-Object
动态定义属性,必须使用计算属性,该属性包括定义属性名称的哈希表和定义属性值({ ... }
)的脚本块,在该脚本块中,您可以通过自动$_
变量引用手头的管道输入对象。
但是,您不希望定义计算的属性,而是希望输出计算的值。为此,您需要使用对ForEach-Object
:的调用
$colNames = $cols |
Where-Object ColumnName -ne ROWID |
ForEach-Object ColumnName
$colValues = $colNames |
ForEach-Object { $drFrom.Item($_).ToString() }
注意,对于Where-Object
和ForEach-Object
调用,第一个管道都使用简化的语法。
你说
我想将相应的值放入第二个集合中。
您有:
$cols = $drFrom.Table.Columns
$colNames = $cols |
Where-Object { $_.ColumnName -ne "ROWID" } |
Select-Object $_.ColumnName
这是有效的(但可以简化)。
现在有两件事你想做:
- 选择列
- 将列转换为字符串
单独做这些要简单得多。
首先选择您想要的属性:
$colValues = $drFrom |
Select-Object $colNames
现在您已经在PSCustomObject中拥有了所需的列。这很重要,因为我们可以使用隐藏的PSObject属性:
$colValues.PSObject.Properties.Name |
ForEach {$colValues.$_ = [string]$colValues.$_}
在这里,我已经从调用.ToString()切换到使用强制转换运算符[string],因为它处理$null时不会出错。
我想这会给你想要的。
您的列名计算可以简化为
$colNames = drFrom.Table.Columns.ColumnName |
Where-Object {$_ -ne "ROWID"}
如果有任何可能drFrom是一个列表,那么:
$colNames = drFrom[0].Table.Columns.ColumnName |
Where-Object {$_ -ne "ROWID"}
当您只想消除列时(似乎是这样),您可以简化为:
$colValues = $drFrom |
Select-Object * -ExcludeProperty "ROWID"
并将剩余属性转换为字符串:
$colValues.PSObject.Properties.Name |
ForEach {$colValues.$_ = [string]$colValues.$_}
当你写:
我想将相应的值放入第二个集合中。
不清楚您想要该集合的形式。上面我生成了一个具有命名属性的对象,因为我发现它在PowerShell中更有用。您提供的代码似乎试图提取字符串列表。如果这是你想要的,那么将上面的最后一行代码替换为:
$stringList = $colValues.PSObject.Properties.Name |
ForEach {[string]$colValues.$_}
我希望这能有所帮助。