0

am outputting my powershell objects in HTML format but I want the individual columns to be aligned as

First  Column : Left Aligned
Second Column : Center Aligned
Third Column  : Right Aligned

Here's my code : I want the solution in Powershell.

$Body = ""
$format= "<style>"
$format= $format+ "BODY{background-color:LightYellow;}"
$format= $format+ "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$format= $format+ "TH{border-width: 2px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
$format= $format+ "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}"
$format= $format+ "</style>"

$body += "<b>USAGE REPORT</b>"
$body += "<br><br>"
$outputf =$arr | select "NAME" , server, "USEDSPACE %"    |Sort-Object -Property "USEDSPACE %" -Descending
$body += $outputf | ConvertTo-Html -head $format
$body += "<BR>"

I have tried text-align: left in TD but it aligns all to left side.

I am sending out this as a mail report and viewing on Outlook mail client.

Send-MailMessage -From abc@xyz.com -to fgh@cat.com -Subject "USAGE REPORT" -BodyAsHtml $body -SmtpServer $smtpserver
Matt
  • 45,022
  • 8
  • 78
  • 119
Fenomatik
  • 457
  • 2
  • 8
  • 22
  • 2
    Presumably, [you can use a `td:nth-child(n)` selector](http://stackoverflow.com/questions/15675097/style-the-first-td-column-of-a-table-differently). However, your script as written here is going to generate an invalid document. `CovertTo-Html` by default returns a whole HTML document, including headers. You shouldn't be wrapping an HTML document in HTML tags. Your browser might render it, but it's certainly not correct. I suggest using `ConvertTo-Html -Fragment`. – Bacon Bits Feb 19 '16 at 19:11
  • @BaconBits You think it should look like this ? "TD:nth-child(1){text-align: left;border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}" – Fenomatik Feb 19 '16 at 19:22
  • 1
    I would have it be: `$format= $format+ "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}"; $format= $format+ "TD:first-child{text-align: left;}";$format= $format+ "TD:nth-child(2){text-align: center;}";$format= $format+ "TD:nth-child(3){text-align: right;}";`. However, it's been about 10 years since I've worked with CSS. – Bacon Bits Feb 19 '16 at 19:27
  • @BaconBits Seems like its not working and taking the last text-align only and applying to all the columns – Fenomatik Feb 19 '16 at 19:44
  • Not all browsers and applications render nth Child style. What are you viewing the content on? Versions of Outlook for example wont render this. Up to date chrome should. – Matt Feb 19 '16 at 20:27
  • @Matt , I am sending out this as a mail report and viewing on outlook mail client. Using this Send-MailMessage -From abc@xyz.com -to fgh@cat.com -Subject "USAGE REPORT" -BodyAsHtml $body -SmtpServer $smtpserver – Fenomatik Feb 19 '16 at 20:39
  • You are going to have different issues depending on what you do here. nthchild does not work in my Outlook 2010 and I don't think it has changed with other versions. You should be using -Fragment but you cant use -Head if you do. The mail can still be created with -Head and -BodyAsHTML but it is not a good practice. You can look and create the rows individually but I don't know how well received that will be. – Matt Feb 19 '16 at 21:01

2 Answers2

2

You were correct with using text-align: left. However you cannot apply that style to all TD elements. You will need to apply that style to the first column, and then apply text-align: center and text-align: right to the second and third columns, respectively.

See this jsfiddle.

This can then be used in conjunction with multiple nth-child selectors to produce the desired output. Sidenote, using a here-string for your format can make it easier to setup, thus you will not need to use string concatenation.

$format = @"
<style>
  body {
    background-color: lightyellow;
  }
  table {
    border: 1px solid black;
    border-collapse: collapse;
  }
  th {
    border: 2px solid black;
    padding: 0px;
    background-color: thistle;
  }
  td {
    border: 1px solid black;
    padding: 5px;
    background-color: palegoldenrod
  }
  td:nth-child(1) {
    text-align: left;
  }
  td:nth-child(2) {
    text-align: center;
  }
  td:nth-child(3) {
    text-align: right;
  }
</style>
"@

$arr | select "NAME", server, "USEDSPACE %" | Sort-Object -Property "USEDSPACE %" -Descending | ConvertTo-Html -Head $format -PreContent "<b>USAGE REPORT</b><br><br>" -PostContent "<br>"
Cobster
  • 1,243
  • 10
  • 18
  • Should it look like this ? '$format= $format+ "TD{text-align: left;border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}" $format= $format+ "TD{text-align: center;border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}" $format= $format+ "TD{text-align: right;border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}"' – Fenomatik Feb 19 '16 at 19:16
  • @bacon is correct with his second comment. You need to define additional TD styles that further refine the style of the cells using the TD.nth-child selectors. – Cobster Feb 19 '16 at 19:32
  • Seems like its not working either its taking the last text-align only and applying to all the columns – Fenomatik Feb 19 '16 at 19:48
2

If you are doing to be viewing this mail in the Outlook client you should know that CSS support is very limited. Like Cobster and other comments are suggesting nth:child css style is the way to go for this in a general sense but that does no good where Outlook is concerned. It will not render td:nth-child. Also it is not a good practice to insert a complete html document as a body for an email. It does work however. You should be using -Fragment but you lose your $style. If you can accept those caveats this will work fine (minus the alignment in Outlook). It would display fine in a modern browser.

$head = @"
<style>
    body{background-color:LightYellow;}
    table{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
    th{border-width: 2px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}
    td{border-width: 1px;padding: 5px;border-style: solid;border-color: black;background-color:palegoldenrod}
    td:nth-child(1){text-align: left}
    td:nth-child(2){text-align: center}
    td:nth-child(3){text-align: right}
</style>
"@

# Output for -Body must be a single string.
$html = Get-ChildItem c:\temp | Select-Object name,lastwritetime,length | ConvertTo-Html -Head $head | Out-String
Send-MailMessage -From abc@xyz.com -to fgh@cat.com -Subject "USAGE REPORT" -BodyAsHtml $body -SmtpServer $smtpserver

I use output from Get-ChildItem here for the "report".


Still though you do want this to open in Outlook so I would like to continue with this. It is a relatively dirty solution as most would cower at the approach. This is only meant to work in Outlook mail client. I am only doing it this way to show you how you can get the alignment you are looking for. I am sure there is room for improvement here. Basically we build the <table> ourselves and add it to the SMTP mail.

# Start the body with the open tag for table and its style.
$body = @("<table cellspacing=1; cellpadding=5>")
# Define the style used for the table header
$headerStyle = 'bgcolor="d8bfd8"'
# Using an array store the unique attributes for the 1st,2nd and 3rd columns
$columnStyles = 'align="left"', 'align="center"', 'align="right"'
# Style shared/used by every element in each row.
$rowDataStyle = 'bgcolor="#EEE8AA"'
# Build the header row using the template. Since there is repetiion the format operator cleans up the code nicely.
$header = "<tr><th {0}>Name</th><th {0}>LastWriteTime</th><th {0}>length</th></tr>" -f $headerStyle
# Template used to build each row using the input object.
$htmlRowTemplate = "<tr><td {0};{1}>{2}</td><td {0};{3}>{4}</td><td {0};{5}>{6}</td></tr>"

# Build the table rows
$tableData = Get-ChildItem "c:\temp" | Select-Object name,lastwritetime,length | ForEach-Object{
    # Use the format operator and the template to create the row in HTML
    $htmlRowTemplate -f $rowDataStyle,
         $columnStyles[0], $_.Name,
         $columnStyles[1], $_.lastwritetime,
         $columnStyles[2], $_.length
}

#Build the body. Which is just an html table.
$body = $body + $header + $tableData + "</table>" |  Out-String

Send-MailMessage -From abc@xyz.com -to fgh@cat.com -Subject "USAGE REPORT" -BodyAsHtml $body -SmtpServer $smtpserver

To try and save on space I made large use of the -f Format operator here which you can read up on. Here is the mail I generated from the above code in my Outlook 2010 Client (using my own smtp settings of course):

table in mail client

You will notice that your style is not perfectly replicated. You should be able to make your own changes as you need.

Matt
  • 45,022
  • 8
  • 78
  • 119