Html to PDF

Use the PDF connector to create PDF files in your workflow. The connector uses Hypertext Markup Language (HTML) to define the layout of your PDF pages and fully supports using FlowScript.

Connector Output

The output from the connector is a standard file record.

General Tips & Tricks

  • Write as simple HTML as possible by hand: You will run into problems if you use code taken straight from WYSIWYG HTML editors. Gain some basic knowledge of how to code HTML Tables and using CSS style sheets and you will thank yourself later. Also it's great fun πŸ™‚

  • In most use cases, you want to take control over the page breaks in your document using the page-break-inside CSS property.

  • In order to enable CSS for your document, head to the CSS Section.

  • Try to structure your workflow in a way so that you build your html document in modules. This is especially useful when you are designing complex documents with several parts. To achieve modularity, you can for example write your CSS code in a script-step, your header code in another script-step and so on. Then in your connector HTML settings, you just end up with the document skeleton. An example of this can be found in the Layout Examples section.

Pro Tip: Create a simple workflow with a PDF connector and a user step. In the user step, add a file gallery with the generated PDF document(s) and use the workflow for designing and debugging your page layouts.

Another good practice is to use one machine step per distinct document section (if you build a complex document) and then supply the previous PDF document (file record) as input parameter for the next PDF task (see Append to an existing PDF).

Settings

This chapter describes the available settings in the PDF connector.

File Name

This string defines the filename-key value of the target file record.

Append to an existing PDF

The connector optionally takes a file record containing a PDF file as an input variable. If suppied, the new page(s) created in the current machine step will be appended to the existing PDF file. The target variable will contain the merged PDF file as a standard file record.

To keep the file name from the previous PDF step, just re-use the filename value from the previous PDF file record:

Margins

The margin sizes in DTP points.

Page Size

The default setting for page size is A4-format. The page size selector lets you choose from the most common page sizes. The page size can also be defined manually.

Manual Page Size

It's possible to set a manual page size in DTP points. This setting will override any selection made in the Page Size selection drop down menu and you need to clear any values the Width (pts) and Height (pts) to revert back to using the Page Size selection menu.

Note:

The total page width in DTP Points = the supplied width + Margin Left + Margin Right

The total page height in DTP Points (excluding the page contents) = the supplied height + Margin Top + Margin Bottom

Page Orientation

Choose between Portrait and Landscape orientation. The default orientation is Portrait.

Images / Signatures

If you need to insert images or flow signatures in your PDF document, you need to make sure to have them available in your workflow as file records.

Signatures from the signature capture input provider is by default a file record with some extra fields ("mimeType" and "size") and are supported by the PDF connector as is.

The Images / Signatures field takes either a file record or a table of file records.

Overriding file names

In order to be able to differentiate between the images/signatures in the HTML code, you might need to override the filename component of the file records and give them unique and identifiable file names prior to passing them to the PDF connector. The image below shows a file name being overridden in an assignment step.

To position your image/signature in the document, the HTML IMG tag is used:

<img src=your_file_name.jpg height=40>

Supported image formats

The following image formats are supported by the connector:

  • BMP

  • GIF (with optional transparency)

  • PNG (with optional transparency)

  • JPEG

  • TIFF (with optional transparency)

HTML

The connector supports the HTML 4.01 specification.

The document layout is defined using HTML. It's recommended to keep the code as simple as possible and build the layout using a bottom-up approach. If you are new to HTML, visit WordHtml. However if you use the generated code directly you will get disappointed as there are some important aspects to keep in mind. Most importantly, you need to use percentages instead of absolute values for width. Keep the total width of your columns at about 95%.

Controlling the layout

Styling / CSS

The connector supports the CSS Level 2 Specification, so you can use cascading style sheets to format your PDF documents. Even if you are creating a simple page layout, you will probably still want to use CSS for controlling page breaks inside your HTML elements (such as table rows and/or cells).

In addition, there is also support for gradients on backgrounds and rounded corners:

<!-- Example background gradient -->
<body style="background-color: #333; 
  background-gradient: #707; 
  background-gradient-angle: 60; 
  margin: 0;">

