I am new to powershell and I want to insert the data from csv to html table which is I create separately. This is my csv
Sitename EmailAddress
Test example#gmail.com
Asking for help of how should I insert this data to my html table and then if I add data in csv it also automatically added on HTML table.
test.ps1 script
$kfxteam = Get-Content ('.\template\teamnotif.html')
$notifteam = '' #result html
$teamlist = Import-Csv ".\list\teamlist.csv" | select 'SiteName','EmailAddress'
For($a=0; $a -lt $kfxteam.Length; $a++) {
# If the "<table class=content>" matches on what written on $kfxteam it will show the result`
if($kfxteam -match "<table class=content >"){
# should be replacing the data came from csv to html and also adding new row
write-host $teamlist[$a].SiteName
}
}
html format
<<table class=content >
<td class=c1 nowrap>
Remote Sitenames
</td>
<td class=c1 nowrap >
Users Email Address
</td>
</tr>
<tr>
<td class=c1 nowrap>
usitename
</td>
<td class=c1 nowrap>
[uemail]
</td>
</tr>
</table>
The output html table should be
Remote Sitenames Email Address
Test example#gmail.com
If I were you, I'd change the HTML template file regarding the table to become something like this:
<table class=content>
<tr>
<td class=c1 nowrap>Remote Sitenames</td>
<td class=c1 nowrap>Users Email Address</td>
</tr>
##TABLEROWSHERE##
</table>
Now, you have a placeholder which you can replace with the table rows you create using the CSV file like:
# create a template for each of the rows to insert
# with two placeholders to fill in using the -f Format operator
$row = #"
<tr>
<td class=c1 nowrap>{0}</td>
<td class=c1 nowrap>{1}</td>
</tr>
"#
# import the csv, loop over the records and use the $row template to create the table rows
$tableRows = Import-Csv -Path '.\list\teamlist.csv' | ForEach-Object {
$row -f $_.Sitename, $_.EmailAddress
}
# then combine it all in the html
$result = (Get-Content -Path '.\template\teamnotif.html' -Raw) -replace '##TABLEROWSHERE##', ($tableRows -join [Environment]::NewLine)
# save the completed HTML
$result | Set-Content -Path '.\list\teamlist.html'
Related
I have a table where i'm trying to add more rows with powershell then export it as a new HTML file.
Here's the body of the HTML i'm trying to add rows to.
<BODY>
<TABLE style="WIDTH: 100%" cellPadding=5>
<TBODY>
<TR>
<TH>Bruger</TH>
<TH>Windows</TH>
<TH>Installations dato</TH>
<TH>Model</TH>
<TH>Sidst slukket</TH></TR>
<TR>
<TD>Users name</TD>
<TD>Windows 10 Pro</TD>
<TD>23-01-2020</TD>
<TD>ThinkPad</TD>
<TD>7 dage</TD></TR></TBODY></TABLE>
<TABLE>
<TBODY></TBODY></TABLE></BODY>
I figured i'd need to change the inner html of an object but it's just throwing an error.
Here's my code
$src = [IO.File]::ReadAllText($outPath)
$doc = New-Object -com "HTMLFILE"
$doc.IHTMLDocument2_write($src)
$elm = $doc.getElementsByTagName('tr')[0]
$elm.innerHTML = "<TR>New row!</TR>"
When I check the inner html variable I get the HTML output that I would expect, so it's grabbing the correct object, but I can't assign anything to it for whatever reason.
Here's the error
Exception from HRESULT: 0x800A0258
At line:1 char:1
+ $elm.innerHTML = "<TH>User</TH>"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
Instead of modifying the innerHTML contents of an existing <tr> element, you'll want to:
Create a new <tr> element
Create any requisite <td> child element(s)
Append <td> element(s) to your new row
Append the new row to the existing <tbody>
Try something like this:
$html = #'
<BODY>
<TABLE style="WIDTH: 100%" cellPadding=5>
<TBODY>
<TR>
<TH>Bruger</TH>
<TH>Windows</TH>
<TH>Installations dato</TH>
<TH>Model</TH>
<TH>Sidst slukket</TH></TR>
<TR>
<TD>Users name</TD>
<TD>Windows 10 Pro</TD>
<TD>23-01-2020</TD>
<TD>ThinkPad</TD>
<TD>7 dage</TD></TR></TBODY></TABLE>
<TABLE>
<TBODY></TBODY></TABLE></BODY>
'#
# Create HTML document object
$doc = New-Object -ComObject HTMLFile
# Load existing HTML
$doc.IHTMLDocument2_write($html)
# Create new row element
$newRow = $doc.createElement('tr')
# Create new cell element
$newCell = $doc.createElement('td')
$newCell.innerHTML = "New row!"
$newCell.colSpan = 5
# Append cell to row
$newRow.appendChild($newCell)
# Append row to table body
$tbody = $doc.getElementsByTagName('tbody')[0]
$tbody.appendChild($newRow)
# Inspect resulting HTML
$tbody.outerHtml
You should expect to see the new row appended to the table body:
<TBODY><TR>
<TH>Bruger</TH>
<TH>Windows</TH>
<TH>Installations dato</TH>
<TH>Model</TH>
<TH>Sidst slukket</TH></TR>
<TR>
<TD>Users name</TD>
<TD>Windows 10 Pro</TD>
<TD>23-01-2020</TD>
<TD>ThinkPad</TD>
<TD>7 dage</TD></TR>
<TR>
<TD colSpan=5>New row!</TD></TR></TBODY>
You could create a nice little helper function for adding new rows:
function New-HTMLFileTableRow {
param(
[Parameter(Mandatory)]
[mshtml.HTMLDocumentClass]$Document,
[Parameter(Mandatory)]
[string[]]$Property,
[Parameter(Mandatory, ValueFromPipeline)]
$InputObject
)
process {
$newRow = $Document.createElement('tr')
foreach($propName in $Property){
$newCell = $Document.createElement('td')
$newCell.innerHtml = $InputObject.$propName
[void]$newRow.appendChild($newCell)
}
return $newRow
}
}
Then use like:
Import-Csv .\path\to\user-os-list.csv |New-HTMLFileTableRow -Property User,OSVersion,InstallDate,Model,LastActive -Document $doc |ForEach-Object {
[void]$tbody.appendChild($_)
}
I have a big HTML file, following is a sample):
<tr valign="top">
<td class="ln"></td><td style="color: #000000; background-color: #efcb05; "><code><span class="sf17b16"> "software_name": "Security Update for Microsoft .NET Framework 4 Client Profile (KB2979575v2)",</span> </code></td>
<td class="ln"></td><td style="color: #000000; background-color: #c0c0c0; "><code> </code></td>
</tr>
<tr valign="top">
<td class="ln"></td><td style="color: #000000; background-color: #c0c0c0; "><code> </code></td>
<td class="ln"></td><td style="color: #000000; background-color: #efcb05; "><code><span class="sf17b16"> "system_id": 3,</span> </code></td>
</tr>
I have to export the text between <span class="sf17b16">and </span>, ignoring the " ". If the immediate next line of the above said pattern starts with </tr> then the text colour of that string should be different from the others.
Expected output:
"software_name": "Security Update for Microsoft .NET Framework 4 Client Profile (KB2979575v2)"
"system_id": 3 (Different colour)
Also I have to export all the results to a HTML file.
Following is what I tried (Crappy), but it din't work.
$file = "C:\Users\Administrator\Desktop\test.htm"
$content= gc "C:\Users\Administrator\Desktop\test.htm"
$pattern = 'sf17b16'
$line = Select-String $pattern $file | ForEach-Object {$_.LineNumber}
if ($line -match '^</tr>')
{
{
$result = [regex]::Matches($content, 'class="sf17b16".*?>(.*?)</span>')
$result | select {($_.Groups[1].Value -replace ' ', '').Trim().Trim(',')}
}
else
{
$result = [regex]::Matches($content, 'class="sf17b16".*?>(.*?)</span>')
$result | select {($_.Groups[1].Value -replace ' ', '').Trim().Trim(',')}
}
} | ConvertTo-Html | Out-File C:\Users\Administrator\Desktop\output.html
Note: Related to thread, Read each line of a HTML file using power shell and export the text between two HTML tags
You want a RegEx solution? Ok, we can do RegEx. This will output an array of objects with 2 properties. One is the value of the search, and the other is if the next row is . How you format or output is up to you, but it gets you the data you want to work with...
$Source = #"
<tr valign="top">
<td class="ln"></td><td style="color: #000000; background-color: #efcb05; "><code><span class="sf17b16"> "software_name": "Security Update for Microsoft .NET Framework 4 Client Profile (KB2979575v2)",</span> </code></td>
<td class="ln"></td><td style="color: #000000; background-color: #c0c0c0; "><code> </code></td>
</tr>
<tr valign="top">
<td class="ln"></td><td style="color: #000000; background-color: #c0c0c0; "><code> </code></td>
<td class="ln"></td><td style="color: #000000; background-color: #efcb05; "><code><span class="sf17b16"> "system_id": 3,</span> </code></td>
</tr>
"#
$Data = ([regex]"class=`"sf17b16`".*?>(?: )*(.*?),<\/span>.*?`r`n(?:<td|<\/tr>)").matches($source)|%{[PSCustomObject]#{'Value' = $_.groups[1].value;'NextRowIsTR'=$_.value -match '<\/tr>$'}}
$Data
You want to run that against a file? Just change the source... just make sure it's all one string to search against for your RegEx matching by joining the array of strings into one multi-line string.
$Source = Get-Content "C:\Users\Administrator\Desktop\test.htm" -join "`r`n"
I've got the following code:
<tr class="even">
<td>
Title1
</td>
<td>
Name1
</td>
<td>
Email1
</td>
<td>
Postcode1
</td>
I want to use RegEx in to output the data between the tags like so:
Title1
Name1
Email1
Postcode1
Title2
Name2
Email2
Postcode2
...
You shouldn't use a regex to parse html, use an HTML parser instead.
Anyway, if you really want a regex you can use this one:
>\s+<|>\s*(.*?)\s*<
Working demo
Match information:
MATCH 1
1. [51-57] `Title1`
MATCH 2
1. [109-114] `Name1`
MATCH 3
1. [166-172] `Email1`
MATCH 4
1. [224-233] `Postcode1`
This should get rid of everything between the tags, and output the rest space separated:
$text =
#'
<tr class="even">
<td>
Title1
</td>
<td>
Name1
</td>
<td>
Email1
</td>
<td>
Postcode1
</td>
'#
$text -split '\s*<.+?>\s*' -match '\S' -as [string]
Title1 Name1 Email1 Postcode1
Don't use a regex. HTML isn't a regular language, so it can't be properly parsed with a regex. It will succeed most of the time, but other times will fail. Spectacularly.
Use the Internet Explorer COM object to read your HTML from a file:
$ie = new-object -com "InternetExplorer.Application"
$ie.visible = $false
$ie.navigate("F:\BuildOutput\rt.html")
$document = $ie.Document
# This will return all the tables
$document.getElementsByTagName('table')
# This will return a table with a specific ID
$document.getElementById('employees')
Here's the MSDN reference for the document class.
I am trying to get values from a database and place them in a dropdown list within an HTML <select> tag.
I'm able to get the values in a long string and display all of them within a single option but I want to put each value in a separate <option> tag. I just don't know what logic I could use to do this.
Here's what I have so far:
#!c:\perl\bin\perl.exe
use CGI;
require ("data_eXchangeSubs.pm");
$query = new CGI;
print $query->header(-expires=>'-1d');
print $query->start_html(
-title=>'Dex Vendor Testing',
-bgcolor=>'white'
);
$user = $query->param("user");
my $dataX = ${ConnectToDatabase($main::DBone, $main::dataENV)};
$resultSet = $dataX->Execute("select vendor from dex_vendor_info group by vendor");
while(!$resultSet->EOF) {
$vendors .= $resultSet->Fields("vendor")->Value."\n";
$resultSet->MoveNext;
}
print <<ONE;
<table width=75% border=0>
<th colspan=2 align=left><strong><font size=5pt color=#FF6633 face=garamond>Vendor Information</strong</font><hr size=4pt color=midnightblue></th>
<tr>
<td align=left nowrap><font size=4pt face=garamond><label id=lVendor for=vendor><strong>Company Name</strong></font></label></td>
<td align=left nowrap><font size=4pt face=garamond><label id=lVendor for=vendor><strong>Contact's Name</strong></font></label></td>
</tr>
<tr>
<td align=left nowrap><select id="vendors">
<option>$vendors</option>
</td>
</td>
<td align=left nowrap><input type=text name="contact" id=contact value="" size=25></td>
</tr>
</table>
<br>
ONE
print $vendors;
print $query->end_html;
If you're using CGI, then use CGI.
print $query->popup_menu(
-name => 'vendors'
, -values => \#list_of_vendors
, -default => $default_vendor
);
And you get #list_of_vendors in your row processing loop:
my #list_of_vendors;
while(!$resultSet->EOF) {
push #list_of_vendors, $resultSet->Fields("vendor")->Value;
$resultSet->MoveNext;
}
If you want labels to be a different text value from values include -labels tag in the call and point it to an array ref containing the text you want visible.
I want to be able to monitor my printers status web page and have a script email me when the ink level falls below 25%. Im pretty sure this can be done in Powershell, but Im at a loss on how to do it.
This is the page HTML in question:
<h2>Supply Status</h2>
<table class="matrix">
<thead>
<tr>
<th>Supply Information</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>Black Toner</td>
<td>End of life</td>
</tr>
<tr>
<td>Cyan Toner</td>
<td>Under 25%</td>
</tr>
<tr>
<td>Magenta Toner</td>
<td>Under 25%</td>
</tr>
<tr>
<td>Yellow Toner</td>
<td>Under 25%</td>
</tr>
</tbody>
</table>
<p>
Thanks.
Adam
Building on #Joey's answer, give this a whirl with the HTML Agility Pack.
$html = new-object HtmlAgilityPack.HtmlDocument
$result = $html.Load("http://full/path/to/file.htm")
$colors = $html.DocumentNode.SelectNodes("//table[#class='matrix']//tbody/tr")
$result = $colors | % {
$color = $_.SelectSingleNode("td[1]").InnerText
$level = $_.SelectSingleNode("td[2]").InnerText
new-object PsObject -Property #{ Color = $color; Level = $level; } |
Select Color,Level
}
$result | Sort Level | ft -a
This assumes you already have the HTML Agility Pack loaded into PowerShell. Mine is loaded in my profile as:
[System.Reflection.Assembly]::LoadFrom(
(join-path $profileDirectory HtmlAgilityPack)
+ "\HtmlAgilityPack.dll" ) | Out-Null
Using the example HTML provided, your output looks like:
At this point, you have the output and can email it out.
The easiest way would probably be the HTML Agility Pack which you can import in PowerShell. Lee Holmes has a short article demonstrating a simple example with it. Essentially you're using an XML-like API to access the HTML DOM.