There are lots of ways to create custom print layouts. This is my version using a SP Widget.
In the example below, I am using widget to print out details from an incident. However you can customize the widget anyway you would like. Here are just some of possibilities:
Add data from other data tables
Add a company logos or other graphics
Create custom calculations
Make some fields editable for additional print detail
Use a REST API call to pull in data from another application
Style the fields with CSS
SCREENSHOT
Code
Portal
I like to create a portal to contain all the print layouts
Title: Print
URL suffix: print
Page
Title: Print Record
ID: print_record
Add Custom Print Widget to Page after Widget is created
UI Action
Use a UI Action to run the custom print
Name: Print Record
Table: <your choice>
Action name: printRecord
Client: true
OnClick: printRecord()
Form button: true
Show update: true
Isolate Script: false
Script:
function printRecord() {
win = window.open("print?id=print_record&table_name="+g_form.getTableName()+"&sys_id="+ g_form.getUniqueValue());
win.focus();
return false;
}
Widget: Incident Custom Print
HTML
<div>
<div class="text-right no-print">
<button class="btn btn-primary pull-right" type="submit" onclick="javascript: window.print();">
<div class="fa fa-print"></div>
<span>Click to Print</span>
</button>
</div>
<table class="borderless">
<tr>
<td><h3 class="panel-body" style="cursor: default"> Detail</h3></td>
</tr>
</table>
<div class="panel panel- b" >
<div class="panel-heading">
<h4 class="panel-title" style="cursor: default"> - </h4>
</div>
<div class="panel-body">
<dl class="ticket-fields" ng-if="data.fields.length > 0">
<dt class= "col-md-6 col-sm-12 col-xs-6 break-word"
ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)"
ng-repeat-start="field in data.fields"></dt>
<dd class= "col-md-6 col-sm-12 col-xs-6 break-word"
ng-repeat-end ng-switch="field.type"
ng-if="field.value && (field.type != 'decimal' || field.type == 'decimal' && field.value != 0)">
<div ng-switch-when="glide_date_time" title="">
<sn-time-ago timestamp="::field.value" />
</div>
<div ng-switch-default ></div>
</dd>
</dl>
<div ng-if="data.variables.length > 0" ng-init="c.variable_toggle = true">
<button class="h4 options-btn btn" ng-click="c.variable_toggle = !c.variable_toggle" aria-expanded="" aria-controls="variables-toggle">
<span style="font-size: 12px;" class="glyphicon" ng-class="c.variable_toggle ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'"></span>
$
</button>
<div ng-if="c.variable_toggle" id="variables-toggle" aria-hidden="">
<hr role="presentation">
<div class="m-b break-word" ng-repeat="variable in data.variables | filter:">
<label class="m-t-xs m-b-none text-muted"><b></b></label>
<div ng-if="!variable.multi_row"><span class="pre-wrap"></span></div>
<div ng-if="variable.multi_row">
<a href="javascript:void(0)" uib-popover-template="'sp_multirow_vs_summarizer.html'" popover-title=""
popover-placement="auto left" popover-append-to-body="true" popover-trigger="outsideClick">${Click to view}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
CSS
.header {
font-weight:bold;
padding: 10px 290px 10px 10px;
}
.pre-wrap {
white-space: pre-wrap;
}
.ticket-fields {
margin-left: -7px;
margin-right: -8px;
-webkit-margin-before: 0;
-webkit-margin-after: 0;
dt {
//font-weight: normal;
margin-bottom: 10px;
}
dd {
margin-bottom: 10px;
}
}
@media print
{
.no-print, .no-print *
{
display: none !important;
}
}
table, td {
border-color:#000;
border-style:solid;
}
table {
border-collapse:collapse;
border-spacing:0;
border-width:0 0 1px 1px;
margin-top:14px;
}
td {
border-width:1px 1px 0 0;
margin:0;
padding:4px;
vertical-align:bottom;
}
table.borderless, table.borderless td {
border:0px;
border-style:none;
}
table.borderAroundMe {
border:1px;
border-style:solid;
}
td.header {
background-color:#a7a7a7 !important;
color:#fff !important;
font-weight:bold;
}
br.page-break {
display:block;
page-break-before:always;
}
table
tr {
page-break-inside:avoid;
page-break-after:auto
}
td {
page-break-inside:avoid;
page-break-after:auto
}
Server Script
(function() {
data.sys_id = $sp.getParameter("sys_id");
data.table = $sp.getParameter("table_name");
var gr = new GlideRecord(data.table);
gr.get(data.sys_id);
//var gr = $sp.getRecord();
if (gr == null)
return;
data.canRead = gr.canRead();
if (!data.canRead)
return;
var fields = $sp.getFields(gr, 'number,caller,category,subcategory,service,cmdb_ci,contact_type,state, impact,urgency,priority,assignment_group,assigned_to,problem_id,rfc,caused_by,sys_created_on,sys_updated_on,short_description,description,close_code,close_notes');
//if (gr.getValue("sys_mod_count") > 0)
// fields.push($sp.getField(gr, 'sys_updated_on'));
data.number = $sp.getField(gr, 'number').display_value;
data.short_description = $sp.getField(gr, 'short_description').display_value;
data.tableLabel = gr.getLabel();
data.fields = fields;
data.variables = new GlobalServiceCatalogUtil().getVariablesForTask(gr, true);
})();