Note: Since both FlowScript and CSS syntax uses curly brackets, the connector leverages a concept called Magic Tags to distinguish CSS from FlowScript. Hence you need to get familiar with these tags in order to be able to use CSS in your layouts.

Learning HTML and CSS is out of scope of this documentation. However if you have issues getting your document layout look as you expect - the best bet is to simplify the code and make sure you are not using any syntax feature outside of the supported specifications (CSS Level 2 and HTML 4.01). Keep it simple.

Page breaks

The CSS property page-break-inside is used by the connector to control how page breaks are rendered. Two values are supported: auto (default) and avoid.

With the default values there are no rules defined to transfer html-blocks or words to the next page. The page break will simply happen when the page runs out of space (which might result in text being cut through the middle):

Using td { page-break-inside: avoid; } - words located on the bottom of a page will be transferred to the new page without getting split. The same goes for th, p, span and for any text in any other tags:

With table { page-break-inside: avoid; } - if a table row does not fit on the current page, then the whole row will be transferred to the next page. If the row height is larger than the whole page height, it doesn’t make sense to transfer it and the value of page-break-inside will be ignored.

Known cosmetic issues

If the page-break-inside=auto has been set on the table and page-break-inside=avoid has been set on the cell, then an empty part of table cell can be rendered at the end of page:

If page-break-inside=avoid has been set on the table and the row is bigger than the rest of page but will fit on the next page - it will be transferred to the next page and a lot of space will be left empty on the previous one:

Headers, footers and watermarks

An HTML element with the CSS property position: fixed will be rendered on every page and can therefore be used as headers/footers or watermarks.

Important: These elements will ignore the page margins, so if you need to fit a 50px high header on your pages and want a 20px high margin to the page contents, you need to update the page top margin to 70px to make room for your page header.

Example header and footer CSS code:

.header {
    position: fixed;
    left: 20px;
    top: 20px;
}

.footer {
    position: fixed;
    left: 20px;
    top: 750px;
}

Note: Plain CSS used for clarity. You will need to replace the curly brackets with Magic Tags in your connector markup code.

Example HTML document using the header and footer:

<body>
    <div class="header">
        logo
    </div>
    <div class="footer">
        disclaimer
    </div>

    <p>
        page content...
...

Magic tags

Magic Tags are a connector specific tag system which enables the usage of both FlowScript and CSS in the HTML section of the connector settings. This section will walk you through how to enable Magic Tags parsing and how to use them with CSS in your page layouts.

Enabling magic tags

To enable parsing of the tags, you just need to add the line [_ENABLE_MAGIC_TAGS_] in the HTML section of the connector settings:

[_ENABLE_MAGIC_TAGS_]
<html>
<!-- Your page layout goes here -->
</html>

Using magic tags to write CSS code

In order to convert your CSS code to be usable by the connector:

  1. Replace all left curly brackets "{" with "[_CBL_]"

  2. Replace all right curly brackets "}" with "[_CBR_]"

This is how the converted CSS code from the header/footer example above will look like:

.header [_CBL_]
    position: fixed;
    left: 20px;
    top: 20px;
[_CBR_]

.footer [_CBL_]
    position: fixed;
    left: 20px;
    top: 750px;
[_CBR_]

Layout Examples

Document Skeleton

Sample document skeleton including style sheet, header and footer which are defined in script steps in the workflow:


[_ENABLE_MAGIC_TAGS_]

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us" dir="ltr">


<head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />

    {pdf_stylesheet}

</head>


<body>

    {pdf_header}

    {pdf_footer}

    <h1>Heading</h1>

    <table class="ContentTable" id="1">

        {content_table_1}

    </table>


    <table class="ListTable" cellspacing="0" cellpadding="0">

        {list_table}

    </table>


    <table class="CheckListTable">

        {self_control_table_2}

    </table>

</body>


</html>

Style Sheet

Sample MagicTag-formatted CSS code defined in a script step. The output variable name pdf_stylesheet is used and then referred to in the document skeleton above. Note that here we include the <style /> tags which were excluded in the document skeleton.

