PDF Application Guide

Auto Tables

The application can detect tables within the PDF. While it's easy for a human eye to detect the tables, doing so in an automatic method uses the following rules to determine:

  • Determine if field is in a column is done by finding all fields that are named the same but have a suffix of a numeral number. For instance fields first_name_001 and first_name_002 are determined to be in the same column. The application will strip all 0-9 and _ from the end of the field name. If the field name is the same as another, then they are in the same column. It is possible for a column to span multiple PDF pages. Some applications, or you can do it yourself, name fields on multiple pages in the following format name_page_row. From the column algorithm, the _ and numbers are removed and it will be just name. It is in this way that columns are defined across multiple pages.
  • Determine which columns are in a table is done by looking at all the columns that are found, then looking at the position of the first row. Any other columns that start close to the same rows on the form on the same page is determined to be in the same table. Currently the row tolerance is 20 units (about a 1/3 of an inch).

The Auto Tables can be detected only once per form and is done by clicking the Detect Tables button on the UXstorm PDF Form.

When Auto Tables are detected, a new tab on the form will appear and the Detect Tables button will be removed. The new tab will contain all the detected tables and where they appear in the PDF form. The name of each table is impossible to automatically detect so each will start with Auto Detected Table#X.

NOTE: Not all detected tables may actually be tables on the form, for instance if you have two fields on the form undefined_1 and undefined_2, this will be reported as a table. This can be resolved by renaming the fields so they do not look like columns.

Table Form

The Table Form for each Auto Table will contain:

Field Description
Name Name of the table. It is recommended to give each table a descriptive name
Page The first page in the PDF where this table starts
X The units from the left side of the page where the table starts
Y The units from the bottom of the first page where the table starts
Rows How many rows are in the table
Map Check to map the table
Table Data Source What method to use to gather the data that will be mapped into the table. Only available if Table is Mapped
Related List Appears if Table Data Source is Related List or Related List to Reference Field. Used to select the related list of records.
Reference Field Appears if Table Data Source is Related List to Reference Field Used to select the reference field that a related list will be used to get the related list of records. For instance if the table has a reference field to the sys_user table, and is selected, the the Reference Field will show all related lists to the User Record.
Catalog Table Variable Appears if Table Data Source is Catalog Table Variable. This will list all detected Catalog Table Variables on the Catalog Item specified on the PDF form. If the table is not sc_req_item or there are no Catalog Table Variables detected, then this list will be empty
Table Script Appears if Table Data Source is Script. This contains a script to gather all the data for the table using ServiceNow Javascript.

Table Data Sources

At the heart of the usefulness of the Auto Tables is to quickly map a list of records to a table in a PDF Form. For this a Data Source must be determined. To make it easy, UXstorm PDF uses the same methodology as ServiceNow to get related records using Related Lists.

In addition to using Related Lists, two other Data Sources are supported:

  • Catalog Table Variable supports using a Catalog Table Variable as the Data Source. This requires that the Catalog Table Variable application from ServiceNow Share, be install and configured correctly.
  • Script supports retrieving the data for the table using a ServiceNow JavaScript.

For any Data Source, a list of records/rows are provided. Each column must be mapped in the table to the appropriate column from the Data Source. If the Data Source provides more rows that the table has defined, then any extra data will not be shown. If you have the possibility for a large table, ensure that the table is large enough and use the selectPages in the PDF Form's Post Script to remove pages with no data in the table.

With *Table Data Source specifying Related List, then the field Related List appears and will contain all related lists to the table specified on the PDF form. When generating the form, all records that would appear in that related list on the current record, will be provided in the Data Source.

This works very similar to Related List, but the relationship is not to the table specified on the PDF Form, but a Related List to a Reference Field on the table specified on the PDF Form. For instance, if a field assigned_to is a Reference Field to User[sys_user] table, then the Related List field will contain all the Related Lists to the User record. Then, for example, this could then be use to provide a Data Source for all CI's owned by the person the record is assigned to.

Catalog Table Variable

Specifies to use a Catalog Table Variable for the Data Source. A field will appear with all the valid Catalog Table Variables found for the specified catalog item on the PDF Form.

Multi Row Variable Set

Specifies to use ServiceNow’s Multi Row Variable Set for the Data Source. A field will appear with all the valid MRVS found for the specified catalog item on the PDF Form.

Script

This script is provided so that data from other types of relationships, formulas, conditionals, etc can be used for a Data Source. The script will have present a variable, current, that is a GlideRecord to the current record being used to generate the PDF. This can then be used to find/determine the appropriate data to retrieve for the table.

This script is unique in that it can be ran in two modes returnColumns and returnData.

