Jump to content

Print table from script using internet browser


JanZoudlik
 Share

Recommended Posts

Hello everyone,

here is my little contribution to AutoIt community.

I was looking for a way to print tables from my scripts. None of the solutions was exactly working for me as there were always some limitations.

If you need to be able to print table, while making sure that header is printed on each page (if large table), rows won't split up(across several pages) and you want to be able to adjust table size on page or each column size, you in the right place. Also you can choose between landscape and portrait mode :)

It uses a browser to print table out. Simply, it generates a html file which is then open within browser and it initialize print. This version is tested with Chrome browser...

Please be aware that there is a bug. When you try to disable row numbers, it will also remove table borders(lines). If anybody can figure out why, it would be appreciated by me and I am sure by others as well.

Enjoy

Jan

UPDATE: found today that geniuses from Google stopped following standards and it no longer prints correctly with Chrome. It also ignores the portrait/landscape settings.

However, I tested it with latest IE on Win 7 and it works fine!!! so I suggest you use IE to print...

In case you don't have IE as main browser and you do have issues with your current browser then replace shellexecute and winwaitactive at the end of function with:

local $hIE=run('"C:\Program Files\Internet Explorer\iexplore.exe" "' & $sFile & '"')
ProcessWait($hIE)
; AutoIt Version: 3.3.10
; Language:       English
; Platform:       Win
; Author:         Jan Zoudlik
; NOTE:           big thanks to DoctorDestructo from http://stackoverflow.com/ for main script with css styling etc 
;                 and guinness, tproli, Lupo73 from https://www.autoitscript.com/forum/ for inspiration with their listview to html function
; Script Function:
;  table print - example + _table_print function

#include <File.au3>

Local $aTestArray[4][4] = [[20, 50, 20, 7], ["head", "heading<br/>accross two lines", "heading", "X"],["data row 1",5,"data",6],["data row 2",5&"<br/>"&6,"data",6]]
_table_print("test title",100,$aTestArray,True)

