如何创建像'Import-CSV'这样的Powershell自定义对象

时间:2017-12-14 15:05:59

标签: powershell object ms-access import-from-csv

我正在尝试从Microsoft Access中提取表格并使其看起来像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列表定制的自定义对象。

2 个答案:

答案 0 :(得分:1)

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个文件提取String和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是什么或如何创建。{1}}。我认为它类似于ADO RecordSet,但是你的逻辑让我有些失望。  (也就是说,$rs.MoveFirst()看起来像是错误的循环,如果它做了我记得RecordSet.MoveFirst()做的事情,但我可能会记错了。)

然而,这里的想法是一样的。

答案 1 :(得分:0)

$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; 

}     直到     ($ rs.EOF -eq $ True)

}

}
   $resultsarray 

我做到了!!!!诀窍是将记录添加到数组中,然后清除对象,添加成员,添加到数组,清除对象.....太棒了!