1
votes

Here is a short example (my actual code requires me to output many more tables during the function run, and get a single returned output from it):

Function Select-RowFromCSV ($CSV)
{
    $CSV
    return $CSV[(read-host "select row # from CSV")]
}

Instead of outputting $CSV within the function it gets appended to the return and is getting into the variable that the function inserted to.

PS C:\Windows\system32>  $ROW = Select-RowFromCSV -CSV (Import-Csv "C:\scripts\csv.csv")
select row # from CSV: 0

PS C:\Windows\system32> $ROW
Name         Phone                                                                                          

Dan         111111                                                                                         
Dave        5555555                                                                                        
Oliver      666666                                                                                         
Dan         111111                                                                                         

PS C:\Windows\system32> 

I tried multiple ways to try and print it to the screen, however unlike write-host that do work as expected for strings, none of the other one i tried works for non strings objects (FT, write-output, echo).

2
What about using Out-Gridview instead with the -passthru option to select rows? $ROW = Import-Csv "C:\scripts\csv.csv"|Out-GridView -PassThru user6811411

2 Answers

1
votes

If you want to output something to the console without affecting the output of the Function, Write-Host is probably the simplest solution (but is considered harmful). Your code needs to be as follows:

Function Select-RowFromCSV ($CSV)
{
    Write-Host ($CSV | Format-Table | Out-String)
    Return $CSV[(read-host "select row # from CSV")]
}

$ROW = Select-RowFromCSV -CSV (Import-Csv "raid.csv")

As you observed, because your object isn't a string you need to Format it as you'd like and then convert it to a String (| Format-Table | Out-String).

However, you might want to consider using Write-Verbose which will write output to the Verbose stream instead, only when the -Verbose switch is used. To use this you need to add [cmdletbinding()] and a Param() block to your function, like this:

Function Select-RowFromCSV 
{
    [cmdletbinding()]
    Param($CSV)

    Write-Verbose ($CSV | Format-Table | Out-String)
    Return $CSV[(read-host "select row # from CSV")-1]
}

Then execute your function with the -Verbose switch to see the extra output:

$ROW = Select-RowFromCSV -CSV (Import-Csv "raid.csv") -Verbose

Further Explanation:

In your original function you were outputting all of $CSV because it appeared on a line by itself, then also returning a row of it. The Return keyword is a little misleading in PowerShell, it doesn't define what is only returned, it just triggers the Function to immediately end and anything that has been output will go in to the output stream.

You should also note that the row number your user enters needs to start from 0, because Array indexes start from 0.

If you wanted the first row to be 1 rather than 0, you might want to do this:

$CSV[(read-host "select row # from CSV")-1]

You could also drop the Return keyword entirely as it's not necessary. If you want to be more explicit, I personally favour Write-Output.

0
votes

Just use the following method:

$counter = 0 
$table = @()
XXX | foreach-object {

    do something; 
    $table +=[pscustomobject]@ {
        XXXX
    }
   $table[$counter]
   $counter++
}