0

I'm trying to create a html table with a CSV as source, which needs a few format including add color based on cell value, and merge the first column if the value is same as the next row.

However, 1. the color part works 2. the merge part doesn't work. there is no error but nothing gets merged.

can someone please help to check?

$file = import-csv I:\SCRIPT\IPCNewScript\BackupCode\ResultFinal.csv


$HTMLBody += "<span style='font-family:Courier New;font-size:12pt'>"   # Due to blank space problem


$head = @'
<title>Table</title>
<style>
body { background-color:#E5E4E2;
       font-family:Monospace;
       font-size:10pt; }
td, th { border:0px solid black; 
         border-collapse:collapse;
         white-space:pre; }
th { color:white;
     background-color:black; }
table, tr, td, th { padding: 2px; margin: 0px ;white-space:pre; }
tr:nth-child(odd) {background-color: lightgray}
table { width:95%;margin-left:5px; margin-bottom:20px;}
h2 {
 font-family:Tahoma;
 color:#6D7B8D;
}
.warning {
 color: orange; 
 }
 .issue {
 color: red; 
 }
 .mergecol {
 rowspan="2";
 }
</style>
'@



[xml]$html = $file | convertTo-Html -fragment -As table



for ($j=4; $j -le $html.table.tr[1].td.count-1; $j++){
    if(($html.table.tr[1].td[$j] -as [string]) -eq "Sun" ){ 
        for ($i=2; $i -le $html.table.tr.count-1; $i++){
            $class = $html.CreateAttribute("class")
            $class.value = 'warning'
            $html.table.tr[$i].ChildNodes[$j].Attributes.append($class) | out-null
        }
    } 
    else {
        for ($i=2; $i -le $html.table.tr.count-1; $i++){
            if (($html.table.tr[$i].td[$j] -as [int]) -eq 0){
                 $class = $html.CreateAttribute("class")
                 $class.value = 'issue'
                 $html.table.tr[$i].ChildNodes[$j].Attributes.append($class) | out-null
            }
        }
    }}

    #merge column
    for ($i =1; $i -le $html.table.tr.count-2; $i++){
        if (($html.table.tr[$i].td[0] -as [string]) -eq  ($html.table.tr[$i+1].td[0] -as [string]))
        {
            $class = $html.CreateAttribute("class")
            $class.value = 'mergecol'
            $html.table.tr[$i].ChildNodes[0].Attributes.append($class) | out-null 
            $i++
         }
    }
    convertto-html -head $head -body $($html.innerxml) | out-file "I:\SCRIPT\IPCNewScript\BackupCode\final28.htm"
ella
  • 165
  • 2
  • 4
  • 17
  • That's quite a lot of code. Consider writing a [mcve](https://stackoverflow.com/help/mcve). – G42 Jan 28 '18 at 19:59
  • What does this --- 'ResultFinal.csv' --- contain? How is it delimited? Are there headers on this file? What do you mean by merge (merge on import or on formatting for output)? – postanote Jan 28 '18 at 20:58
  • @postanote seems i can not attach file here. the file is delimited by ',' . actually the reason why I put the whole code here is to let ppl have a easier comparison. The part of adding color, and merge is written in the same way, but only the color part works. By 'merge' i mean merge two cells together like in the excel. – ella Jan 28 '18 at 23:56
  • @gms0ulman the reason why I put the whole code here is to let ppl have a easier comparison. The part of adding color, and merge is written in the same way, but only the color part works. – ella Jan 28 '18 at 23:58

1 Answers1

0

I've cleaned up the code in your question a little bit (indenting and the like).

There is some questionable logic in the loops you have iterating over the table elements. There's no reference to $j in the #merge column inner-loop. The two loops do not appear to be related, so why are they nested?

You are also calling ConvertTo-HTML on every iteration over $j which seems pretty questionable.

