0

I would like to be able to change this string:

$Result
Header 1,Text 1,Text 11,,,,,
Header 2,Text 2,Text 22,,,,,
Header 3,Text 3,Text 33,,,,,
Header 4,,Text 44,,,,,

In to this string:

$Result
Header 1,Header 2,Header 3,Header 4
Text 1,Text 2,Text 3,,
Text 11,Text 22,Text 33,Text 44

I managed to do this when it only concerns one header and one text item. But I can't figure out how to do this dynamically, in case I don't know how many text items will follow. This string will then be imported by ConvertFrom-Csv for later use.

My current code which works for one header and one text item:

$Result | ForEach-Object {$Header += "$($_.Split(',')[0]),"; $Content += "$($_.Split(',')[1]),"}
$Result = "$Header`n$Content"

Solution, thanks to the guys below:

Function ConvertTo-ReverseCSV {
    [CmdletBinding(SupportsShouldProcess=$True)]
    Param (
        [parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true)]
        [ValidateNotNullOrEmpty()]
        [String] $String
    )

    PROCESS {
        $StringMax = 0
        $h = @()

        $String.split("`n") | % {
            $a = $_.split(",")
            $h += ,$a
            if($a.length -gt $StringMax) { $StringMax = $a.length }
        }

        for($j = 0; $j -lt $StringMax; $j++) {
            for($i = 0; $i -lt $h.length; $i++) {
                $Result += "$($h[$i].split("`n")[$j]),"
            }
            $Result +="`n"
        }
        Write-Output $Result
    }
}
DarkLite1
  • 13,637
  • 40
  • 117
  • 214
  • This should be helpful: http://stackoverflow.com/questions/1736613/how-to-transpose-data-in-powershell – Piotr Stapp Aug 19 '14 at 14:04
  • Thx for the tip Garath, but it's collecting everything under the same header being `Header 1`. I'm not quite skilled enough yet to solve this. – DarkLite1 Aug 19 '14 at 14:13

2 Answers2

2

I think the below will do the transformation you require:

$r = @'
Header 1,Text 1,Text 11,,,,,
Header 2,Text 2,Text 22,,,,,
Header 3,Text 3,Text 33,,,,,
'@

$rmax = 0
$h = @()

$r.split("`n") | % {
    $a = $_.split(",")
    $h += ,$a
    if($a.length -gt $rmax) { $rmax = $a.length }
}

for($j = 0; $j -lt $rmax; $j++) {
    for($i = 0; $i -lt $h.length; $i++) {
        write-host -nonewline "$($h[$i].split("`n")[$j]),"
    }
    write-host ""
}

You can tidy it up into a function if it works for you.

arco444
  • 22,002
  • 12
  • 63
  • 67
  • Thank you arco444, this is indeed working out great! Is there a way to also remove the empty lines between the results? – DarkLite1 Aug 19 '14 at 14:23
  • Perfect, thank you! Is there a way to save it in a variable? Need to figure that one out.. – DarkLite1 Aug 20 '14 at 06:50
  • Found it :) Had to change this `$Result += "$($h[$i].split("`n")[$j]),"` and `$Result +="`n"` and add after the loop `Write-Output $Result`. Update the OP with the full solution. Thank you again arco444, this helped me a lot. – DarkLite1 Aug 20 '14 at 08:13
  • No problem, happy you got it sorted. – arco444 Aug 20 '14 at 09:26
0

Looks like a matrix transpose problem. You could try something like this:

C:\PS> $data = @()
C:\PS> @'
>>> Header 1,Text 1,Text 11,Text 111
>>> Header 2,Text 2,Text 22,Text 222
>>> Header 3,Text 3,Text 33,Text 333
>>> '@ -split "`n" | Foreach {$data += ,($_ -split ',')}
C:\PS> $trans = new-object object[] -arg $data[0].length
C:\PS> for ($i=0;$i -lt $trans.length;$i++) { $trans[$i] = new-object string[] $data.length }
C:\PS> for ($i=0;$i -lt $data.Length; $i++) {
>>>     for ($j=0;$j -lt $data[0].Length; $j++) {
>>>         $trans[$j][$i] = $data[$i][$j]
>>>     }
>>> }
C:\PS> $trans
Header 1
Header 2
Header 3
Text 1
Text 2
Text 3
Text 11
Text 22
Text 33
Text 111
Text 222
Text 333
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • Thank you Keith, but I really need it in the comma format way. So I'm able to import it as a CSV later on. – DarkLite1 Aug 20 '14 at 06:40