Reputation: 65
I'm trying to do some checks when loading a CSV and inform the user of what extra headers were found and which ones are still missing. $headers_required will be hardcoded, $headers_loaded will be populated by Import-CSV The goal is to populate the two arrays with the differences from the other array, like diff in Unix.
$headers_required=@( `
'Path', `
'GivenName', `
'Name', `
'EmailAddress', `
'sAMAccountName', `
'psw-temp', `
'Path', `
'ChangePasswordAtLogon' `
)
$headers_loaded=@( `
'Path', `
'GivenName', `
'Name', `
'PhoneNumber', `
'PreferredFilm', `
'sAMAccountName', `
'psw-temp', `
'Path', `
'ChangePasswordAtLogon', `
'BankAccount' `
)
Eventually I would like to have
$extra_headers_not_nedeed=@('BankAccount', 'PhoneNumber', 'PreferredFilm')
$missing_headers=@('EmailAddress')
I can filter them in this way
$extra_headers_not_nedeed=Compare-Object ($headers_required|Sort-Object) ($headers_loaded|Sort-Object) | Where SideIndicator -eq '<='
$missing_headers=Compare-Object ($headers_required|Sort-Object) ($headers_loaded|Sort-Object) | Where SideIndicator -eq '=>'
And I do filter them
PS C:\> $missing_headers|Write-host
@{InputObject=EmailAddress; SideIndicator=<=}
PS C:\> $extra_headers_not_needed|Write-host
@{InputObject=BankAccount; SideIndicator==>}
@{InputObject=PhoneNumber; SideIndicator==>}
@{InputObject=PreferedFilm; SideIndicator==>}
how can I get normal arrays as specified above instead of a structured object? I tried $missing_headers['InputObject'] but it returns the whole object instead of 'EmailAddress'
is a there a more compact way (aside symbols) to get to the same result?
TIA
Upvotes: 1
Views: 121
Reputation: 60035
I would use a function
that you can re-use and can dynamically assign new reference headers to compare with your Csv.
I wouldn't use Compare-Object
personally, I think it takes all the fun away.
function Test-Csv {
param(
[parameter(mandatory)]
[string[]]$ReferenceHeaders,
[parameter(mandatory)]
[object]$InputObject
)
$csvHeaders = $InputObject[0].PSObject.Properties.Name
$valid, $missing = $ReferenceHeaders.where({ $_ -in $csvHeaders }, 'Split')
$invalid = $csvHeaders.where({ $_ -notin $ReferenceHeaders })
$valid.foreach({
[pscustomobject]@{
HeaderName = $_
Status = 'Valid'
}
})
$missing.foreach({
[pscustomobject]@{
HeaderName = $_
Status = 'Missing'
}
})
$invalid.foreach({
[pscustomobject]@{
HeaderName = $_
Status = 'Invalid'
}
})
}
Usage
# Define the Reference Headers
$requiredHeaders =@(
'Path'
'GivenName'
'Name'
'EmailAddress'
'sAMAccountName'
'psw-temp'
'ChangePasswordAtLogon'
)
# This example Csv would be the one you import from a file as an example
$exampleCsv = @'
GivenName,sAMAccountName,RandomHeader1,Path,RandomHeader2
z,z,z,z,z
'@ | ConvertFrom-Csv
PS \> Test-Csv -ReferenceHeaders $requiredHeaders -InputObject $exampleCsv
HeaderName Status
---------- ------
Path Valid
GivenName Valid
sAMAccountName Valid
Name Missing
EmailAddress Missing
psw-temp Missing
ChangePasswordAtLogon Missing
RandomHeader1 Invalid
RandomHeader2 Invalid
PS \> $result = Test-Csv -ReferenceHeaders $requiredHeaders -InputObject $exampleCsv
PS \> $result | Where-Object Status -EQ 'Missing'
HeaderName Status
---------- ------
Name Missing
EmailAddress Missing
psw-temp Missing
ChangePasswordAtLogon Missing
PS \> $result | Where-Object Status -EQ 'Invalid'
HeaderName Status
---------- ------
RandomHeader1 Invalid
RandomHeader2 Invalid
Upvotes: 2
Reputation: 3158
Just another option:
Clear-Host
$Extra_Headers_Not_Needed = New-Object -TypeName 'System.Collections.ArrayList'
$Missing_Headers = New-Object -TypeName 'System.Collections.ArrayList'
$x = Compare-Object ($headers_required|Sort-Object) ($headers_loaded|Sort-Object)
ForEach ( $header in $x) {
Switch (($Header).SideIndicator) {
'=>' {$Null = $Extra_Headers_Not_Needed.Add($Header.InputObject) ; Break}
'<=' {$Null = $Missing_Headers.Add($Header.InputObject) ; Break}
Default {"Error: $($Header.InputObject)" }
}
}
"Not Needed $($Extra_Headers_Not_Needed.Count) :"
$Extra_Headers_Not_Needed
"`nMissing Headers $($Missing_Headers.Count) :"
$Missing_Headers
Output:
Not Needed 3 :
BankAccount
PhoneNumber
PreferredFilm
Missing Headers 1 :
EmailAddress
Upvotes: 2
Reputation: 65
Thanks Zdan and Santiago,
eventually I found this way too (from the a[key]='value' concept)
PS C:\> $missing_headers.'InputObject'
BankAccount
PhoneNumber
PreferredFilm
PS C:\> $extra_headers_not_nedeed.'InputObject'
EmailAddress
Because of
PS C:> $extra_headers_not_nedeed.psobject.properties
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : EmailAddress
TypeNameOfValue : System.String
Name : InputObject
IsInstance : True
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : <=
TypeNameOfValue : System.String
Name : SideIndicator
IsInstance : True
Upvotes: 0
Reputation: 29450
Add the -PassThru
argument to the compare-object
command:
# ~> $extra_headers_not_nedeed=Compare-Object ($headers_required|Sort-Object) ($headers_loaded|Sort-Object) -passthru| Where SideIndicator -eq '<='
# ~> $extra_headers_not_nedeed
EmailAddress
# ~> $missing_headers=Compare-Object ($headers_required|Sort-Object) ($headers_loaded|Sort-Object) -PassThru | Where SideIndicator -eq '=>'
# ~> $missing_headers
BankAccount
PhoneNumber
PreferredFilm
Upvotes: 2