private/Write-Table.ps1

function Write-Table{
    [CmdletBinding()]
    param (
        [string]$title,
        $columns,
        $values
    )

    Write-Output ''
    if ($title){
        Write-Output $title
        Write-Output ''
    }

    # determine size of the columns
    $_size = @()
    foreach($_col in $columns) {
        $_size += $_col.Length
    }
    foreach ($key in $values.keys) {
        for($i=0; $i -lt $values[$key].Count; $i++){
            if (($values[$key][$i].Length + 1) -gt $_size[$i]){
                $_size[$i] = $values[$key][$i].Length + 1
            }
        }
    }

    #compose header and sub header
    $_header = $null
    $_subheader = $null
    for($i=0; $i -lt $columns.Count; $i++) {
        $_col = $columns[$i]

        if (-not $_header){
            $_header = $_col.PadLeft($_size[$i], ' ')
            $_subheader = ''.PadLeft($_size[$i], '-')
        }
        else {
            $_header += ' ' + $_col.PadLeft($_size[$i], ' ')
            $_subheader += ' ' + ''.PadLeft($_size[$i], '-')
        }
    }
    Write-Output $_header
    Write-Output $_subheader

    #compose lines
    $_out = $null;
    foreach ($key in $values.keys) {
        for($i=0; $i -lt $values[$key].Count; $i++){
            if (-not $_out){
                $_out = ([string]$values[$key][$i]).PadLeft($_size[$i], ' ')
            }
            else{
                $_out += ([string]$values[$key][$i]).PadLeft($_size[$i] + 1, ' ')
            }
        }
        Write-Output $_out
        $_out = $null
    }
}