This script is designed to create an Excel spreadsheet from each HTML table from auto-generated index.html
file.
It needs to be very robust but unfortunately I don't have many example files to test it against. Any feedback on style, possible points of failure, or vulnerabilities would be very appreciated.
Powershell
function Main
{
# find each file called "index.html" in the folders below the directory of the script
$Directory = $PSScriptRoot
$htmlFiles = Get-ChildItem -path $Directory -Recurse -Include index.html
# for each html file, create an excel file in the directory of the script
# called Exceptions Log <date of HTML file creation>.xlsx
ForEach($htmlFile in $htmlFiles)
{
$fileCreationDate = (Get-ChildItem $htmlFile).CreationTime
$fileString = $fileCreationDate.ToString("yyyy-mm-dd hh.mm.ss")
$outputFile = "$Directory\Exceptions Log $fileString.xlsx"
Write-Host "Parsing HTML file: $htmlFile"
$document = ParseHtml $htmlFile
Write-Host "Creating Excel file: $outputFile"
CreateExcelFromHtml $document $outputFile
}
}
# load local HTML file and return COM object that we can query
function ParseHtml([string]$fileIn)
{
$html = New-Object -ComObject "HTMLFile"
$source = Get-Content $fileIn -Raw
$html.IHTMLDocument2_write($source)
return $html
}
# create excel spreadsheet from html document
function CreateExcelFromHtml($document, [string]$excelFile)
{
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false # $true
$excel.DisplayAlerts = $false
$workbook = $excel.Workbooks.Add()
$sheet = $workbook.ActiveSheet
Write-Host "Filling in Excel file"
$row = 1;
# iterate over tables
$tables = $document.getElementsByTagName("table")
$captions = $document.getElementsByTagName("caption")
for($t=0; $t -lt $tables.length; $t++){
# create 2 row space between tables
$row += 2
#iterate over rows
$rows = $tables[$t].getElementsByTagName("tr")
for($i=0; $i -lt $rows.length; $i++)
{
# iterate over cells
# every other cell is a blank cell, however cells with content are always nested in a "font" tag
$cells = $rows[$i].getElementsByTagName("font")
for($j=0; $j -lt $cells.length; $j++)
{
# load each cell contents into an excel cell
$sheet.Cells.Item($row + $i, $j+1) = $cells[$j].innerText.Trim()
}
}
# add corrective action column to first table
if($t -eq 0){
$j += 1 # increment table size
$sheet.Cells.Item($row, $j) = "Corrective Action";
}
# get table title from corresponding caption
$title = [string]$captions[$t].innerText
StyleTable $sheet $title $row $i $j
$row += $i
}
Write-Host "Formating Excel file"
$sheet.UsedRange.ColumnWidth = 18
Write-Host "Saving Excel file"
$workbook.SaveAs($excelFile, 51)
$workbook.Close();
$excel.Quit()
}
Function StyleTable($sheet, $tableTitle, $startRow, $numberOfRows, $endColumn){
# give the table a title and style it
$titleCell = $sheet.Cells($startRow - 1, 1)
$titleCell.Value = $tableTitle
$titleCell.Font.Name = "Cambria"
$titleCell.Font.Size = 14
$titleCell.Font.Bold = $true
$titleCell.Font.ThemeColor = 5
# give the table a border
$tableRange = $sheet.Range($sheet.Cells($startRow, 1), `
$sheet.Cells($startRow + $numberOfRows - 1, $endColumn))
$tableRange.Borders.Weight = 2
# make the table header bold and blue
$headerRange = $sheet.Range($sheet.Cells($startRow, 1), `
$sheet.Cells($startRow, $endColumn))
$headerRange.Interior.ColorIndex = 37
$headerRange.Font.Bold = $true
}
Main
Example index.html
file
<html> <head> <title>FooBar</title> </head> <body> <center> <p> <b><font size=6>Bar</font> </b><br> <b><font size=4>Foo</font> </b><br> <font size=3>FooBar</font> </p> <table> <caption><font size=3><b>Title</b></font></caption> <thead> <th align=left valign=bottom><font size=2><u>A</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>B</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>C</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>D</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>E</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>F</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>G</u></font></th><th> </th> </thead> <tbody> <tr> <td valign=top><font size=2>1</td><td> </td> <td valign=top><font size=2>2</td><td> </td> <td valign=top><font size=2>3</td><td> </td> <td valign=top><font size=2>4</td><td> </td> <td valign=top><font size=2>5</td><td> </td> <td valign=top><font size=2>6</td><td> </td> <td valign=top><font size=2>7</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> <tr> <td valign=top><font size=2>Do</td><td> </td> <td valign=top><font size=2>Re</td><td> </td> <td valign=top><font size=2>Mi</td><td> </td> <td valign=top><font size=2>Fa</td><td> </td> <td valign=top><font size=2>So</td><td> </td> <td valign=top><font size=2>La</td><td> </td> <td valign=top><font size=2>Ti</td><td> </td> </tr> </tbody> </table> <br> <table> <caption><font size=3><b>Title 2</b></font></caption> <thead> <th align=left valign=bottom><font size=2><u>Foo</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>Bar</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>FoobBar</u></font></th><th> </th> </thead> <tbody> <tr> <td valign=top><font size=2>Fizz</td><td> </td> <td valign=top><font size=2>Buzz</td><td> </td> <td valign=top><font size=2>FizzBuzz<br> <br> </td><td> </td> </tr> <tr> <td valign=top><font size=2>Foo</td><td> </td> <td valign=top><font size=2>Bar</td><td> </td> <td valign=top><font size=2>FooBar<br> <br> </td><td> </td> </tr> </tbody> </table> <br> <table> <caption><font size=3><b>Title 3</b></font></caption> <thead> <th align=left valign=bottom><font size=2><u>Fizz</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>Buzz</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>FizzBuzz</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>FooBar</u></font></th><th> </th> </thead> <tbody> <tr> <td valign=top><font size=2>Foo</td><td> </td> <td valign=top><font size=2>Bar</td><td> </td> <td valign=top><font size=2>FooBar</td><td> </td> <td valign=top><font size=2>FizzBuzz</td><td> </td> </tr> </tbody> </table> <br> <p> <b><font size=4>Something</font> </b><br> </p> <table> <caption><font size=3><b>Title 4</b></font></caption> <thead> <th align=left valign=bottom><font size=2><u>Foo</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>Bar</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>Fizz</u></font></th><th> </th> <th align=left valign=bottom><font size=2><u>Buzz</u></font></th><th> </th> </thead> <tbody> <tr> <td valign=top><font size=2>Foo</td><td> </td> <td valign=top><font size=2>Bar</td><td> </td> <td valign=top><font size=2>Fizz</td><td> </td> <td valign=top><font size=2>Buzz</td><td> </td> </tr> <tr> <b><td valign=top><font size=2>Foo</td><td> </td> </b><td valign=top><font size=2>Bar</td><td> </td> <td valign=top><font size=2>Fizz</td><td> </td> <td valign=top><font size=2>Buzz</td><td> </td> </tr> </tbody> </table> <br> </center> </body> </html>