Func _table_print($Title,$Table_Size,ByRef $2D_array, $Landscape=True, $Row_Numbers=True)
   ;table that will print as table should (tested with chrome and ie browsers)> header on each page, table cell won't be printed across two pages > so even multi line row will always stay on one page or will be as whole pushed to next page
   ;to break the line within the cell or heading use "<br/>" not @LF or @CRLF as it is html... if word within cell is wider then column width it will adjust columnm width so word will fit, it will auto(line)break sentance if wider than column
   ;the allingment withing table is : vertical middle - horizontal left(header is vertical down - horizontal middle) and row numbers are vertical middle - horizontal right... sufficient for me...
   ;file name automatically generated and saved in temp folder
   ;Title - self explaining - displayed on the top of the table on first page only
   ;Table_Size - in percent - how big table(width) should be compare to the paper size so 100 - table will spread accross whole paper printable area, 50 - table size will be approx half of the paper size
   ;2D_array - row 0, number in percent per each column (width of column) - all together it should add up 100%(97% if row_numbers are used as 3% is used as size for row count column)
   ;2D_array - row 1, column header - will repeat on each page
   ;2D_array - row 2-n, data
   ;$Row_Numbers - first column will contain row number(so there will be one extra column in table)
   ;$Landscape - to print in landscape or portrait mode...
   ;paper size is as per printer settings
   ;font size is set to 10; if adjustment needed for blind people, then search for font-size: 10px; and don't forget to also adjust line-height: 13px accordingly(so it is bigger than font)
   ;_table_print function CREATED BY Jan Zoudlik
   ;big thanks to DoctorDestructo from http://stackoverflow.com/ for main script with css styling etc and guinness, tproli, Lupo73 from https://www.autoitscript.com/forum/ for inspiration with their listview to html function

   $sHTMLTable='<!DOCTYPE html>' & @CRLF & _
   '<html>' & @CRLF & _
   '  <body>' & @CRLF & _
   '    <table '
   if $Row_Numbers then $sHTMLTable=$sHTMLTable & 'class="print t1" '
   $sHTMLTable=$sHTMLTable & 'width="' & $Table_Size & '%"> <!-- Delete "t1" class to remove row numbers. -->' & @CRLF & _
   '      <caption>' & $Title & '</caption>' & @CRLF
   if $Row_Numbers then $sHTMLTable=$sHTMLTable & '     <col width="3%">' & @CRLF
   for $column=0 to ubound($2D_array,2)-1
      $sHTMLTable=$sHTMLTable & '       <col width="' & $2D_array[0][$column] & '%">' & @CRLF
   Next
   $sHTMLTable=$sHTMLTable & '      <thead>' & @CRLF & _
   '        <tr>' & @CRLF
   if $Row_Numbers then $sHTMLTable=$sHTMLTable & '          <th>#</th>' & @CRLF
   for $column=0 to ubound($2D_array,2)-1
      $sHTMLTable=$sHTMLTable & '          <th>' & $2D_array[1][$column] & '</th>' & @CRLF
   Next
   $sHTMLTable=$sHTMLTable & '        </tr>' & @CRLF & _
   '      </thead>' & @CRLF & _
   '      <tbody>' & @CRLF
   for $row=2 to ubound($2D_array)-1
      $sHTMLTable=$sHTMLTable & '        <tr>' & @CRLF
      if $Row_Numbers then $sHTMLTable=$sHTMLTable & '          <td></td>' & @CRLF
      for $column=0 to ubound($2D_array,2)-1
         $sHTMLTable=$sHTMLTable & '          <td>' & $2D_array[$row][$column] & '</td>' & @CRLF
      Next
      $sHTMLTable=$sHTMLTable & '        </tr>' & @CRLF
   Next
   $sHTMLTable=$sHTMLTable & '      </tbody>' & @CRLF & _
   '    </table>' & @CRLF & _
   '  </body>' & @CRLF & _
   '</html>' & @CRLF
   $sCSSstyle='<style>' & @CRLF & _
   '  /* THE FOLLOWING CSS IS REQUIRED AND SHOULD NOT BE MODIFIED. */' & @CRLF & _
   '    div.fauxRow {' & @CRLF & _
   '      display: inline-block;' & @CRLF & _
   '      vertical-align: top;' & @CRLF & _
   '      width: 100%;' & @CRLF & _
   '      page-break-inside: avoid;' & @CRLF & _
   '    }' & @CRLF & _
   '    table.fauxRow {border-spacing: 0;}' & @CRLF & _
   '    table.fauxRow > tbody > tr > td {' & @CRLF & _
   '      padding: 0;' & @CRLF & _
   '      overflow: hidden;' & @CRLF & _
   '    }' & @CRLF & _
   '    table.fauxRow > tbody > tr > td > table.print {' & @CRLF & _
   '      display: inline-table;' & @CRLF & _
   '      vertical-align: top;' & @CRLF & _
   '    }' & @CRLF & _
   '    table.fauxRow > tbody > tr > td > table.print > caption {caption-side: top;}' & @CRLF & _
   '    .noBreak {' & @CRLF & _
   '      float: right;' & @CRLF & _
   '      width: 100%;' & @CRLF & _
   '      visibility: hidden;' & @CRLF & _
   '    }' & @CRLF & _
   '    .noBreak:before, .noBreak:after {' & @CRLF & _
   '      display: block;' & @CRLF & _
   '      content: "";' & @CRLF & _
   '    }' & @CRLF & _
   '    .noBreak:after {margin-top: -594mm;}' & @CRLF & _
   '    .noBreak > div {' & @CRLF & _
   '      display: inline-block;' & @CRLF & _
   '      vertical-align: top;' & @CRLF & _
   '      width:100%;' & @CRLF & _
   '      page-break-inside: avoid;' & @CRLF & _
   '    }' & @CRLF & _
   '    /*table.print > thead {white-space: nowrap;}*/ /* Uncomment if line-wrapping causes problems. */' & @CRLF & _
   '    table.print > tbody > tr {page-break-inside: avoid;}' & @CRLF & _
   '    table.print > tbody > .metricsRow > td {border-top: none !important;}' & @CRLF & _
   '' & @CRLF & _
   '  /* THE FOLLOWING CSS IS REQUIRED, but the values may be adjusted. */' & @CRLF & _
   '    /* NOTE: All size values that can affect an elements height should use the px unit! */' & @CRLF & _
   '    table.fauxRow, table.print {' & @CRLF & _
   '      font-size: 10px;' & @CRLF & _
   '      line-height: 13px;' & @CRLF & _
   '    }' & @CRLF & _
   '' & @CRLF & _
   '  /* THE FOLLvOWING CSS IS OPTIONAL. */' & @CRLF
   if $Landscape then $sCSSstyle=$sCSSstyle & ' @page {size: landscape;} /* Delete to print in portrait mode*/' & @CRLF
   if $Row_Numbers then  $sCSSstyle=$sCSSstyle & '    body {counter-reset: t1;} /* Delete to remove row numbers. */' & @CRLF & _
   '    .noBreak .t1 > tbody > tr > :first-child:before {counter-increment: none;} /* Delete to remove row numbers. */' & @CRLF & _
   '    .t1 > tbody > tr > :first-child:before { /* Delete to remove row numbers. */' & @CRLF & _
   '      display: block;' & @CRLF & _
   '      text-align: right;' & @CRLF & _
   '      counter-increment: t1 1;' & @CRLF & _
   '      content: counter(t1);' & @CRLF & _
   '    }' & @CRLF
   $sCSSstyle=$sCSSstyle & '    table.fauxRow, table.print {' & @CRLF & _
   '      font-family: Tahoma, Verdana, Georgia; /* Try to use fonts that dont get bigger when printed. */' & @CRLF & _
   '      margin: 0 auto 0 auto; /* Delete if you dont want table to be centered. */' & @CRLF & _
   '    }' & @CRLF & _
   '    table.print {border-spacing: 0;}' & @CRLF & _
   '    table.print > * > tr > * {' & @CRLF & _
   '      border-right: 1px solid black;' & @CRLF & _
   '      border-bottom: 1px solid black;' & @CRLF & _
   '      padding: 0 3px 0 3px;' & @CRLF & _
   '    }' & @CRLF & _
   '    table.print > * > :first-child > * {border-top: 1px solid black;}' & @CRLF & _
   '    table.print > thead ~ * > :first-child > *, table.print > tbody ~ * > :first-child > * {border-top: none;} ' & @CRLF & _
   '    table.print > * > tr > :first-child {border-left: 1px solid black;}' & @CRLF & _
   '    table.print > thead {vertical-align: bottom;}' & @CRLF & _
   '    table.print > thead > .borderRow > th {border-bottom: none;}' & @CRLF & _
   '    table.print > tbody {vertical-align:middle;}' & @CRLF & _
   '    table.print > caption {font-weight: bold;}' & @CRLF & _
   '</style>' & @CRLF & _
   '' & @CRLF & _
   '<script>' & @CRLF & _
   '' & @CRLF & _
   '  (function() { // THIS FUNCTION IS REQUIRED.' & @CRLF & _
   '    if(/Firefox|MSIE |Trident/i.test(navigator.userAgent))' & @CRLF & _
   '        var formatForPrint = function(table) {' & @CRLF & _
   '        var noBreak = document.createElement("div")' & @CRLF & _
   '          , noBreakTable = noBreak.appendChild(document.createElement("div")).appendChild(table.cloneNode())' & @CRLF & _
   '          , tableParent = table.parentNode' & @CRLF & _
   '          , tableParts = table.children' & @CRLF & _
   '          , partCount = tableParts.length' & @CRLF & _
   '          , partNum = 0' & @CRLF & _
   '          , cell = table.querySelector("tbody > tr > td");' & @CRLF & _
   '        noBreak.className = "noBreak";' & @CRLF & _
   '        for(; partNum < partCount; partNum++) {' & @CRLF & _
   '          if(!/tbody/i.test(tableParts[partNum].tagName))' & @CRLF & _
   '            noBreakTable.appendChild(tableParts[partNum].cloneNode(true));' & @CRLF & _
   '        }' & @CRLF & _
   '        if(cell) {' & @CRLF & _
   '          noBreakTable.appendChild(cell.parentNode.parentNode.cloneNode()).appendChild(cell.parentNode.cloneNode(true));' & @CRLF & _
   '          if(!table.tHead) {' & @CRLF & _
   '            var borderRow = document.createElement("tr");' & @CRLF & _
   '            borderRow.appendChild(document.createElement("th")).colSpan="1000";' & @CRLF & _
   '            borderRow.className = "borderRow";' & @CRLF & _
   '            table.insertBefore(document.createElement("thead"), table.tBodies[0]).appendChild(borderRow);' & @CRLF & _
   '          }' & @CRLF & _
   '          }' & @CRLF & _
   '        tableParent.insertBefore(document.createElement("div"), table).style.paddingTop = ".009px";' & @CRLF & _
   '        tableParent.insertBefore(noBreak, table);' & @CRLF & _
   '      };' & @CRLF & _
   '      else' & @CRLF & _
   '      var formatForPrint = function(table) {' & @CRLF & _
   '      var tableParent = table.parentNode' & @CRLF & _
   '         , cell = table.querySelector("tbody > tr > td");' & @CRLF & _
   '        if(cell) {' & @CRLF & _
   '          var topFauxRow = document.createElement("table")' & @CRLF & _
   '            , fauxRowTable = topFauxRow.insertRow(0).insertCell(0).appendChild(table.cloneNode())' & @CRLF & _
   '            , colgroup = fauxRowTable.appendChild(document.createElement("colgroup"))' & @CRLF & _
   '            , headerHider = document.createElement("div")' & @CRLF & _
   '            , metricsRow = document.createElement("tr")' & @CRLF & _
   '            , cells = cell.parentNode.cells' & @CRLF & _
   '            , cellNum = cells.length' & @CRLF & _
   '            , colCount = 0' & @CRLF & _
   '            , tbods = table.tBodies' & @CRLF & _
   '            , tbodCount = tbods.length' & @CRLF & _
   '            , tbodNum = 0' & @CRLF & _
   '            , tbod = tbods[0];' & @CRLF & _
   '          for(; cellNum--; colCount += cells[cellNum].colSpan);' & @CRLF & _
   '          for(cellNum = colCount; cellNum--; metricsRow.appendChild(document.createElement("td")).style.padding = 0);' & @CRLF & _
   '          cells = metricsRow.cells;' & @CRLF & _
   '          tbod.insertBefore(metricsRow, tbod.firstChild);' & @CRLF & _
   '          for(; ++cellNum < colCount; colgroup.appendChild(document.createElement("col")).style.width = cells[cellNum].offsetWidth + "px");' & @CRLF & _
   '          var borderWidth = metricsRow.offsetHeight;' & @CRLF & _
   '          metricsRow.className = "metricsRow";' & @CRLF & _
   '          borderWidth -= metricsRow.offsetHeight;' & @CRLF & _
   '          tbod.removeChild(metricsRow);' & @CRLF & _
   '          tableParent.insertBefore(topFauxRow, table).className = "fauxRow";' & @CRLF & _
   '          if(table.tHead)' & @CRLF & _
   '            fauxRowTable.appendChild(table.tHead);' & @CRLF & _
   '          var fauxRow = topFauxRow.cloneNode(true)' & @CRLF & _
   '            , fauxRowCell = fauxRow.rows[0].cells[0];' & @CRLF & _
   '          fauxRowCell.insertBefore(headerHider, fauxRowCell.firstChild).style.marginBottom = -fauxRowTable.offsetHeight - borderWidth + "px";' & @CRLF & _
   '          if(table.caption)' & @CRLF & _
   '            fauxRowTable.insertBefore(table.caption, fauxRowTable.firstChild);' & @CRLF & _
   '          if(tbod.rows[0])' & @CRLF & _
   '            fauxRowTable.appendChild(tbod.cloneNode()).appendChild(tbod.rows[0]);' & @CRLF & _
   '          for(; tbodNum < tbodCount; tbodNum++) {' & @CRLF & _
   '            tbod = tbods[tbodNum];' & @CRLF & _
   '            rows = tbod.rows;' & @CRLF & _
   '            for(; rows[0]; tableParent.insertBefore(fauxRow.cloneNode(true), table).rows[0].cells[0].children[1].appendChild(tbod.cloneNode()).appendChild(rows[0]));' & @CRLF & _
   '          }' & @CRLF & _
   '        tableParent.removeChild(table);' & @CRLF & _
   '        }' & @CRLF & _
   '        else' & @CRLF & _
   '         tableParent.insertBefore(document.createElement("div"), table).appendChild(table).parentNode.className="fauxRow";' & @CRLF & _
   '      };' & @CRLF & _
   '    var tables = document.body.querySelectorAll("table.print")' & @CRLF & _
   '    , tableNum = tables.length;' & @CRLF & _
   '    for(; tableNum--; formatForPrint(tables[tableNum]));' & @CRLF & _
   '  })();' & @CRLF & _
   '</script>'

   $sFile=_TempFile ( @TempDir , "~", ".html" )
;~    $sFile= @ScriptDir  & "\Export.html"
   $hFile= FileOpen($sFile, 2 + 8)
   FileWrite($hFile,$sHTMLTable & $sCSSstyle)
   FileClose($hFile)
   If @error Then
      msgbox(0,"Print Error","Failed to close the file!")
   EndIf
   ShellExecute($sFile)
   WinWaitActive(StringTrimLeft($sFile,StringInStr($sFile,"\","",-1)))
   send("^p")
EndFunc ;==>_table_print
Edited by JanZoudlik
update
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...