1

I'm building a script that will create an html report containing a table with multiple values in each Column Row (e.g. given cell may have 1 or more values). I'm building my output variable like this (assume there is a bunch of script before that is going to put data into all those variables):

I'm going to return the data generated here as part of a function call


$dlphashtable=[Ordered]@{
        Exchange = ($exchangemembers | Out-String).Trim()
        OneDriveUsers = ($onedrivemembers | Out-String).Trim()
        OneDriveGroups = ($onedrivesites | Out-String).Trim()
        SharePoint = ($sharepointlocations | Out-String).Trim()
        Teams = ($teamslocations | Out-String).Trim()
        Endpoints = ($endpointdlplocations | Out-String).Trim()
        DefenderforCA = ($defenderforCAlocations | Out-String).Trim()
        OnPremDLP = ($onpremlocations | Out-String).Trim()
    }

    $dlppolicydetailobject = [PSCustomObject]$dlphashtable
        
    return $dlppolicydetailobject

If I output this data to a csv, grid-view, or to the screen, each one of the items shows up on a new line as i want it to (and i'd expect). Grid View Output Image Excel Output Image

However if I convert the file to HTML then the table formats the text based on the width of the browser. View of converto-html output

How can I make the output so that each of the values in the HTML table show up on a new line in their appropriate column?

Jim842
  • 23
  • 2

1 Answers1

0

If your intent is to simply force line breaks between the multiple values represented in a single table cell, you must separate them with <br> HTML elements instead of literal newlines (which is what Out-String uses; literal newlines are not preserved as such in HTML rendering).

The challenge is that ConvertTo-Html automatically escapes the property values it puts into table cells, so that verbatim <br> turns into &lt;br&gt;. The workaround is to insert the <br> strings afterwards, and for that you can mark the places where it goes with a character you don't expect to be part of the values, a NUL ([char] 0x0), represented as "`0" as an expandable string is the ideal candidate:

# Note: No need for `return`: This both constructs and outputs
#       the custom object.
([pscustomobject] @{
  Exchange       = $exchangemembers -join "`0"
  OneDriveUsers  = $onedrivemembers -join "`0"
  OneDriveGroups = $onedrivesites -join "`0"
  SharePoint     = $sharepointlocations -join "`0"
  Teams          = $teamslocations -join "`0"
  Endpoints      = $endpointdlplocations -join "`0"
  DefenderforCA  = $defenderforCAlocations -join "`0"
  OnPremDLP      = $onpremlocations -join "`0"
} | ConvertTo-Html) -replace "`0", '<br>'

Original form of the answer, which applies to a different use case:

If you have multiple collections with corresponding elements and you want want to represent each set of corresponding elements in a separate table row, you need to construct multiple objects, with the properties of each containing one element from each input array:

# The list of all arrays.
$arrays = @(
  $exchangemembers,
  $onedrivemembers,
  $onedrivesites,
  $sharepointlocations,
  $teamslocations,
  $endpointdlplocations,
  $defenderforCAlocations,
  $onpremlocations
)

# Find the max. element count among all arrays.
$maxElemCount = ($arrays | ForEach-Object Count | Measure-Object -Maximum).Maximum

# Loop over all arrays and construct and output
# a [pscustomobject] for each set of corresponding elements.
foreach ($i in 0..($maxElemCount-1)) {
  [pscustomobject] @{
    Exchange       = $exchangemembers[$i]
    OneDriveUsers  = $onedrivemembers[$i]
    OneDriveGroups = $onedrivesites[$i]
    SharePoint     = $sharepointlocations[$i]
    Teams          = $teamslocations[$i]
    Endpoints      = $endpointdlplocations[$i]
    DefenderforCA  = $defenderforCAlocations[$i]
    OnPremDLP      = $onpremlocations[$i]
  }    
}

# Note: No `return` statement needed - the above loop
#       *implicitly* output all objects.
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Thanks for the pointer on this. Your path is pretty crisp, however this assumes that each column has an equal number of properties and and that they are all related if you go across the role. What i ended up doing was similar here [link]https://community.spiceworks.com/topic/851119-convertto-html-carriage-return-in-cells. I'm still testing but i think what i'll end up doing is join the values together and then split them out when i do the convertto-html portion. will share when i solve it. – Jim842 Aug 06 '22 at 20:00
  • @Jim842, please see my update. – mklement0 Aug 07 '22 at 19:04