In the script, if returnColumns is true, col must specify the columns in the table. The format is an array of objects with members name and label.

Here is an example returning three columns

 if (returnColumns) {
    cols = [
        { name: "firstName", label: "First Name"},
        { name: "lastName",  label: "Last Name"},
        { name: "city",      label: "Current City"}
    ];
 }

If returnData is true then *data must be set with the data for the table. The format is an array of objects where each member is the name of a column and the value is the value for that row/name.

Here is an example using hard coded data, returning 3 rows of data

if (returnData) {
    data = [
    { firstName: "Able", lastName: "Tutor", city: "Damascus"},
    { firstName: "Carmen", lastName: "Lee", city: "Columbus"},
    { firstName: "Danielle", lastName: "Smith", city: "Stillwater"},
    ];
}

With the two previous examples, a valid script would be:

/***********************************************************
 Script to gather all the rows and columns.  Two varibles
 is set by this script:

 returnColumns -- This contains a array of objects definining
                  the columns.  Each object contains name of
                  the column and the label for the column.

  data -- Array of objects.  Each element is a row in the table
          and each field is contained in the object for the row
          using the column name.

  This script is called with returnColumns set to true if the
  columns must be set.
  This script is called with returnData if the data is to be set.
  Enclose all logic to retrieve the table in a condition checking 
 for returnData.  If the script is called without requiring
  data, then the current record is not set and it may not be able
  to determine the data.

  A variable, current, is set to the GlideRecord of the record
  generating the PDF.

*****************************************************************/

// Example Table Script

 if (returnColumns) {
    cols = [
        { name: "firstName", label: "First Name"},
        { name: "lastName",  label: "Last Name"},
        { name: "city",      label: "Current City"}
    ];
  }
  if (returnData) {
    data = [
    { firstName: "Able", lastName: "Tutor", city: "Damascus"},
    { firstName: "Carmen", lastName: "Lee", city: "Columbus"},
    { firstName: "Danielle", lastName: "Smith", city: "Stillwater"},
    ];
  }

Column Mapping

When the Table Data Source is properly configured, then the columns for the table can be mapped. This is done by selecting the column from the Columns related list on the Table form.

When the Column is mapped, a Field can be chosen from the Related list or a Column can be chosen from a Script or Catalog Table Variable. This will designate what data from each row in the Data Source to map to this column in the table.

Format Script

To provide extra formatting capabilities, you can use a Format Script to modify the data before it's written into the table cell. Check Run Format Script to edit the Format Script.

This script runs the same as the Direct Field mapping Format Script with the field value being set to the value to place in the table cell.

Field Description
current This is different depending on the Table Data SourceScript: current is the current record generating the PDFCatalog Table Variable: current is the current record generating the PDFRelated List: current is the current related list record
ctvField The Catalog Table Variable field value. This is used to determine advanced information about the CTV Field. For instance, if you want to display information about a related field such as location, this object will contain the related table name and sys_id.
value Set to the formatted value to place in the table cell.
Here is an example of a Format Script to convert the cell text to lowercase.
/**************************************************
 * Format Script.
 *
 * Set variable answer to the new format.
 *
 * Variables:
 *
 * current -- This is different depending on the Table Data Source
 *            Script: current is the current record generating the PDF
 *            Catalog Table Variable: current is the current record generating the PDF
 *            Related List: current is the current related list record
 *
 * value   -- The current value of the mapped field/variable
 * ctvField -- The Catalog Table Variable field value. This is used to determine
 *             advanced information about the CTV Field.  For instance, if you
 *             want to display information about a related field such as location,
 *             this object will containt the related table name and sys_id.  The
 *             structure of such a field is:
 *
 *    {
 *         "field": "location",
 *         "label": "Location",
 *         "mandatory": "",
 *         "type": "reference",
 *         "giveFocus": "",
 *         "reference": "cmn_location",
 *         "choiceOptions": null,
 *         "refQual": "",
 *         "onChangeFunc": "",
 *         "cellCSS": "",
 *         "labelCSS": "",
 *         "show": "always",
 *         "imageSrc": "",
 *         "value": "0002c0a93790200044e0bfc8bcbe5df5",
 *         "display": "2-10-1 Yurakucho, Chiyoda-ku, Tokyo",
 *         "relatedTable": "",
 *         "disabled": true
 *       }
 *
 * Example:
 *
 * answer = value.substring(0,10);   // Make sure the value is at most 10 chars
 *
 * Or for a CTV with a related field.
 *
 * var gr = new GlideRecord(ctv.reference);
 * gr.get(ctv.value);
 * answer = gr.contact + '';   // Show the location's contact insteand of location name
 */

answer = value.toLowerCase();