Search code examples
htmlpowershellloopsconverters

Powershell: convert ForEach loop results into an HTML table


I wrote a code for Azure subscription cost calculation based on two Tags (In this case Application tag and Owner tag), that are used in our environment.

$ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
$ApplicationTagLoop = @(Foreach ($ApplicationTag in $ApplicationTags) {
    $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate 
    (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
    $ApplicationTag}
    $SumForApplicationTag = 0
    $TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
    $TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
    Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur" 
        $OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
        ForEach ($OwnerTag in $OwnerTags) {
        $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) - 
        EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
        $ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
        $SumForOwner = 0
        $TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
        $TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
        ConvertTo-HTML -Body "Application tag: $ApplicationTag 'Owner: $OwnerTag Cost: 
        $([int]$SumForOwner) Eu." -Title "Cost of subscriptions" | Out-File c:\example.html
        Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
    }
})

Output of this PS code is:

Application tag is Testing. Sum for the tag is: 25 Eur
Owner is - [email protected] Sum for the owner is: 15 Eur
Owner is - [email protected] Sum for the owner is: 10 Eur
Application tag is Testing 2. Sum for the tag is: 100 Eur
Owner is - [email protected] Sum for the owner is: 40 Eur
Owner is - [email protected] Sum for the owner is: 40 Eur
Owner is - [email protected] Sum for the owner is: 20Eur 

...and so on...

Now I need to stream this output to an HTML table somehow, I tried doing that with ConvertTo-HTML command but it keeps rewriting itself with the last output and does not populate the table in any way. I also tried to make ForEach loops into arrays like so: $ApplicationTagLoop = @(foreach ($i in $ApplicationTag) And using that with Convert-To-HTML, but doing it this way $ApplicationTagLoop does not provide any results at all, so nothing is converted to HTML.

How could I rewrite the ConvertTo-HTML part so that every output of the loop would be saved into a new line of the HTML file?

Desired output format should be: https://i.sstatic.net/z13SM.png


Solution

  • Viewing the code, i guess the expected oputput.

    Use object collection build to get proper HTML :

    $ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
    $html = [System.Collections.ArrayList]@()
    Foreach ($ApplicationTag in $ApplicationTags) {
        $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate 
        (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
        $ApplicationTag}
        $SumForApplicationTag = 0
        $TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
        $TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
        Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur" 
            $OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
            ForEach ($OwnerTag in $OwnerTags) {
               $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) - 
               EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
                 $ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
               $SumForOwner = 0
               $TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
               $TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
               #ConvertTo-HTML -Body "Application tag: $ApplicationTag 'Owner: $OwnerTag Cost:         
                   #$([int]$SumForOwner) Eu." -Title "Cost of subscriptions" | Out-File c:\example.html
               $html.Add((Select-Object @{n='Application tag';e={$ApplicationTag}},@{n='Owner';e={$OwnerTag}},@{n='Cost';e={[string]$([int]$SumForOwner)+" Eu."}} -InputObject ''))
               Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
        }
    }; $html |  ConvertTo-Html -As Table -Title "Cost of subscriptions"  | Out-File c:\example.html
    

    Which should render the following HTML :

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Cost of subscriptions</title>
    </head><body>
    <table>
    <colgroup><col/><col/><col/></colgroup>
    <tr><th>Application tag</th><th>Owner</th><th>Cost</th></tr>
    <tr><td>Testing</td><td>[email protected]</td><td>15 Eu</td></tr>
    <tr><td>Testing</td><td>[email protected]</td><td>10 Eu</td></tr>
    <tr><td>Testing 2</td><td>[email protected]</td><td>40 Eu</td></tr>
    <tr><td>Testing 2</td><td>[email protected]</td><td>40 Eu</td></tr>
    <tr><td>Testing 2</td><td>[email protected]</td><td>20 Eu</td></tr>
    </table>
    </body></html>
    

    enter image description here

    Second edit as OP required a new formatted output, we're using a hash to break by application tag and format the output accordingly.

    $ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
    $html = [System.Collections.ArrayList]@()
    $hash = @{}
    Foreach ($ApplicationTag in $ApplicationTags) {
        $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate 
        (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
        $ApplicationTag}
        $SumForApplicationTag = 0
        $TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
        $TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
        Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur" 
            $OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
            ForEach ($OwnerTag in $OwnerTags) {
               $ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) - 
               EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq 
                 $ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
               $SumForOwner = 0
               $TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
               $TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
               # We use the hash to check for break by ApplicationTag
               if (!$hash[ApplicationTag]) { 
                   $hash[$ApplicationTag]=$True
                   $html.Add((Select-Object @{n="Application tag";e={$ApplicationTag}},@{n="Owner";e={""}},@{n="Cost";e={[string]$([int]$SumForApplicationTag)+" Eu."}} -InputObject ''))
               }
               # Adding the owners
               $html.Add((Select-Object @{n="Application tag";e={""}},@{n='Owner';e={$OwnerTag}},@{n='Cost';e={[string]$([int]$SumForOwner)+" Eu."}} -InputObject ''))
               Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
        }
    }; $html |  ConvertTo-Html -As Table -Title "Cost of subscriptions"  | Out-File c:\example.html
    

    Which should render the following HTML :

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Cost of subscriptions</title>
    </head><body>
    <table>
    <colgroup><col/><col/><col/></colgroup>
    <tr><th>ApplicationTag</th><th>Owner</th><th>Cost</th></tr>
    <tr><td>Testing</td><td></td><td>25 Eu</td></tr>
    <tr><td></td><td>[email protected]</td><td>15 Eu</td></tr>
    <tr><td></td><td>[email protected]</td><td>10 Eu</td></tr>
    <tr><td>Testing 2</td><td></td><td>100 Eu</td></tr>
    <tr><td></td><td>[email protected]</td><td>40 Eu</td></tr>
    <tr><td></td><td>[email protected]</td><td>40 Eu</td></tr>
    <tr><td></td><td>[email protected]</td><td>20 Eu</td></tr>
    </table>
    </body></html>
    

    Wich should render as :

    enter image description here