for ($j=4; $j -le $html.table.tr[1].td.count-1; $j++){
    <# Colorizing code removed for clarity #>

    <# Do you really want to merge columns on every iteration over $j? #>
    #merge column
    for ($i =1; $i -le $html.table.tr.count-2; $i++){
        if (($html.table.tr[$i].td[0] -as [string]) -eq  ($html.table.tr[$i+1].td[0] -as [string]))
        {
            $class = $html.CreateAttribute("class")
            $class.value = 'mergecol'
            $html.table.tr[$i].ChildNodes[0].Attributes.append($class) | out-null 
            $i++
         }
    }
    <# Do you really want to ConvertTo-HTML on every iteration over $j? #>
    convertto-html -head $head -body $($html.innerxml) | out-file "I:\SCRIPT\IPCNewScript\BackupCode\final28.htm"
}
veefu
  • 2,820
  • 1
  • 19
  • 29
  • You are right. I have removed the merge code out of the loop of $j. Also took ConvertTo-HTML out of the loop. However, i feel thats not the cause of issue, because once I changed $class.value = 'mergecol' to be $class.value = 'warning', I do see the first column got color changed. that means the whole structure works, but i feel my class of 'mergecol' is not right? – ella Jan 29 '18 at 00:58
  • Yes, I think you're right too. The class is being added, but it isn't causing the table to render in the way you expect. I suggest editing the 'final28.htm' by hand until it renders the way you want it to, then express those changes in your script's logic. – veefu Jan 29 '18 at 01:30
  • yes i already tried manually. U09 works. thats why i wrote the that class but still not work @veefu – ella Jan 29 '18 at 01:36
  • According to an answer here, rowspan and colspan are not valid CSS attributes. Change your script to modify the TD colspan property directly. https://stackoverflow.com/questions/25334593/css-tables-for-rowspan-and-colspan – veefu Jan 29 '18 at 01:53
  • thank you very much. Not sure how to incorporate the example into my script though. i will have some try. thanks again – ella Jan 29 '18 at 02:03
  • I suspect you can do `$ColspanProp = $html.CreateAttribute('colspan'); $ColspanProp.Value = 2; $html.table.tr[$i].ChildNode[0].Attributes.append$($colspanProp)` but I haven't tried it at all. – veefu Jan 29 '18 at 02:49
  • $ColspanProp = $html.CreateAttribute('colspan') $ColspanProp.Value = 2 $html.table.tr[3].ChildNode[1].Attributes.append($‌​ColspanProp) – ella Jan 29 '18 at 03:00
  • hmm@veefu not work. Unexpected token '$‌​ColspanProp' in expression or statement. At I:\SCRIPT\IPCNewScript\BackupCode\ChnageColorOntheFly.ps1:140 char:67 + $html.table.tr[3].ChildNode[1].Attributes.append($‌​ColspanProp) – ella Jan 29 '18 at 03:01
  • works!!!! ChildNode should be ChildNodes though!!! colspan needs to be 'colSpan'. i will review and paste here tomorrow thanks!!! – ella Jan 29 '18 at 04:01
  • sorry i need more time to check because the format is not good. the next row (of which has rowspan as 2), is 'squeezed' to the right, instead of being merged together.... I will come back to update here.. – ella Jan 31 '18 at 02:55
  • thanks for the help but i expected the 2nd row got merged when i set rowspan of the 1st row to be 2. However the whole 2nd row shifted one column to the right. I tried to delete the 1st cell of the 2nd row but didnt work. for ($i =2; $i -le $html.table.tr.count-2; $i++){ if (($html.table.tr[$i].td[0] -as [string]) -eq ($html.table.tr[$i+1].td[0] -as [string])) { $ColspanProp = $html.CreateAttribute("rowSpan") $ColspanProp.Value = 2 $html.table.tr[$i+1].RemoveChild[0] $html.table.tr[$i].ChildNodes[0].Attributes.append($ColspanProp) } } – ella Feb 01 '18 at 22:12
  • I played around with this a couple days ago. I was able to get the rows to merge by setting the style `display:none` on every `td` element that was to be merged. https://stackoverflow.com/questions/133051/what-is-the-difference-between-visibilityhidden-and-displaynone – veefu Feb 01 '18 at 22:35
  • cool!!! your solution works. I just found below code works too for deleting the merged cell. Can you please update your original answer so that i can mark is as answer? for ($i =2; $i -le $html.table.tr.count-2; $i++){ if (($html.table.tr[$i].td[0] -as [string]) -eq ($html.table.tr[$i+1].td[0] -as [string])) { $ColspanProp = $html.CreateAttribute("rowSpan") $ColspanProp.Value = 2 $html.table.tr[$i+1].RemoveChild($html.table.tr[$i+1].firstchild) $html.table.tr[$i].ChildNodes[0].Attributes.append($ColspanProp) } } – ella Feb 01 '18 at 22:45
  • I experimented with removing the "to-be-merged" `` elements, too. Once you remove the `` element, the next value appears to be the first. When the loop goes on to read the next column it blows up. – veefu Feb 01 '18 at 23:30
  • unfortunately, you are right. I also fidd an issue with `display:none`. It works on the html itself, but once I read it into email body, the "to-be-merged" still shows up. – ella Feb 02 '18 at 00:16
  • looks silly but my final solution is to write 3 sets of code like below for 3 columns. below is for column 2. I tried to put them into one loop but not work `for ($i =2; $i -le $html.table.tr.count-2; $i++){ $ColspanProp = $html.CreateAttribute("rowSpan") $ColspanProp.Value = 2 | out-null $html.table.tr[$i].ChildNodes[1].Attributes.append($ColspanProp) | out-null $html.table.tr[$i+1].RemoveChild($html.table.tr[$i+1].ChildNodes[0]) | out-null $i++ }` – ella Feb 02 '18 at 23:39
  • I think a two-pass system might be easiest. 1. Loop over the list of data and 'mark' ``s that should be deleted 2. Loop again and remove 'marked' elements from the DOM. I don't think it's possible to keep the 'merge' logic functional when the elements keep changing. – veefu Feb 03 '18 at 03:23