Category

S-Docs Cookbook

Formatting Phone Fields

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

S-Docs provides a number of different options for formatting Salesforce phone fields in your documents.

You can use any of the formatting options described in the Syntax section of this article. Simply replace the formatting shown below with your desired formatting.

For merge fields, place your formatting within the curly braces after the field syntax, as shown below.

[code lang="html"]{{!Contact.mobilephone ###-###-####}}[/code]

For related lists, use the format-number column attribute to add your phone field formatting, as shown below.

[code lang="html"]<column format-number="###-###-####">Contact.mobilephone</column>[/code]

Syntax

S-Docs accepts the following phone field formatting:

For 10-Digit Numbers

[code lang="html"]###-###-####
(###)###-####
(###) ###-####
(###)-###-####
###.###.####
### ### ####[/code]

For 11-13 Digit Numbers

[code lang="html"]+### ###-###-####
+### (###)###-####
+### (###) ###-####
+### (###)-###-####
+### ###.###.####
+### ### ### ####[/code]

Note: You can use the formatting for 11-13 digit numbers with 10-digit phone number fields to add a +1 to the beginning of the number.

Considerations

  • If your phone field is populated with an 11-13 digit number, but the formatting doesn't include +### at the beginning, it will be merged into your document in its original formatting.
  • Only 10-13-digit numbers are supported. If your phone field is populated with a number that has less than 10 digits or greater than 13 digits, it will be merged into your document in its original formatting.


DOC-NEW

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

The DOC-NEW template format allows you to create .doc templates with separate sections that behave like next-page section breaks in Microsoft Word. Sections are subdivisions of a single document and can be formatted separately from one another; for example, one section can be landscape while the other is portrait. The DOC-NEW template format provides a section-based editor that makes it easy to create and edit different sections.

Access DOC-NEW

Note: DOC-NEW is available in S-Docs version 4.317 and above.

To access the DOC-NEW template format, you'll need to add it as a Template Format value on the SDoc Template object. From the setup menu, navigate to the Object Manager and find the SDoc Template object.

Next, navigate to the Fields and Relationships tab, and click on the Template Format field.

Scroll down to the Values section and click New. Type DOC-NEW into the text box, then click Save.

You've now successfully added the DOC-NEW option to the Template Format field. To create your first DOC-NEW template, simply select this option as your template format.

Convert DOC Templates to DOC-NEW

Note: The DOC-NEW conversion functions are available in S-Docs version 4.356 and above.

To quickly convert all existing DOC templates to the DOC-NEW format, you can run the following function in the Execute Anonymous window in the Developer Console:

[code lang="html"]SDOC.SDUtil.convertDOCTemplatesToDOCNEW();[/code]

Your original DOC templates will be cloned and saved as a backup.

To convert a subset of DOC templates to the DOC-NEW format, you can specify a WHERE clause as an input to the function. For example, the following function would convert all DOC templates with the string "to be converted" in their names.

[code lang="html"]SDOC.SDUtil.convertDOCTemplatesToDOCNEW('Name LIKE \'%to be converted%\'');[/code]

Using DOC-NEW

The DOC-NEW template editor is broken up into three elements: Page Settings, Section Content, and Conditional Logic. Let's examine each of these elements now.

Page Settings

The dedicated Page Settings tab is absent from the DOC-NEW template editor. Instead, the DOC-NEW template editor's page settings appear at the top of each section as follows:

The Page Settings element allows you to:

[1] Delete the section.
[2] Edit the section's units of measurements, page width, and page height. The page width and height can be used to change the section's orientation; for example, by default a section is set to 8.5 x 11 inches, or portrait orientation. Altering these measurements to 11 x 8.5 inches would change the section to landscape orientation.
[3] Edit the section's margins.

Note: The Unit of Measure setting applies to all measurements in the Page Settings.

Section Content

The Section Content element allows you to edit the header, body, and footer of each section. It appears as follows:

You can add content into a section's three editors just like you would in any other S-Docs template, including merge fields, related lists, and component templates. You can also edit the template source in each section's three editors.

Note: CSS applied in one editor will only apply to content in that editor. For example, if CSS is added to the footer of section 1, it will only affect content in the footer editor of section 1.

Conditional Logic

The Conditional Logic element allows you to input conditions that dictate whether or not a section is rendered in the final document. It appears as follows:

[1] Input your render conditions into this field using the same syntax as the S-Docs Conditional Logic feature, omitting the render tags. If conditions in this field evaluate to "true," the section will be included in the final document; otherwise, it will be omitted.
[2] This element also allows you to create a new section by clicking Add New Section.

Creating New Sections

When you create a new section by clicking Add New Section at the bottom of the section editor, you'll see a few more options appear for every section.

[1] Change a section's position in the document by using the Move Section Up and Move Section Down buttons.
[2] Reuse page settings defined in another section. Choosing another section's page settings will hide the page settings options in the current section.
[3] Reuse another section's header and footer. Choosing another section's header or footer will hide the header and footer editors in the current section, respectively.

Note: When using a header or footer across multiple sections, ensure the same page settings are applied to each section.

That's all there is to it! DOC-NEW gives you the flexibility of creating section-based templates without ever leaving Salesforce.


Sandbox Refresh Considerations

By Best Practices, Documentation, S-Docs Cookbook No Comments

migrate
migration
import
upload
transfer

Introduction

When you refresh a sandbox org that you are using with S-Docs, there are a few considerations to keep in mind to ensure you can continue using S-Docs like normal once the refresh is complete. This article will detail what actions to take when you refresh your sandbox from production.

You may also want to view Salesforce's Sandbox Considerations article for additional tips on what to do when refreshing your sandbox org.

Note: You do not need to reinstall S-Docs or S-Sign when you refresh your sandbox.

Record IDs

Although sandbox record data will be identical to production record data after a sandbox refresh, sandbox and production record IDs are always unique between different orgs. S-Docs can be affected by this in two main ways.

Template Preview IDs

If you're using the template editor Save & Preview feature, record IDs in the Preview ID field will point to production records after a sandbox refresh. You must replace these IDs with corresponding sandbox record IDs. Record IDs can be found in your browser's URL bar when you're viewing a record.

The Preview ID field can be found in the template editor under the Advanced Options tab.

S-Docs Template IDs 

If you've referenced S-Docs template IDs anywhere in your org, they will point to production template records after a sandbox refresh. You should replace these references with plain text template names. You can also replace them with sandbox template IDs, but we recommend using the template name since record names don't change between production and sandbox orgs. This way, you won't have to update these references after future sandbox refreshes, or when you migrate templates from sandbox to production orgs.

S-Docs template IDs are commonly referenced using the doclist parameter with document automation with S-Docs Jobs, mass merge, or one-click/zero-click S-Docs buttons.

URLs

Any references to login.salesforce.com must be changed to test.salesforce.com, and any references to your Salesforce production domain (e.g. na132.salesforce.com) must be changed to your Salesforce sandbox domain (e.g. cs5.salesforce.com). S-Docs can be affected by these URLs in the following places.

Custom Settings

From the setup menu, type "Custom Settings" into the Quick Find bar and click Custom Settings in the dropdown menu. Find the SDocsSettings entry and click Manage.

Click the Edit link next to SDocsSettings.

Then, ensure that any references to the Salesforce production login URL or your Salesforce production domain are updated. In the following example, #1 would need to be updated to test.salesforce.com, and #2 would need to be updated to a sandbox domain, such as cs5.salesforce.com.

You may also need to update the ConnectedAppUserName if you are using the Run As User feature. This username is used as the "run as" user if the provided username is not found or not valid. It must be a valid Salesforce username in your sandbox org, and the user must be active.

Remote Site Settings

If you have a remote site setting configured for the Salesforce production login URL or your Salesforce production domain, you'll need to add new remote sites for your Salesforce sandbox login URL and your Salesforce sandbox domain.

From the setup menu, type "Remote Site" into the Quick Find bar, click Remote Site Settings in the dropdown menu, and click New Remote Site to add your sandbox remote sites.

Run As User Connected App

If you're using the Run As User feature, you'll need to update your Connected App's Callback URL. From the Setup menu, type "Apps" into the Quick Find bar, then click App Manager in the dropdown menu. Find the SDocs Connected Apps entry, click the dropdown arrow, and click Edit.

Scroll down to the API (Enable OAuth Settings) section, and update the Callback URL to:

https://test.salesforce.com/services/oauth2/callback

Click Save.

S-Sign Considerations

After refreshing a sandbox from production, your S-Sign Site will be updated to your production site. The production site URL includes your Salesforce production domain, which will not function properly in your sandbox and cannot be edited.

Because of this, you must deactivate the production site and create a new site with your Sandbox domain. Click here to view instructions for creating a new site for S-Sign.

After recreating your S-Sign site, you'll need to provide S-Sign with your site's information and assign guest user permissions once more. Click here to view instructions.


Adding Page Numbers to Your DOC Template

By Documentation, General Solutions, S-Docs Cookbook No Comments

Add Page Numbers in the Header or Footer

To add pagination to your DOC templates, you can insert the following code into the Source editor of the Header or Footer tabs in the template editor:

[code lang="html"]Page Number: <span style="mso-field-code: PAGE "></span>
Total Pages: <span style="mso-field-code: NUMPAGES "></span>[/code]

Note: This code is not functional in the template body and must be used in either the Header or Footer tabs.

Example

The following example code was inserted into the Footer tab.

When the document is generated, the pagination appears as follows:


Call Apex Classes in S-Docs Templates

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

The S-Docs Callable Apex feature allows you to generate merge field or table values in your S-Docs templates via custom Apex code. This feature is useful if your business requirements necessitate the use of advanced logic that can't be defined directly within an S-Docs template.

You can include as many callable apex classes in your template as you'd like, but we recommend writing a single class with multiple functions or arguments, as opposed to multiple classes.

Apex Class

Your Apex class must be global and return a <string, string> map where keys are represented by field names and values are represented by field values. The following example provides a basic overview of an acceptable class, however you can use multiple functions or arguments in your class.

[code lang="html"]global class CallableApexTest implements Callable {
public Object call(String action, Map<String,Object> args) {
switch on action {
when 'getMergeFieldMapExample1' {
return this.getMergeFieldMapExample1((String)args.get('recordId'));
}
when else {
throw new ExtensionMalformedCallException('Method not implemented');
}
}
}
public class ExtensionMalformedCallException extends Exception {}
public Map<String,String> getMergeFieldMapExample1(String recordId) {
Opportunity opp = [SELECT Id FROM Opportunity WHERE Id=:recordId]; // Base Object Record
Map<String,String> mergeFieldMapExample = new Map<String,String>{
'Field_1' => 'Value_1',
'Field_2' => 'Value_2',
'Field_3' => 'Value_3'
};
return mergeFieldMapExample;
}
}
[/code]

Callable Syntax

To call your Apex class in your S-Docs template, navigate to the Source editor and use syntax similar to the following example:

[code lang="html"]<!--{{!
<callable>
<class>CallableApexTest</class>
<action>getMergeFieldMapExample1</action>
<args>{ "recordId" : "{{!Opportunity.Id}}", "recordId" : "{{!Opportunity.Field__c}}" }</args>
</callable>
}}-->
Field_1: {{!Field_1}}<br />
Field_2: {{!Field_2}}<br />
Field_3: {{!Field_3}}<br />[/code]

Lines [1-2] open the callable Apex statement. The Apex class name is referenced in <class> tags on line [3]. The function of the Apex class is referenced in <action> tags on line [4]. Arguments can optionally be referenced within <args> tags, as shown on line [5]. Finally, the statement is closed on lines [6-7].

You can include any merge fields referenced in your <string, string> map anywhere in your S-Docs template. The three fields from the example map are included on lines [8-10].

The example above would render the following document:

Example Use Case

To further understand this feature, let's take a look at an example use case.

Let's say that the Opportunity object contains a custom multi-select picklist field with 6 different products.

We'd like our document to display a list of 6 sections that output a letter that corresponds to the product's positioning in the chosen list. In other words, if all products are chosen, the S-Docs document should render like this:

But if Products 1, 3, and 6 are chosen, the S-Docs document should render like this:

To easily accomplish this, we can write an Apex class and then call that class in our S-Docs template. The Apex class for this function looks like this (and includes comments for clarification):

[code lang="html" highlight="16,29"]global class SDocsCallable implements Callable {
public Object call(String action, Map<String,Object> args) {
switch on action {
when 'getSectionMergeFieldMap' {
return this.getSectionMergeFieldMap((String)args.get('recordId'));
}
when else {
throw new ExtensionMalformedCallException('Method not implemented');
}
}
}

public class ExtensionMalformedCallException extends Exception {}
/*

Example input:
Opportunity with a Products__c value of:
Product 1;Product 3;Product6

To be clear:

'Product 1' // Included
'Product 2' // NOT Included
'Product 3' // Included
'Product 4' // NOT Included
'Product 5' // NOT Included
'Product 6' // Included

Example output:
{
"Section 1" : "A",
"Section 2" : "",
"Section 3" : "B",
"Section 4" : "",
"Section 5" : "",
"Section 6" : "C"
}
(these are mapped to merge fields in the S-Docs Template like so: {{!Section_1}} )

*/
public Map<String,String> getSectionMergeFieldMap(String recordId) {
String Products = [SELECT Products__c FROM Opportunity WHERE Id=:recordId].Products__c;
List<String> productNames = new List<String>{
'Product 1',
'Product 2',
'Product 3',
'Product 4',
'Product 5',
'Product 6'
};
Map<String,String> mergeFieldMap = new Map<String,String>();
Integer currentChar = 65;
for (Integer i = 0; i < productNames.size(); i++) {
String mergeFieldValue = '';
if (Products.contains(productNames[i])) {
mergeFieldValue = 'Section ' + String.fromCharArray( new List<Integer> { currentChar } );
currentChar++;
}
mergeFieldMap.put('Section_' + (i + 1), mergeFieldValue);
}
return mergeFieldMap;
}
}
[/code]

Our S-Docs template Source code for this use case looks like this:

[code lang="html"]<!--{{!
<callable>
<class>SDocsCallable</class>
<action>getSectionMergeFieldMap</action>
<args>{ "recordId" : "{{!Opportunity.Id}}" }</args>
</callable>
}}-->Section 1: {{!Section_1}}<br />
Section 2: {{!Section_2}}<br />
Section 3: {{!Section_3}}<br />
Section 4: {{!Section_4}}<br />
Section 5: {{!Section_5}}<br />
Section 6: {{!Section_6}}<br />[/code]

When we generate the document, the correct letters correspond to the correct sections:

Callable Apex - Line Items

You can also call apex classes to generate table values in your S-Docs templates - this is done by placing your callable statement within a <lineitems> statement and including one of three return types in <returntype> tags. The three return types are SDocTable, ListSObject, and XML.

SDocTable

The SDocTable return type allows you to generate highly customized tables using logic otherwise not available within S-Docs templates. In an S-Docs template, the callable syntax for the SDocTable return type looks similar to the following:

[code lang="html" highlight="6"]<table><!--{{!<LineItems>
<callable>
<class>CallableApexTestlineitems</class>
<action>getLineItemsAsSDocTable</action>
<args>{ "arg1" : "val1" }</args>
<returntype>SDocTable</returntype>
</callable>
<class>table123</class>
<column>product_rate_category</column>
<column>domestic_rate_adjustment_1</column>
<column>domestic_rate_adjustment_2</column>
<column>domestic_rate_adjustment_3</column>
</LineItems>}}-->
</table>[/code]

The callable syntax is nested inside of a <LineItems> statement. Note the addition of <returntype> tags in line 6, which specify that the apex class will build and return an SDocTable. After the <callable> tags are closed out, the <LineItems> statement is written as normal.

The corresponding Apex class might look similar to the following:

[code lang="html"]global class CallableApexTestlineitems implements Callable {

public Object call(String action, Map<String,Object> args) {
switch on action {
when 'getLineItemsAsSDocTable' {
return this.getLineItemsAsSDocTable((String)args.get('recordId'));
}
when else {
throw new ExtensionMalformedCallException('Method not implemented');
}
}
}

public class ExtensionMalformedCallException extends Exception {}

public Map<String,String> getScheduleMergeFieldMap(String recordId) {
return new Map<String,String>{ 'Schedule_1' => 'Schedule A', 'Schedule_3' => 'Schedule B'};
}

public SDOC.SDUtil.SDocTable getLineItemsAsSDocTable(String recordId) {
Map<String,List<String>> rateCategoryMap = new Map<String,List<String>>{
'Category C' => new List<String>{ 'C1', 'C2', 'C3' },
'Category A' => new List<String>{ 'A1', 'A2', 'A3' },
'Category B' => new List<String>{ 'B1', 'B2', 'B3' }
};
List<String> rateCategoryKeysSorted = new List<String>{
'Category A',
'Category B',
'Category C'
};
SDOC.SDUtil.SDocTable table = new SDOC.SDUtil.SDocTable();
for (String rateCategory : rateCategoryKeysSorted) {
SDOC.SDUtil.SDocTableRow row = new SDOC.SDUtil.SDocTableRow();
row.cells.add(new SDOC.SDUtil.SDocTableCell('product_rate_category', rateCategory));
Integer draNum = 1;
for (String domesticRateAdj : rateCategoryMap.get(rateCategory)) {
row.cells.add(new SDOC.SDUtil.SDocTableCell('domestic_rate_adjustment_' + draNum, domesticRateAdj));
draNum++;
}
table.rows.add(row);
}
return table;
}
}[/code]

The output document would look similar to this:

ListSObject

The ListSObject return type allows you to return a list of records similar to a <LineItemsSOQL> statement. Unlike <LineItemsSOQL> statements, however, you're given much more flexibility since the query is written in an Apex class. For example, you could filter records based on rich-text field data, which isn't normally possible. In an S-Docs template, the callable syntax for the ListSObject return type looks similar to the following:

[code lang="html" highlight="6"]<table><!--{{!<LineItems>
<callable>
<class>CallableApexTestlineitems</class>
<action>getLineItemsAsListSObject</action>
<args>{ "recordId" : "{{!Opportunity.Id}}" }</args>
<returntype>ListSObject</returntype>
</callable>
<class>table499</class>
<column>Name</column>
<column>StageName</column>
<column>Account.Name</column>
<column>Account.Owner.Name</column>
</LineItems>}}-->
</table>[/code]

The corresponding Apex class might look similar to the following:

[code lang="html"]global class CallableApexTestlineitems implements Callable {

public Object call(String action, Map<String,Object> args) {
switch on action {
when 'getLineItemsAsListSObject' {
return this.getLineItemsAsListSObject((String)args.get('recordId'));
}
when else {
throw new ExtensionMalformedCallException('Method not implemented');
}
}
}

public class ExtensionMalformedCallException extends Exception {}

public List<SObject> getLineItemsAsListSObject(String recordId) {
return [SELECT Name, StageName, Account.Name, Account.Owner.Name FROM Opportunity WHERE AccountId != null LIMIT 3];
}
}[/code]

The output document would look similar to this:

XML

The XML return type allows you to merge XML data into a table in your document. The XML can be hardcoded in your apex class or pulled from an external system, making this option great for merging external data into your templates. In an S-Docs template, the callable syntax for the XML return type looks similar to the following:

[code lang="html" highlight="6,9"]<table><!--{{!<LineItems>
<callable>
<class>CallableApexTestlineitems</class>
<action>getLineItemsAsXMLString</action>
<args>{ "arg1" : "val1" }</args>
<returntype>XML</returntype>
</callable>
<class>table499</class>
<listname>products</listname>
<column>productname</column>
<column>productdescription</column>
<column>productcode</column>
</LineItems>}}-->
</table>[/code]

Note the addition of <listname> tags before the table <column> tags, which should be the same as the parent tags in your XML string. The corresponding Apex class might look similar to the following:

[code lang="html"]global class CallableApexTestlineitems implements Callable {

public Object call(String action, Map<String,Object> args) {
switch on action {
when 'getLineItemsAsXMLString' {
return this.getLineItemsAsXMLString((String)args.get('recordId'));
}
when else {
throw new ExtensionMalformedCallException('Method not implemented');

}
}
}

public class ExtensionMalformedCallException extends Exception {}
public String getLineItemsAsXMLString(String recordId) {
return ''
+ '<products>'
+ ' <productname>Apple</productname>'
+ ' <productdescription>Red fruit</productdescription>'
+ ' <productcode>4016</productcode>'
+ '</products>'
+ '<products>'
+ ' <productname>Banana</productname>'
+ ' <productdescription>Yellow fruit</productdescription>'
+ ' <productcode>4011</productcode>'
+ '</products>'
+ '<products>'
+ ' <productname>Pear</productname>'
+ ' <productdescription>Green fruit</productdescription>'
+ ' <productcode>3012</productcode>'
+ '</products>';
}
}[/code]

The output document would look similar to this:

As you can see, the callable Apex feature allows you to perform complex functions in your documents that otherwise aren't available in the S-Docs template editor.


Selecting Email Recipients

By Documentation, General Solutions, S-Docs Cookbook No Comments

When you're ready to email your documents, the S-Docs email page provides two options for quickly selecting email recipients.

Contact / User Lookup

The Contact / User Lookup field allows you to search for any contacts or users in your org.

The S-Docs contact user lookup field

Click inside the field to open the Contact / User Lookup window.

The contact lookup window

To find contact or user information, [1] enter a search term and click Go. You can then [2] switch between all Contact and User results that match your query. [3] Click a Contact or User name to insert their email address into the email To field. You can also copy and paste the address into the CC or BCC fields as needed.

Contact Quick Pick

The Contact Quick Pick field allows you to quickly choose any Contact records related to your base record.

Note: S-Docs will search for any lookup relationships between your base object and the Contact or Account objects to populate this picklist.

The S-Docs contact quick pick menu

Contacts that you select will be added to the To field, separated by commas. You can also copy and paste the address into the CC or BCC fields as needed. When a contact is added, an Edit link will appear next to their name. You can click this link to open and edit the contact record in a new window.

Troubleshooting

Why Can't I access the Contact / User Lookup or the Contact Quick Pick?
If the Contact / User Lookup and Contact Quick Pick fields are missing, this means that an admin has locked the To field for one of the documents that you are emailing (this includes HTML email body templates).

If the To field is locked for any of the templates that you generate, you will not be able to edit this field, and the recipient selection options will not appear.

Where are the CC and BCC fields?
If the CC or BCC fields are missing, this means that an admin has locked those fields for one of the documents that you are emailing (this includes HTML email body templates).

The S-Docs email page without CC or BCC fields

Why is my email failing to send?
By default, S-Docs links outbound emails to the contact record with a matching email address; Salesforce requires this linkage. If you try to send an email to an email address that is not listed under any Contact record in your org, S-Docs will attempt to link it to a single dummy contact record called "No Contact Record." This contact record is created automatically by the S-Docs package to handle this linkage, and is immediately deleted once the email is sent.

If your org has implemented validation rules that require additional contact fields to be completed, then the S-Docs package will not be able to create this contact record. In this case, you can create an Apex trigger to ensure your emails can be sent. Click here to learn more about solving email deliverability issues.


Overview: Translating S-Docs

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

Multinational companies with employees and customers based around the globe need to do business in a variety of different languages. S-Docs provides a number of language translation options that you can leverage to give your users and customers a seamless experience, whether they're using S-Docs internally or viewing generated documents. This article will go over key points of consideration and provide you with the necessary resources for translating S-Docs based on your requirements.

The two main aspects of S-Docs that can be translated are:

  1. The S-Docs user interface that admins and business users interact with inside of Salesforce
  2. The content of your generated documents that customers and internal stakeholders view

This article will explain how to ensure that both of these aspects are translated based on the languages of your Salesforce users, customers, or both.

Translate the S-Docs UI for Salesforce Users

If your business has multinational employees that need to generate documents, translating the S-Docs user experience can be imperative to allowing them to work as efficiently and seamlessly as possible. S-Docs allows you to translate the entire document generation experience, from selecting templates to sending emails. There are two options for translating the S-Docs UI.

Note: Currently, the S-Docs template editor is only available in English. However, fields listed in the Insert Field menu will appear in the user's Salesforce language.

Download Translations

S-Docs provides preconfigured translations for two languages: Spanish and German.

Translating the user experience using our preconfigured translations is a simple matter of downloading the desired translation template and adding the translation parameter to your S-Docs button. Once this is completed, the S-Docs user experience will be translated for users that click this button.

Click here for detailed instructions on downloading translation templates and adding the translate parameter to your S-Docs button.

Define Your Own Translations

If your users speak a language other than Spanish or German (or you want to write your own translations for Spanish or German) you can also translate the S-Docs UI yourself by navigating to the S-Docs translation page and translating each field manually.

Click here for detailed instructions on defining your own translations.

Translate Document Content

For companies that do business with customers around the globe, sending documents in your customers' native language can be vital to delivering great customer experiences.

Translating Data

Merge Fields
S-Docs leverages the Salesforce Translation Workbench to allow you to translate any Salesforce field label and any Salesforce picklist field data (other forms of field data, such as text, cannot be translated because they are not supported by the Translation Workbench).

Ensuring that your documents are generated with translated field labels and picklist field data is a simple process:

  1. Define translations in the Salesforce Translation Workbench
  2. Add the translate parameter to your S-Docs button (or set the language at the template level)
  3. Add the translate attribute to your merge fields

Click here for detailed instructions on translating field labels and field data.

Related Lists
Related list data can also be translated using the toLabel() function within a direct soql query.

Click here for more information on translating related lists and lookup fields.

Formatting International Characters

If your template contains international characters such as Japanese or Hebrew, there are a few steps you can take to make sure the text in your output documents are formatted correctly.

Template Settings
If your template contains international characters, you should check the Template contains international characters (Unicode fonts) box under the Document Options tab. If your international characters still don't render correctly, you can set the Unicode Enforcement Level to Strict under the same tab. This will override any font settings being applied to merge fields.

If your documents are written in a right-to-left language like Arabic or Hebrew, you can do one of the following:

  1. Use the rtl merge field attribute to transform merge field data to be right-to-left. This will not transform static text.
  2. Use <rtl> tags in the template source to transform both merge field data and static text to be right-to-left.

Click here for more information on transforming right-to-left languages.


Using Arithmetic Functions

By Documentation, General Solutions, S-Docs Cookbook No Comments

Arithmetic Function Syntax

S-Docs templates support arithmetic functions for both static numbers and numeric fields. All functions should be written using standard Salesforce math operators. S-Docs will evaluate all functions using the standard mathematical order of operations.

To use arithmetic functions in your S-Docs templates, simply enclose the function within <MATH> tags.

The following example uses both static numbers and numeric fields.

[code lang="html"]<MATH>(2 + 1) / 3</MATH>

<MATH>( {{!Opportunity.Num1__c}} + {{!Opportunity.Num2__c}} ) / {{!Opportunity.Num3__c}}</MATH>[/code]

Note: You can use negative numbers in your functions. Keep in mind that subtraction functions should include a space on either side of the minus symbol to differentiate between negative numbers and subtraction functions. For example, to evaluate three minus two, use the following syntax:

[code lang="html"]<MATH>3 - 2</MATH>[/code]

Instead of something like this:

[code lang="html"]<MATH>3 -2</MATH>[/code]

Formatting Numbers

To format the result of your arithmetic function, use the format-number attribute within the <MATH> tag as shown below, but not within the merge fields.

[code lang="html"]<MATH format-number="#,###.##">{{!Opportunity.amount}} - {{!Opportunity.expectedrevenue}}</MATH>[/code]

Note: When you insert numeric fields using the Insert Field button, number formatting is added to the merge fields automatically. Ensure that you remove this formatting when using merge fields within arithmetic functions.

Arithmetic Functions with Date Fields

You can also use date fields or static dates within your arithmetic functions. The two main types of date math supported are:

  1. Adding/subtracting time from a date
  2. Evaluating days/months between dates

Both types of date math require the use of the type="date" attribute within your <MATH> tag.

Note: Static dates must be written in the yyyy-MM-dd format (for example, January 1, 2021 would look like 2021-01-01).

Adding/Subtracting Time

To add or subtract days, months, or years from any date field, use the following syntax (where X equals the number of days, months, or years you would like to add or subtract from the value of the date field):

[code lang="html"]<MATH type="date">{{!Opportunity.createdByDate}} + DAYS(X) - MONTHS(X) + YEARS(X)</math>[/code]

Evaluating Time Between Dates

To evaluate the time between two dates, use the following syntax:

[code lang="html"]<MATH type="date">DaysBetween({{!Opportunity.createdByDate}},{{!Opportunity.closedate}}</MATH>
<MATH type="date">MonthsBetween({{!Opportunity.createdByDate}},{{!Opportunity.closedate}}</MATH>
<MATH type="date">YearsBetween({{!Opportunity.createdByDate}},{{!Opportunity.closedate}}</MATH>[/code]

Formatting Dates

To format the result of your arithmetic date function, use the format-date attribute within the <MATH> tag as shown below, but not within the merge fields.

[code lang="html"]<MATH type="date" format-date="M/dd/yyyy">[/code]

Note: When you insert date fields using the Insert Field button, date formatting is added to the merge fields automatically. Ensure that you remove this formatting when using date fields within arithmetic functions.

DOCX Syntax

When using arithmetic functions in DOCX templates, use lowercase <math> tags and be sure to enclose the entire function within square brackets, as shown in the following example.

[code lang="html"][<math>(2 + 1) / 3</math>]
[<math>( {{!Opportunity.Num1__c}} + {{!Opportunity.Num2__c}} ) / {{!Opportunity.Num3__c}}</math>][/code]


PDF-Upload

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

The S-Docs PDF-Upload feature allows you to upload any preexisting PDF to the S-Docs template editor. Once your PDF is uploaded, you can use the intuitive user interface to drag and drop merge fields onto your document. There's no need to copy and paste when using this feature: simply grab the merge field and place it wherever you'd like. This article will explain how to access the PDF-Upload feature, navigate the user interface, and customize your merge fields with your own styling. Before we dive in, here's a quick look at the feature in action:

Access PDF-Upload

To access the PDF-Upload feature, you'll need to add it as a Template Format value on the SDoc Template object. From the setup menu, navigate to the Object Manager and find the SDoc Template object.

Next, navigate to the Fields and Relationships tab, and click on the Template Format field.

Scroll down to the Values section and click New. Type PDF-UPLOAD into the text box, then click Save.

You've now successfully added the PDF-Upload option to the Template Format field. To create your first PDF-Upload template, simply select this option as your template format.

Using PDF-Upload

We will now go over basic usage of the PDF-Upload feature. To begin, navigate to the Template Editor for your PDF-Upload template, then click Upload PDF File under the Upload PDF tab, and choose a PDF.

Your PDF will appear on the right, and options will appear in the left menu.

PDF-Upload Settings

The two menus available to you are [1] S-Docs Fields, which is where you'll select your merge fields to drag and drop, and [2] PDF-Upload Settings, which we'll go over now.

The PDF-Upload Settings allow you to [3] apply a default style for how all of your merge field data will display. This styling box accepts CSS syntax. For example, if we want our merge field text to be 20 pixels, we'd add font-size: 20px; into the box. This styling can also be overridden for any individual merge field.

S-Docs Fields

The S-Docs Fields menu allows you to create merge fields, apply individual styling, write conditional statements for those fields, and drag and drop them onto your document. If your PDF-Upload template is S-Sign enabled, this menu is also where you'll configure your signature tags. Click Create Another Field to get started.

This is the merge field menu.

Begin by [1] selecting the type of field. In this case, we're going to select merge field. If S-Sign was enabled for this template, we could also use this picklist to choose an S-Sign field. Next, [2] click Select Merge Field to find your merge field.

This will [1] bring up a list of all available fields for your base object, which in this case is Opportunity. You can also [2] select special merge fields to insert information such as document date, document name, or the name of the user generating the document. When you [3] select your merge field, you can access fields from related objects by clicking on fields with the > symbol next to them, just like you can with any other S-Docs template. This functionality allows you to go three levels deep. In this example, we're selecting the billing address for the account related to this opportunity. When you find your desired field, [4] click Insert Field.

As you can see, [1] the merge field was added into the Merge Field text area, meaning that this field will now display data from this opportunity's account billing address.

Remember the default merge field styling we applied earlier? You can [2] override this styling by adding additional CSS in the Additional Style field. If the default font size is 20 pixels, we could add font-size: 12px; here so that this field appears smaller than the rest.

You can additionally [3] insert conditional logic in the Render If field to render this field data only under certain conditions. This field accepts the same syntax as the S-Docs Conditional Logic feature, omitting the render tags. For example, let's say we only want the account's billing address to display if the opportunity is closed. We would add {{!Opportunity.stagename}} == 'Closed' into this field.

Finally, [4] drag your field (SDOCS INPUT ID=1) and place it on your PDF. Once you do, you can reset this field by clicking the Re-Drag Merge Field button, then drag it again. If you no longer need a field, you can [5] click Delete Field to delete it. [6] Click Create Another Field to repeat this process as many times as you'd like; there's no limit to the amount of merge fields you can use!

Once you've added all of your merge fields, it's time to generate your document!

As you can see, S-Docs merged in all of our Salesforce data in the areas that we specified. That's all there is to it! The PDF-Upload feature was designed to give you maximum flexibility and ease of use while maintaining the powerful feature functionality of S-Docs.

Note that the PDF-Upload templates work with the Live Edit feature. If your PDF-Upload template is Live-Edit enabled, users will be able to edit the field data after the document is generated.

PDF-Upload Limitations

While PDF-Upload is a robust and easy-to-use feature, there are a few limitations to consider when using it.

Note: Limitations to PDF files in general also apply to the PDF-Upload feature in addition to the limitations listed here.
  • PDF is the only file type supported
  • Pre-existing templates cannot be switched to the PDF-Upload template format
  • PDF-Upload templates cannot be switched to a different template format
  • The Header, Footer, Page Settings, and Auto Create Task tabs are not available
  • PDFs must be the traditional 8.5 x 11 inch size; landscape PDFs are not supported
  • The page count upper limit is currently around 15 pages. Keep in mind that certain contents increase template size and complexity (such as images or large amounts of text), which may have an effect on the page number limitation
  • To export templates and transfer them between orgs, use the S-Docs Template Migrator instead of manually exporting and importing the template data.
  • Component templates are not supported
  • Related Lists are not supported
  • Conditional statements need to be written out (the Insert Conditional Logic button is not supported)
  • Nested renders are not supported
  • Named queries are not supported
  • SOQL queries are not supported


Generate A Component Template For Each Record In A List Of Records

By Documentation, General Solutions, S-Docs Cookbook No Comments

Introduction

This article will teach you how to build an S-Docs template that will generate an entire component template within it for each record in a list of Salesforce records.

Let's say you wanted to create a single summary document of each opportunity related to an account, but you don't want to use the standard related list table formatting. You could remove the table CSS styling by using <class>none</class>, but this will only output your data as a comma-delimited list.

Using this feature, you could create a component template for your related opportunity data and format the data in any way you'd like. Then, when you generate a parent template that references the component template, you'll have a single document with your custom-formatted component template repeating itself for each opportunity record in your account's related list.

This feature works with any list of Salesforce records.

If you need to generate a separate document for each record in a list of records, click here.

This feature involves two templates:

  1. The parent template: This template will end up being the final document where all of the record data is displayed. It is the template that the end user will select and generate.
  2. The component template: S-Docs component templates are templates that are built to be displayed within other templates, and are not generated as stand-alone documents. This template will be used to configure how data from each record is displayed in the parent template. It won't be seen or selected by the end user. Although it's only one template, it will repeat itself in the parent template for each record in the list that you specify.

Create The Parent Template

To begin, we'll create the parent template. Let's say we want to generate a document from the Account object that has data merged in from each opportunity record in the Opportunity related list. Create a new S-Docs template, and ensure that the Related To Type field is set to Account (or whichever base object you're working with).

Navigate to the template editor and click on the Source button. There are two different ways to write the component query.

Method 1:

This method will run 1 SOQL query for each component merged. It's ideal for shorter lists of records. Paste something like the following into the source of the template editor.

[code lang="html"]<!--{{!<LineItemsSOQL>
<component>Component_Template</component>
<soql>SELECT Id FROM Opportunity WHERE AccountId='{{!Account.Id}}'</soql>
</LineItemsSOQL>}}-->[/code]

This LineItemsSOQL statement will be where our component template appears for each record in the related list. Let's dig a little deeper into what's going on here.

After opening the LineItemsSOQL statement, we've specified the name of our component template, Component_Template, within the <component> tags.

After this, we've written a SOQL query that will allow the component template to pull field data from opportunities related to our account. This feature isn't limited to related lists, however - you can query any object in your org with any filter conditions.

Because this method runs a SOQL query for each component merged, it may not be scalable for large lists of records. In that case, you can use method 2.

Method 2

Note: Method 2 is available in S-Docs 4.447+

This method will run 1 SOQL query in total, no matter how many components are merged. It's ideal for longer lists of records. Paste something like the following into the source of the template editor:

[code lang="html"]<!--{{!<lineitemsSOQL>
<class>none</class>
<soql>SELECT id, name, stagename from opportunity WHERE AccountId='{{!Account.Id}}'</soql>
<component columnFields="true" mergeFieldPrefix="prefix">Component_Template</component>
<column componentMergeField="true">id</column>
<column componentMergeField="true">name</column>
<column componentMergeField="true">stagename</column>
</lineitemsSOQL>}}-->[/code]

This method requires adding the columnFields="true" attribute to your <component> tag to specify that your component template uses the fields that you define below in <column> tags. You must also define a merge field prefix within your <component> tags by using the mergeFieldPrefix="prefix" attribute. This prefix must be used in the merge fields in your component template. Each merge field used in your component must also be defined in a <column> tag with the componentMergeField="true" attribute in the parent template component query.

Refer to the section below to see a syntax example of how your merge fields should look in your component template when using method 2.

Create The Component Template

Now that we've written our LineItemsSOQL statement in the parent template, it's time to create the component template that will appear there when the parent template is generated.

Create a new S-Docs template, and ensure that the Related To Type field is set to the object that your SOQL query is pulling data from (in this case, Opportunity). Change the Template Format field to Component. This will automatically uncheck the Available For Use and Initially Visible checkboxes when you save the template, ensuring that users won't be able to select and generate this template on its own.

Navigate to the template editor. All you have to do now is build out how you want the data from each record to appear in the parent template.

For Method 1, you can simply use merge fields like you always would. We'll make a simple list of data that looks something like this:

[code lang="html"]Opportunity ID: {{!Opportunity.id}}
Opportunity Name: {{!Opportunity.name}}
Opportunity StageName: {{!Opportunity.stagename}}[/code]

For method 2, be sure to use the merge field prefix specified in the parent template, and only reference fields defined in the parent template component query <column> tags.

[code lang="html"]Opportunity ID: {{!prefix.id}}
Opportunity Name: {{!prefix.name}}
Opportunity StageName: {{!prefix.stagename}}[/code]

Once you click Save, you're ready to generate your document!

Note: For method 1, you can also reference the merge field {{!RowNum}} in your component template. This will correspond to the row number of the record returned by the LineItemsSOQL statement in the parent template.
For method 2, add a column in your parent template component query like <column componentMergeField="true">rownum</column> and then use {{!MergeFieldPrefix.rownum}} (Replacing MergeFieldPrefix with your chosen prefix)
Note 2: If you're using Named Queries in your parent template, you can reference these merge fields in your component template as well.
Note 3: Component templates support <nullprefix>, <nullpostfix>, <allprefix>, and <allpostfix> tags.

Generate Your Document

It's time to put our work into action. Navigate to a base object record (in this case, we'll be navigating to an Account record) and click the S-Docs button. Choose your parent template and click Next Step.

Once your document has generated, click the PDF icon to view it. The component template will have generated for each record in your list. Since our account had two opportunities attached to it, the component template generated twice in our parent template.

Although this is only a very simple example, you can use the full power of the S-Docs template editor to style both the component and parent template in any way that you want.


Top