2015-12-08 80 views
1

我想在PowerShell中执行一个简单的任务,其中一些基本统计信息是针对CSV文件中的多个列进行计算的。我差不多完成了,但是当我创建的新列出现为空时,我一直收到错误。在这里,我看不出我要出错的地方。新创建的列为空....为什么?

具体的代码导致错误的线是

$STATS2.Columns.Add($colVZA) | 

进口$filename什么时候有一个名为VZA,VAZ等栏目,所以这不是问题创建的表。

好像添加和填充列应该是一个简单的任务,所以我确信我在这里错过了一些简单的东西。这里是我的代码:

####################### 
function Get-Type 
{ 
    param($type) 

$types = @( 
'System.Boolean', 
'System.Byte[]', 
'System.Byte', 
'System.Char', 
'System.Datetime', 
'System.Decimal', 
'System.Double', 
'System.Guid', 
'System.Int16', 
'System.Int32', 
'System.Int64', 
'System.Single', 
'System.UInt16', 
'System.UInt32', 
'System.UInt64') 

    if ($types -contains $type) { 
     Write-Output "$type" 
    } 
    else { 
     Write-Output 'System.String' 

    } 
} #Get-Type 

####################### 
<# 
.SYNOPSIS 
Creates a DataTable for an object 
.DESCRIPTION 
Creates a DataTable based on an objects properties. 
.INPUTS 
Object 
    Any object can be piped to Out-DataTable 
.OUTPUTS 
    System.Data.DataTable 
