我正在尝试从Microsoft访问中拉出一张表,并且看起来像PowerShell中的Import-CSV
表,如果CSV文件中的每个列成为自定义对象的属性,而行中的项目成为属性值。我唯一取得的成功是:
$ColumnCount = 0;
$contactObject = new-object PSObject;
if ($rs.RecordCount -ne 0) {
do {
$rs.MoveFirst()
$valueArray = @();
do {
foreach ($columnHeader in $rs.fields.item($ColumnCount).name) {
$value = $rs.Fields.Item($columnHeader).Value;
$valueArray += $value
}
$rs.MoveNext()
} until ($rs.EOF -eq $True)
$contactObject | Add-Member -MemberType NoteProperty -Name $columnHeader -Value $valueArray;
$ColumnCount++
} until ($ColumnCount -eq $rs.fields.count)
}
,它输出了以下内容:
EquipmentPackageID ElementID ArchitectureID Delete
------------------ --------- -------------- ------
{117, 117, 126, 126...} {32, 32, 32, 32...} {-1, 1, -1, 1...} {False, False, False, False...}
但我不想要单个数组。
我希望这一切基本上都是一个桌子。而且,此功能必须能够接受访问的不同尺寸和命名表。因此,我无法创建针对此4列表量身定制的自定义对象。
powershell v3.0 的基本模式是这样的:
$MyFiles = Get-ChildItem C:Windows | ForEach-Object {
[pscustomobject]@{
Name = $_.Name;
FullName = $_.FullName;
CreationDate = $_.CreationTime.Date;
}
}
另外,避免这种模式:
$Array = @()
$x | ForEach-Object {
$Record = [...]
$Array += $Record
}
基本.NET阵列无法调整大小。这意味着$Array += [...]
必须制作一个全新的数组,复制所有内容,然后销毁旧数组。数组的变化越大,此操作越昂贵,它消耗的内存就越多,并且脚本的速度越慢。它将任何普通的O(n)复杂度循环变成O(n^2)复杂度环。
这意味着您应该这样做:
$Array = $x | ForEach-Object { [...] }
或以下:
$Array = New-Object -TypeName System.Collections.ArrayList;
$x | ForEach-Object {
$Record = [...]
$Array.Add($Record)
}
这是一个动态拉动标头的示例。在这种情况下,它将在C:Windows
中的前10个文件中拉出类型字符串和DateTime的所有属性。
# Get the data
$Data = Get-ChildItem C:Windows -File | Select-Object -First 10;
# Get the headers that meet our criteria
# It's not important what this code is doing, it's just establishing headers
# dynamically
$Headers = $Data[0].PSObject.Properties |
Where-Object TypeNameOfValue -in @('System.String', 'System.DateTime') |
Select-Object -ExpandProperty Name;
# Iterate through the Data
$Results = $Data | ForEach-Object {
# Create a hash table to save the properties in.
$Record = @{};
# For each header, create a property in the hash table and assign it the corresponding value from the object in the stream
foreach ($Header in $Headers) {
$Record.$Header = $_.$Header;
}
# Convert the hash table we've saved to a PSCustomObject
[PSCustomObject]$Record;
}
不幸的是,我不知道$rs
是什么或如何创建一个。我认为这就像ADO RecordSet一样,但是您的逻辑使我有些逃脱。 (也就是说,如果$rs.MoveFirst()
做到了我记得的RecordSet.MoveFirst()
,则看起来像是错误的循环,但我可能会误解。)
这里的想法是相同的。
$resultsArray = New-Object -TypeName System.Collections.ArrayList;
$ColumnCount = 0;
$contactObject = New-Object PSObject;
if ($rs.RecordCount -ne 0){
$rs.MoveFirst()
Do {
$ColumnCount = 0;
Do{
$columnHeader = $rs.fields.item($ColumnCount).name
$value = $rs.Fields.Item($columnHeader).Value;
$contactObject | add-member -membertype NoteProperty -name $columnHeader -
Value $value;
$columncount++
}until($ColumnCount -eq $rs.fields.count)
$resultsArray.add($contactObject)
$rs.MoveNext()
$contactObject= New-Object PSObject;
} until ($rs.EOF -eq $True)
}
}
$resultsarray
我做到了!诀窍是将记录添加到数组,然后清除对象,添加成员,添加到数组,清除对象.....棒极了!