return ''
&'    <style>'
&'      body [_CBL_]'
&'          font-size:12px;'
&'          color:#000000;'
&'          font-family: sans-serif;'
&'      [_CBR_]'

&'      h1 [_CBL_]'
&'          margin:0px;'
&'          padding-top:20px;'
&'          padding-bottom:0px;'
&'      [_CBR_]'

&'      div [_CBL_]'
&'          display:block;'
&'      [_CBR_]'

&'      td [_CBL_]'
&'          page-break-inside: avoid;'
&'      [_CBR_]'

&'      table [_CBL_]'
&'          page-break-inside: avoid;'
&'          border-collapse: collapse;'
&'      [_CBR_]'

&'      .header [_CBL_]'
&'          position:fixed;'
&'          height: 45px;'
&'          left: 50px;' 
&'          top: 30px;'
&'      [_CBR_]'

&'      .footer [_CBL_]'
&'          position: fixed;'
&'          left: 50px;'
&'          top: 800px;'
&'      [_CBR_]'

&'      #title [_CBL_]'
&'          font-size: 28px;'
&'      [_CBR_]'

&'      .ContentTable [_CBL_]'
&'          width:100%;'
&'      [_CBR_]'

&'      .ContentTable th [_CBL_]'
&'          text-align: left;'
&'          padding: 2px 2px 2px 2px;'
&'      [_CBR_]'

&'      .ContentTable td [_CBL_]'
&'          text-align: left;'
&'          padding: 2px 2px 2px 2px;'
&'      [_CBR_]'

&'      .ListTable [_CBL_]'
&'          width:100%;'
&'      [_CBR_]'

&'      .ListTable th [_CBL_]'
&'          border:1px solid #666666;'
&'          font-weight: bold;'
&'          font-style: normal;'
&'          text-decoration: none;'
&'          color: #ffffff;'
&'          background-color: #333333;'
&'      [_CBR_]'

&'      .ListTable td [_CBL_]'
&'          border:1px solid #666666;'
&'          font-style: normal;'
&'          text-decoration: none;'
&'          color: #000000;'
&'      [_CBR_]'

&'      .ListTable th, .listTable td [_CBL_]'
&'          margin: 0px;'
&'          padding: 5px 5px 5px 5px;'
&'      [_CBR_]'

&'      .ListTable th, .listTable tr.tableRowHead td [_CBL_]'
&'          text-align: left;'
&'          background-color: #333333;'
&'          color: #ffffff;'
&'      [_CBR_]'

&'      .ListTable td.empty_dataset [_CBL_]'
&'          padding-top: 40px;'
&'          padding-bottom: 40px;'
&'      [_CBR_]'

&'      tr.altrow td [_CBL_]'
&'          background-color: #FFFFFF;'
&'      [_CBR_]'

&'    </style>';

Header FlowScript code, referred to as pdf_header in the document skeleton:

return '<div class="header"><img src="company_logo.png" alt="" /></div>';

Footer FlowScript code, referred to as pdf_footer in the document skeleton:

return '<div class="footer">Sample footer text</div>';

HTML table from flow record

Code referred to as checklist_table in the document skeleton:

let infoRec = First(infoTable);
let html = ''
&'      <tr>'
&'          <th>Info 1:</th>'
&'          <th>Info 2:</th>'
&'          <th>Info 3:</th>'
&'          <th>Info 4:</th>'
&'      </tr>'
&'      <tr>'
&'          <td>'&infoRec.info1&'</td>'
&'          <td>'&infoRec.info2&'</td>'
&'          <td>'&infoRec.info3&'</td>'
&'          <td>'&infoRec.info4&'</td>'
&'      </tr>'
&'      <tr>'
&'          <th>Info 5:</th>'
&'          <th>Info 6:</th>'
&'          <th>Info 7:</th>'
&'          <td rowspan="2"></td>'
&'      </tr>'
&'      <tr>'
&'          <td>'&infoRec.info5&'</td>'
&'          <td>'&infoRec.info6&'</td>'
&'          <td>'&infoRec.info7&'</td>'
&'      </tr>';
return html;

