This powershell script takes up to 8 rows in a csv file and combines them into one row by duplicating the columns, and then saving in a result file (the first result file saved fine). If there are 16 rows in the csv it is meant to save a second result file etc.
eg in rows.csv:
first_field second_field third_field fourth_field
ball bat racket club
orange banana mango pear
In result1.csv:
first1 second1 third1 fourth1 first2 second2 third2 fourth2
ball bat racket club orange banana mango pear
I get an error:
New-Object : Cannot convert 'System.Object[]' to the type 'System.Collections.IDictionary' required by parameter 'Property'. Specified method is not supported.
At C:csv.ps1:19 char:42
+ $results = New-Object PSObject -Property $details
+ ~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand
Note that the first new-object creation worked ok on line 16. In Powershell ISE if I rerun the script it errors on line 16 too. I have no idea what is wrong here but assume I need to destroy the PSObject after saving each csv file?
$csvObjects = import-csv C:\rows.csv
$results = @()
$counter=1
foreach ($item in $csvObjects){
$detailsnew = [ordered] @{
"first$counter" = $item.'First_field'
"second$counter" = $item.'Second_field'
"third$counter" = $item.'Third_field'
"fourth$counter" = $item.'Fourth_field'
}
$details += $detailsnew
# modulus comparison returns remainder - write out file every 8
if ($counter % 8 -eq 0) {
if ($counter -eq 8) {
#works on line below on first run but fails on subsequent runs within Powershell ISE
$results = New-Object PSObject -Property $details
}
if ($counter -eq 16) {
# fails on line below
$results2 = New-Object PSObject -Property $details
}
$quotient = $counter / 8
$results | export-csv -Path c:\result"$quotient".csv -noType
$details = @()
$results = @()
}
$counter++
}
#write out final file if number not divisible by 8
if (-not($counter % 8 -eq 0)) {
$results += New-Object PSObjectF -Property $details
$modulo = $counter % 8
$quotient_plus1 = (($counter-$modulo) / 8) +1
$results | export-csv -Path C:\result"$quotient_plus1".csv -noType
}
tl;dr
$details = @()
should be $details = [ordered] @{}
To also make repeated executions from the ISE work as intended, place another $details = [ordered] @{}
statement before the loop.
In the very first loop iteration, $details
is initially undefined , and $details += $detailsnew
assigns the $detailsnew
(ordered) hash table (an [ordered] @{... }
hash table in PowerShell is of type System.Collections.Specialized.OrderedDictionary
) as-is to $details
(that is, with $details
undefined, +=
effectively behaves the same as =
).
The $detailsnew
hash tables created in the next 7 iterations are then merged by +=
into the hash table already stored in $details
.
After the 8th iteration, you mistakenly (re-)initialize $details
as an array ( @()
), which is the source of the problem: subsequent use of +=
then adds a new array element to $details
instead of merging the hash table entries, and passing an array rather than a hash table (or any dictionary type that implements System.Collections.IDictionary
) to New-Object
's -Property
parameter then - predictably - fails.
$details
as an ordered hash table: $details = [ordered] @{}
In Powershell ISE if I rerun the script it errors on line 16 too.
The PowerShell ISE dot-sources the scripts it runs , which means that variables from previous invocations can linger .
As an aside: This equally applies to Visual Studio Code with its PowerShell extension , which you should consider migrating to [1] . However, there you can opt to create a new, temporary session instead , as described in the bottom section of this answer .
In your case, this means that $details
already is an array in the very first iteration when you re-execute the script in the ISE.
[1] The PowerShell ISE is no longer actively developed and there are reasons not to use it (bottom section).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.