Предполагая, что ваш пример выходной таблицы является результатом массива объектов PSO:
$data = [PsCustomObject]@{ Count = 1; Name = 'Cisco Spark Room 55, NetworkAddressMissing'},
[PsCustomObject]@{ Count = 1; Name = 'Cisco Spark Room 55, OK'},
[PsCustomObject]@{ Count = 2; Name = 'Cisco Spark Room Kit, NetworkAddressMissing'},
[PsCustomObject]@{ Count = 2; Name = 'Cisco TelePresence DX80, NetworkAddressMissing'},
[PsCustomObject]@{ Count = 1; Name = 'Cisco TelePresence DX80, NoHTTPSResponse'},
[PsCustomObject]@{ Count = 4; Name = 'Cisco TelePresence DX80, OK'},
[PsCustomObject]@{ Count = 10; Name = 'Cisco TelePresence MX200 G2, OK'},
[PsCustomObject]@{ Count = 11; Name = 'Cisco TelePresence MX200, OK'},
[PsCustomObject]@{ Count = 3; Name = 'Cisco TelePresence MX300 G2, NoHTTPSResponse'},
[PsCustomObject]@{ Count = 48; Name = 'Cisco TelePresence MX300 G2, OK'},
[PsCustomObject]@{ Count = 6; Name = 'Cisco TelePresence MX300, OK'},
[PsCustomObject]@{ Count = 3; Name = 'Cisco TelePresence Profile 52/55 C40, NetworkAddressMissing'}
И вам нужна пустая строка между сгруппированными элементами, это может помочь:
# show headers on the first iteration only
$hideHeaders = $false
$data | Group-Object @{ Expression = {($_.Name -split ',')[0]}} | ForEach-Object {
($_.Group | Format-Table -AutoSize -HideTableHeaders:$hideHeaders | Out-String).TrimEnd()
$hideHeaders = $true
}
Вывод:
Count Name
----- ----
1 Cisco Spark Room 55, NetworkAddressMissing
1 Cisco Spark Room 55, OK
2 Cisco Spark Room Kit, NetworkAddressMissing
2 Cisco TelePresence DX80, NetworkAddressMissing
1 Cisco TelePresence DX80, NoHTTPSResponse
4 Cisco TelePresence DX80, OK
10 Cisco TelePresence MX200 G2, OK
11 Cisco TelePresence MX200, OK
3 Cisco TelePresence MX300 G2, NoHTTPSResponse
48 Cisco TelePresence MX300 G2, OK
6 Cisco TelePresence MX300, OK
3 Cisco TelePresence Profile 52/55 C40, NetworkAddressMissing
Перечитывая вопрос, я понимаю, что вывод вашей таблицы должен / мог бы быть HTML.
В этом случае, возможно, может пригодиться функция, представленная ниже:
$style = @"
<style type="text/css">
body {
font-family: Calibri, Verdana, Arial, Geneva, Helvetica, sans-serif;
font-size: 11pt;
color: black;
}
table, td, th {
border-style: solid;
font-family: Calibri, Verdana, Arial, Geneva, Helvetica, sans-serif;
font-size: 11pt;
margin: 8pt 0 8pt 0;
}
table {
border-width: 0 0 1px 1px;
border-spacing: 0;
border-collapse: collapse;
}
td, th {
margin: 0;
padding: 4px;
border-width: 1px 1px 0 0;
text-align: left;
}
th {
color: white;
font-weight: bold;
}
</style>
"@
# HTML start
$openHtml = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Report</title>
<meta name="generator" content="PowerShell" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
$style
</head>
<body>
"@
# HTML close
$closeHtml = '</body></html>'
function ConvertTo-HTMLTable {
# Converts an object to a themed HTML table, mimicking the Excel "Table Style Normal"
# Accepts a System.Data.DataTable object or an array of PSObjects and converts to styled HTML table
[CmdletBinding(DefaultParameterSetName = 'ByTheme')]
Param (
[parameter(Mandatory = $true, Position = 0)]
[object[]]$Data,
[parameter(ParameterSetName = 'ByTheme')]
[ValidateSet('Black', 'LightBlue', 'Orange', 'Gray', 'Gold', 'Blue', 'Green')]
[string]$ThemeColor,
[parameter(ParameterSetName = 'ByCustomColors')]
[string]$HeaderColor,
[parameter(ParameterSetName = 'ByCustomColors')]
[string]$OddRowColor,
[parameter(ParameterSetName = 'ByCustomColors')]
[string]$EvenRowColor,
[parameter(ParameterSetName = 'ByCustomColors')]
[string]$BorderColor
)
# add type needed to replace HTML special characters into entities
Add-Type -AssemblyName System.Web
# define theme colors as array of hashtables
$colors = switch($ThemeColor) {
'Black' { @{ 'header' = '#D9D9D9'; 'oddrow' = '#000000'; 'evenrow' = $null; 'border' = '#000000'} }
'LightBlue' { @{ 'header' = '#5B9BD5'; 'oddrow' = '#DDEBF7'; 'evenrow' = $null; 'border' = '#000000'} }
'Orange' { @{ 'header' = '#ED7D31'; 'oddrow' = '#FCE4D6'; 'evenrow' = $null; 'border' = '#F4B084'} }
'Gray' { @{ 'header' = '#A5A5A5'; 'oddrow' = '#EDEDED'; 'evenrow' = $null; 'border' = '#C9C9C9'} }
'Gold' { @{ 'header' = '#FFC000'; 'oddrow' = '#FFF2CC'; 'evenrow' = $null; 'border' = '#FFD966'} }
'Blue' { @{ 'header' = '#4472C4'; 'oddrow' = '#D9E1F2'; 'evenrow' = $null; 'border' = '#8EA9DB'} }
'Green' { @{ 'header' = '#70AD47'; 'oddrow' = '#E2EFDA'; 'evenrow' = $null; 'border' = '#A9D08E'} }
default { @{ 'header' = $HeaderColor; 'oddrow' = $OddRowColor; 'evenrow' = $EvenRowColor; 'border' = $BorderColor} }
}
$sb = New-Object -TypeName System.Text.StringBuilder
[void]$sb.AppendLine('<table style="border-color: {0};">' -f $colors['border'])
if ($null -ne $Data) {
if (([object]$Data).GetType().FullName -eq 'System.Data.DataTable'){
# it is a DataTable; convert to array of PSObjects
$Data = $Data | Select-Object * -ExcludeProperty ItemArray, Table, RowError, RowState, HasErrors
}
$headers = $Data[0].PSObject.Properties | Select -ExpandProperty Name
[void]$sb.AppendLine(('<thead><tr style="background-color: {0};">' -f $colors['header']))
foreach ($column in $headers) {
$th = [System.Web.HttpUtility]::HtmlEncode($column)
[void]$sb.AppendFormat('<th style="border-color: {0};">{1}</th>', $colors['border'], $th)
}
[void]$sb.AppendLine('</tr></thead><tbody>')
$currentName = $Data[0].Name
$rowcolor = $colors['evenrow']
$Data | ForEach-Object {
# add inline style for different colored rows on each Name change
if ($_.Name -ne $currentName) {
if ($rowcolor -eq $colors['evenrow']) {
$rowcolor = $colors['oddrow']
}
else {
$rowcolor = $colors['evenrow']
}
$currentName = $_.Name
}
if ([string]::IsNullOrWhiteSpace($rowcolor)) {
$tr = '<tr>'
}
else {
$tr = '<tr style="background-color: {0};">' -f $rowcolor
}
[void]$sb.AppendLine($tr)
# now add the data cells
foreach ($column in $headers) {
[string]$val = $($_.$column)
if ([string]::IsNullOrWhiteSpace($val)) {
$td = '<td style="border-color: {0};"> </td>' -f $colors['border']
}
else {
# if it's a number, align to the right
[double]$num = 0
if ([double]::TryParse($val,[ref]$num)) {
$td = '<td style="border-color: {0}; text-align: right;">{1}</td>' -f $colors['border'], $val
}
else {
$val = [System.Web.HttpUtility]::HtmlEncode($val)
$td = '<td style="border-color: {0};">{1}</td>' -f $colors['border'], $val
}
}
[void]$sb.Append($td)
}
[void]$sb.AppendLine('</tr>')
}
[void]$sb.AppendLine('</tbody>')
}
[void]$sb.AppendLine('</table>')
return $sb.ToString()
}
Имея все это на своем месте, вы можете преобразовать свои исходные данные (опять же: я предполагаю, что это массив PSObjects ) примерно так:
# split the Name property into Name and Status and update the objects
$data | ForEach-Object {
$name, $status = ($_.Name -split ',', 2).Trim()
$_.Name = $name
$_ | Add-Member -MemberType NoteProperty -Name 'Status' -Value $status
}
# convert the data to styled HTML table
$table = ConvertTo-HTMLTable -Data ($data | Sort-Object Name) -ThemeColor Blue
# complete the HTML
$html = '{0}{1}{2}' -f $openHtml, $table, $closeHtml
Далее вы можете сохранить его как html file
$html | Set-Content -Path 'D:\report.html'
Или использовать Send-MailMessage , чтобы отправить его как приятное письмо вашим коллегам.
Синяя тема дает вам этот вывод