.EXAMPLE 
$dt = Get-psdrive| Out-DataTable 
This example creates a DataTable from the properties of Get-psdrive and assigns output to $dt variable 
.NOTES 
Adapted from script by Marc van Orsouw see link 
Version History 
v1.0 - Chad Miller - Initial Release 
v1.1 - Chad Miller - Fixed Issue with Properties 
v1.2 - Chad Miller - Added setting column datatype by property as suggested by emp0 
v1.3 - Chad Miller - Corrected issue with setting datatype on empty properties 
v1.4 - Chad Miller - Corrected issue with DBNull 
v1.5 - Chad Miller - Updated example 
v1.6 - Chad Miller - Added column datatype logic with default to string 
v1.7 - Chad Miller - Fixed issue with IsArray 
.LINK 
http://thepowershellguy.com/blogs/posh/archive/2007/01/21/powershell-gui-scripblock-monitor-script.aspx 
#> 
function Out-DataTable 
{ 
    [CmdletBinding()] 
    param([Parameter(Position=0, Mandatory=$true, ValueFromPipeline = $true)] [PSObject[]]$InputObject) 

    Begin 
    { 
     $dt = new-object Data.datatable 
     $First = $true 
    } 
    Process 
    { 
     foreach ($object in $InputObject) 
     { 
      $DR = $DT.NewRow() 
      foreach($property in $object.PsObject.get_properties()) 
      { 
       if ($first) 
       { 
        $Col = new-object Data.DataColumn 
        $Col.ColumnName = $property.Name.ToString() 
        if ($property.value) 
        { 
         if ($property.value -isnot [System.DBNull]) { 
          $Col.DataType = [System.Type]::GetType("$(Get-Type $property.TypeNameOfValue)") 
         } 
        } 
        $DT.Columns.Add($Col) 
       } 
       if ($property.Gettype().IsArray) { 
        $DR.Item($property.Name) =$property.value | ConvertTo-XML -AS String -NoTypeInformation -Depth 1 
       } 
       else { 
        $DR.Item($property.Name) = $property.value 
       } 
      } 
      $DT.Rows.Add($DR) 
      $First = $false 
     } 
    } 

    End 
    { 
     Write-Output @(,($dt)) 
    } 


$i = 1 


While ($i -le 211) { 

#Set the variable to the filename with the iteration number 
$filename = "c:\zMFM\z550Output\20dSummer\fixed20dSum550Output$i.csv" 


#Check to see if that a file with $filename exists. If not, skip to the next iteration of $i. If so, run the code to collect the statistics for each variable and output them each to a different file 
If (Test-Path $filename) { 


#Calculate the Standard Deviation 
#First get the average of the values in the column 
$STDEVInputFile = Import-CSV $filename 

#Find the average and count for column 'td' 
$STDEVAVG = $STDEVInputFile | Measure-Object td -Average | Select Count, Average 
$DevMath = 0 

# Sum the squares of the differences between the mean and each value in the array 
Foreach ($Y in $STDEVInputFile) { 
$DevMath += [math]::pow(($Y.Average - $STDEVAVG.Average), 2) 

#Divide by the number of samples minus one 
$STDEV = [Math]::sqrt($DevMath/($STDEVAVG.Count-1)) 

} 

#Calculate the basic statistics for column 'td' with the MEASURE-OBJECT cmdlet 
$STATS = Import-CSV $Filename | 
Measure-Object td -ave -max -min | 

#Export the statistics as a CSV 
Export-CSV -notype "c:\zMFM\z550Output\20dSummer\tempstats$i.csv" 


$GetColumns = Import-CSV $filename 

#Append the standard deviation variable to the statistics table and add the value 

$STATS2 = Import-CSV "c:\zMFM\z550Output\20dSummer\tempstats$i.csv" 

$StatsTable = Get-PSDrive | Out-DataTable 

#$colSTDDEV = New-Object System.Data.DataColumn StdDev,([double]) 
$colVZA = New-Object System.Data.DataColumn VZA,([double]) 
#$colVAZ = New-Object System.Data.DataColumn VAZ,([double]) 


$colVZA = $GetColumns[0].VZA 
#$colVAZ = $GetColumns[0].VAZ #COMMENTED FOR DEBUGGING 
#$colSTDDEV = $STDEV 

#$StatsTable.Columns.Add($colSTDDEV) #COMMENTED FOR DEBUGGING 
#$StatsTable[0].StdDev = $STDEV #COMMENTED FOR DEBUGGING 


$StatsTable.Columns.Add($colVZA) | 


#$StatsTable[0].VZA = $VZA 

#$StatsTable.Columns.Add($colVAZ) #COMMENTED FOR DEBUGGING 
#$StatsTable[0].VZA = $VAZ #COMMENTED FOR DEBUGGING 

#Export the $STATS file containing everything you need in the correct folder 



Export-CSV -notype "c:\zMFM\z550Output\20dSummer\20dSum550Statistics.csv" 

} 
$i++ 
} 
+1

你的代码看起来像你希望'Import-Csv'返回'System.Data.DataTable'给你。 – PetSerAl

+0

我的印象是,它确实......这是否意味着我需要创建一个DataTable来加载新列,将其导出为CSV,然后导入它以将新列附加到表中? – AggroCrag

回答

2

即使在$STATS2每个对象具有相同的属性,则$STATS2对象本身只是一个简单的数组,对象的非结构化列表 - 它没有一个Columns属性与Add()方法:

$STATS2.Colums.Add($colVZA) 
^ ^ ^
[array] |  | 
     $null | 
       this fails 

您可以从Import-Csv获取数组的数组在第一个对象数组在Out-DataTable sample在TechNet脚本库检查每个属性,像转换为DataTable对象(其列)

+0

这个视觉例子使问题非常清楚,谢谢你!如果我在Import-Csv之后和$ STATS2.Colums.Add($ colVZA)之前立即调用该函数,是否可以将该Out-Datatable函数实现为脚本? – AggroCrag

+0

是的,您可以,但请注意'$ colVZA'本身就是列名,没有数据会被添加到每一行。 –

+0

谢谢你的信息。但是,我继续使用代码行$ StatsTable = Get-PSDrive | Out-DataTable'直接放在声明'$ STATS2'的地方,输出CSV包含奇怪的列标题,并且没有包含我想要包含的列。奇怪的头文件** AllowDBNull,AutoIncrement,AutoIncrementSeed,.... **这是该函数的问题吗? – AggroCrag

相关问题