HTML table from flow table

Code referred to as list_table in the document skeleton. Here we use checkbox symbols from the Wingdings font to render good looking checkboxes in the final PDF document.

let html = '';
let cbSize = '20';

// Add the table header row:
set html = html
&'      <tr>'
&'          <th style="text-align: left; padding-top: 5px; padding-right: 0px; padding-left: 10px; padding-bottom: 5px;">Information:</th>'
&'          <th style="text-align: center; padding-top: 5px; padding-right: 5px; padding-left: 5px; padding-bottom: 5px;">Yes</th>'
&'          <th style="text-align: center; padding-top: 5px; padding-right: 5px; padding-left: 5px; padding-bottom: 5px;">No</th>'
&'          <th style="text-align: left; padding-top: 5px; padding-right: 0px; padding-left: 10px; padding-bottom: 5px;">Comment:</th>'
&'      </tr>';

// Iterate through the SQL table rows
let counter = 0;
for row in listTable {
   let cbYes = 'o';
   if row.yes = 1 {
       set cbYes = 'ΓΎ';
   }
   
   let cbNo = 'o';
   if row.no = 1 {
       set cbNo = 'ΓΎ';
   }
   
    counter = counter + 1;
    let evenRow = ' class="altrow"';
    if (Floor(counter/2) < counter/2) {
       set evenRow = '';
    }

   if row.header = 1 {
      set counter = 0;
      set html = html
      &'      <tr>'
      &'          <td style="text-align: left; font-weight: bold; padding-top: 15px; padding-right: 0px; padding-left: 10px; padding-bottom: 0px;">'
      &'              '&row.information&'</td>'
      &'          <td style="text-align: center; font-weight: bold; padding-top: 5px; padding-right: 5px; padding-left: 10px; padding-bottom: 5px;">'
      &'          </td>'
      &'          <td style="text-align: center; font-weight: bold; padding-top: 5px; padding-right: 5px; padding-left: 10px; padding-bottom: 5px;">'
      &'          </td>'
      &'          <td style="text-align: right; font-weight: normal; padding-top: 18px; padding-right: 5px; padding-left: 10px; padding-bottom: 0px;">'
      &'              '&row.comment&'</td>'
      &'      </tr>';
   }
   else {
      set html = html
      &'      <tr'&evenRow&'>'
      &'          <td style="text-align: left; font-weight: normal; padding-top: 5px; padding-right: 0px; padding-left: 10px; padding-bottom: 5px;">'
      &'              '&row.information&'</td>'
      &'          <td style="text-align: center; font-weight: normal; font-family: Wingdings; font-size: '&cbSize&'px; padding-top: 5px; padding-right: 5px; padding-left: 5px; padding-bottom: 5px;">'
      &'              '&cbYes&'</td>'
      &'          <td style="text-align: center; font-weight: normal; font-family: Wingdings; font-size: '&cbSize&'px; padding-top: 5px; padding-right: 5px; padding-left: 5px; padding-bottom: 5px;">'
      &'              '&cbNo&'</td>'
      &'          <td style="text-align: left; font-weight: normal; padding-top: 5px; padding-right: 0px; padding-left: 10px; padding-bottom: 5px;">'
      &'              '&row.comment&'</td>'
      &'      </tr>';
   }
}

return html;

Adding Fonts

The connector will be able to use fonts installed on the machine hosting the connector.

To install a font in Windows; right-click the .ttf-file and select "Install", then restart the Flow Server.

To specify the font face in HTML, add the font-family style attribute to your HTML element or CSS:

font-family: 'DengXian Light';

Reference

DTP Point

DTP points on Wikipedia

1 DTP Point = 1/72 inches = 25.4/72 mm = 0.3527 mm

File Record

A file record is a flow record with two fields: filename and data.

/* FlowScript for a file record */
let fileRec = [filename: 'mySignature1.png', data: mySignatureRecord.data];
return fileRec;

Last updated