Category

Documentation

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.


Connecting S-Docs with Amazon S3

By Documentation No Comments

Setting Up S-Docs Amazon S3 Connection

S-Docs connects seamlessly with Amazon Simple Storage Service (Amazon S3), meaning that you can generate documents securely on the Salesforce platform and then upload them to an S3 bucket -- all without ever leaving Salesforce. This article will provide you with step-by-step instructions for configuring the S-Docs Amazon S3 connection. For the purposes of this guide, we'll assume that you have already created an Amazon S3 account and an Amazon S3 bucket.

Note: This connection supports uploading documents to one S3 bucket at a time. To change buckets in the future, you will need to resubmit your Amazon S3 credentials.

Provide S-Docs with Your S3 Credentials

To allow S-Docs to upload documents to your S3 bucket, you first need to provide S-Docs with your Access and Secret keys, the name of the bucket you want to store documents in, and your bucket region.

Note: Your bucket must allow public access settings for this connection to function properly.

To do so, navigate to the Amazon S3 Integration page. If you are using S-Docs 4.381+, do so by clicking the App Launcher, typing in "S-Docs," and clicking S-Docs Setup.

From the S-Docs Setup page, scroll down to the Other Pages section and click Go To AWS S3 Integration Page.

If you are using a version of S-Docs below 4.381, navigate to this page by clicking one of the following links:

[Production]: https://login.salesforce.com/apex/SDOC__SDConfig?viewS3Settings=true
[Sandbox]: https://test.salesforce.com/apex/SDOC__SDConfig?viewS3Settings=true

You'll be presented with the S3 Configuration page. Enter your S3 credentials, then click Submit S3 Credentials.

You will receive a success message when your credentials are successfully submitted. You can exit the page at this time.

Create a Remote Site Setting

Next, you need to create a new remote site setting for your Amazon bucket's virtual-hosted-style URL.

From the setup menu, type "Remote Site Settings" into the Quick Find bar, click Remote Site Settings in the dropdown menu, then click New Remote Site.

Give your remote site a unique name; we recommend something similar to AmazonS3Connection.

Then, enter your bucket's virtual-hosted-style URL. These URLs follow the following format:

[code lang="html"]https://my-bucket.s3.region.amazonaws.com[/code]

Since our bucket is named accountsummaries and our region is us-east-2, our remote site setting looks like this:

Ensure that the Active checkbox is checked, then click Save.

Add the Amazon S3 Enabled Field to the Template Detail Page

To specify which templates can be uploaded to Amazon S3, you need to add the Amazon S3 Enabled checkbox field to your template record detail page. From the setup menu, navigate to the Object Manager and find the SDoc Template object.

Navigate to the Page Layouts tab and click Edit for the SDoc Template layout.

Find the Amazon S3 Enabled field in the Fields section of the layout editor. Drag it down into the SDoc Template Detail section. Then, click Save.

Upload Documents to S3

To enable a template for upload to Amazon S3, simply check the Amazon S3 Enabled checkbox on the template detail page.

When you generate this template, you'll now see an Upload Selected Documents to S3 button on the Generated Documents page.

You will receive a success message when your document is successfully uploaded.

Note: The document will be both uploaded to S3 and saved in the S-Docs related list on your base record. If you don't want your documents to be saved in Salesforce, you can configure a trigger that removes them when they are sent to S3.

Automatically Uploading Documents to S3

Although the default S-Docs & Amazon S3 connection allows you to choose whether or not a document should be uploaded to your S3 bucket, you can also modify this configuration so that documents are automatically uploaded to S3 whenever they are generated. To do so, simply modify your S-Docs button URL and add the autoS3='true' parameter to the end. For example, an S-Docs Account button with the automatic S3 upload feature would look like this:

[code lang="html"]{!URLFOR('/apex/SDOC__SDCreate1', null,[id=Account.Id, Object='Account', autoS3='true'])}[/code]

Note: Documents generated via automation (S-Docs Jobs) that have the S3 Enabled field checked will always be uploaded to Amazon S3 after generation. This includes documents generated with the S-Docs Mass Merge (batch) feature.


Using Custom S-Sign Email Notification Templates

By Documentation, S-Sign No Comments

Introduction

S-Sign allows you to create custom email templates for the following automatic email events:

  1. Signature confirmation - Individual (sent to a user after they submit a document)
  2. Signature confirmation - All signers have finished signing (sent to all signers after the final signer submits the document; includes the signed document as an attachment)
  3. Signature declined notification (sent to the Salesforce user who sent the S-Sign request when a signer declines a signature)

These templates can be created and configured just like any normal S-Docs HTML email template, but there are a few configuration steps to take first to ensure that the S-Sign Site Guest User has the necessary permissions to generate and send your custom templates.

Configuration

There are two mains steps to granting the S-Sign Site Guest User access to send your custom templates.

1. Edit Object Permissions on the S-Sign Site Profile

From the Setup menu, type "Sites" into the Quick Find bar, click Sites in the dropdown menu, then click your S-Sign Site Label to navigate to the S-Sign Site detail page.

From the Site detail page, click Public Access Settings.

Click Edit at the top of the page.

First, scroll down to the Standard Object Permissions section. Check the Read checkbox for the base object that you're using with S-Sign (the object that your S-Sign template's Related To Type field is set to), along with any other objects referenced in your custom email templates (through lookup fields or queries, for example).

Next, scroll down to the Custom Object Permissions section. Check Modify All for the S-Docs, S-Docs Fields, and S-Docs Relationships objects.

Click Save.

2. Create A Sharing Rule On Your Base Object

The next step is to create a Sharing Rule on the base object of your S-Sign template (the object that your S-Sign template's Related To Type field is set to).

Note: You must create identical Sharing Rules on any other objects that you want to use custom S-Sign email notification templates with.

From the Setup menu, type "Sharing Settings" into the Quick Find bar and click Sharing Settings in the dropdown menu. Scroll down to Opportunity Sharing Rules, and click New.

Enter the following values for your Sharing Rule:

Rule Name
Label:
S-Sign Site Guest User
Rule Name: S_Sign_Site_Guest_User

Rule Type: Guest user access, based on criteria

Criteria
Field: 
{Base Object} Owner ID (For example, if your base object is Opportunity, choose Opportunity Owner ID)
Operator: not equal to
Value: 1.00

Share With: S-Sign Site Site Guest User

{Base Object} Access: Read Only

Click Save.

Create Custom Email Notification Templates

Once you've granted the S-Sign Site Guest User the necessary permissions, you can create and use your custom S-Sign email notification templates.

To do so, simply create a new S-Docs template. Set the Related To Type field to the same base object as your S-Sign PDF template, and set the Template Format field to HTML.

From there, you can edit your email template in the S-Docs template editor like normal.

Note that you can use the following special fields in your custom email notification templates:

  • [[DECLINE_REASON]]
  • [[REQUESTER_NAME]]
  • [[REQUESTER_EMAIL]]
  • [[SIGNER_EMAIL]]
  • [[SIGNER_NUMBER]]
  • [[NUM_SIGNERS]]
  • [[SIGNER_ROLE]]
  • [[NUM_SIGNERS_REMAINING]]
  • [[SIGN_LINK]]
  • [[SIGNED_DOC_URL]]
  • [[SIGNER_NAME]]
  • [[DOCUMENT_NAME]]
  • [[DOCUMENT_NUMBER]]
  • [[NUM_DOCUMENTS]]
  • [[EXPIRATION_DATE]]
  • [[CREATED_DATE]]

Assign Email Notification Templates To S-Sign Templates

The final step is to assign your custom email notification template to an S-Sign template. To do so, navigate to your S-Sign enabled PDF template and find the S-Sign Notification Settings in the S-Sign panel on the left (under the S-Sign Template Settings tab). Paste the template ID of your custom email notification template into one of the top three fields based on which automatic email event it is for.

Template IDs can be found in your browser address bar on the template record detail page.

That's all there is to it! You can use a single custom notification template for all of your S-Sign templates, or create unique ones for each different type of document that you need to send for signature.


Automate S-Sign Requests

By Documentation, S-Sign No Comments

Introduction

S-Sign requests can be configured to automatically generate and send after any platform-triggering event in Salesforce. For example, when a user changes an opportunity Stage field to Proposal/Price Quote, you can configure S-Sign to generate and send an e-signature request to all of the Opportunity Contact Roles related to that Opportunity. Users would not need to click on any buttons or choose any templates; whenever the field value is changed, even from a mobile device, the process is invoked and the document is sent for signature.

This article will help you configure S-Docs to meet your requirements using the S-Docs Jobs object in conjunction with one of two Salesforce automation options: Process Builder and Apex triggers.

If you'd like to learn more about the S-Docs Job object and the different automation options offered by S-Docs, please visit our automation guide.

Note: Currently, automating S-Sign with S-Docs Jobs only supports sending 1 PDF for signature per request.

Example Use Case

To walk through setting up automation for S-Sign, we will be using the following example use case:

Whenever the custom checkbox field Send Renewal Agreement is checked on an Account record, S-Sign will automatically generate and send a renewal agreement PDF for signature to all Contacts related to that Account.

Note: While this article details setting up automation, there are a few more steps involved in configuring your S-Sign template to route to each Contact related to your Account record. Please visit Build Templates with a Dynamic Number of Signers to learn more.

This article will demonstrate how to accomplish this using S-Docs Jobs in conjunction with Process Builder and Apex triggers. Both automation options will utilize the following 5 fields on the S-Docs Job object.

Fields for Our Use Case

Field Description
Start Job

(SDOC__Start__c)

This field will invoke the S-Doc Job so that the documents included in the S-Sign request can generate. It will be set to ‘true’.
Doclist

(SDOC__Doclist__c)

This is the comma-delimited list of S-Docs template names that we will be using to generate our documents. Make sure there aren’t any spaces separating each template in your comma-delimited list. In our example use case, Renewal Contract is the name of our S-Sign PDF template, and Email Template is the name of our S-Sign HTML email template. Thus, we will be using the following Doclist for our example use case:

Renewal Contract,Email Template

Object ID

(SDOC__Oid__c)

This is the Object ID field, i.e. the place where we specify which object our Process/Apex Trigger should pull record IDs from. In our example, we will choose Account, since we want our process to use Account record IDs.
Object API Name

(SDOC__ObjAPIName__c)

This is the API name of our object. It will be set to Account.
Send Email

(SDOC__SendEmail__c)

This field will automatically email the S-Sign request. It will be set to '1.' If this field was set to '0,' the S-Sign request would not be emailed.

For this to work properly, our Doclist needs to include an S-Sign enabled HTML email template.

Note: You can also use template IDs for the doclist parameter, but this is not recommended because template IDs are not consistent between sandbox and production orgs, meaning that you will have to re-add new template IDs into this parameter after transferring your process to production. However, if you have multiple templates with the same name in your org, all of them will generate once your process/trigger is invoked. In this case, template IDs may be better suited.

Automate S-Sign with Process Builder

Process Builder is the easiest option for automating S-Sign requests. To begin, navigate to the Setup menu, type "Process Builder" into the Quick Find bar, and click Process Builder.

Click New in the top right corner to create a new process.

You can name the process whatever you'd like, then choose to start the process when a record changes. Click Save.

Click Add Object, choose Account, and start the process when a record is created or edited, since our process will be invoked when our custom checkbox field is checked. Then, click Save.

Next, click Add Criteria. Choose a name and select Conditions are met. Next, set the conditions -- in our case, we'll select the Send Renewal Agreement field, set the Operator to Equals, keep the Type set to Boolean (since it's a checkbox field) and set the Value to True. Finally, we'll choose to invoke the process when All of the conditions are met (AND). This will ensure that the process is invoked whenever the Send Renewal Agreement checkbox is checked. Click Save.

Then, click Add Action (under the Immediate Actions section). Choose Create a Record for the Action Type, enter an action name, and select SDoc Job for the Record Type. You may need to type it in to find it.

A Field Values menu will appear below. This is where you will add the five fields described in the Fields For Our Use Case table above. Click Add Row to add each new field.

Click Save when you finish adding each field. Your process should look similar to this:

Click Activate at the top right to activate your process. S-Sign will now automatically generate and send a renewal agreement to all Contacts related to your Account whenever the Send Renewal Agreement checkbox is checked.

Automate S-Sign with Apex Triggers

To automate S-Sign requests using Apex triggers, begin by navigating to the Developer Console (click the Cog in the upper right corner and select Developer Console).

Create a new trigger (File > New > Apex Trigger).

Name the trigger whatever you'd like, and select Account for the sObject.

Delete the text that was automatically inserted, and paste in the following trigger:
[code lang="html"]trigger RenewalAgreement on Account (after update) {
List<SDOC__SDJob__c> jobList = new List<SDOC__SDJob__c> {};
for (Account acct : Trigger.new) {
Account oldacct = Trigger.oldMap.get(acct.Id);
If (acct.Send_Renewal_Agreement__c == True){
SDOC__SDJob__c job =
new SDOC__SDJob__c(SDOC__Start__c=true,
SDOC__Oid__c=acct.Id,
SDOC__ObjApiName__c='Account',
SDOC__SendEmail__c='1',
SDOC__Doclist__c='Renewal Contract,Email Template');
jobList.add(job);
}
insert jobList;
}
}[/code]
Once you click Save, S-Sign will automatically generate and send a renewal agreement to all Contacts related to your Account whenever the Send Renewal Agreement checkbox is checked.

While this article detailed how to automate S-Sign to satisfy the requirements of a simple use case, you can combine these examples with much larger, more complex processes or triggers to meet any unique business requirement. To learn more about automating S-Docs, please visit our general automation guide, as well as our guide to generating S-Docs with one or zero clicks.


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:


Use Switch Statements

By Documentation No Comments

Introduction

If your S-Docs template that needs to render different contents based on different conditions, render statements can satisfy a majority of your conditional logic requirements.

However, S-Docs also supports using switch statements to replace repeating render statements that conditionally output contents based on a single field's value. Instead of writing multiple render statements to check each possible field value, you can simply create a switch map and reference it in a switch statement to do the work for you. Switch statements can greatly simplify the logic within your template into just a few lines. Let's take a look at how they work.

Example Use Case

To better understand how switch statements work, we will begin with an example.

Let's say we have an internal Opportunity summary template that needs to include different instructions based on the value of the Opportunity's Stage field. Since there are 10 standard values for this field, we could write 10 render statements that each output different instructions for each possible field value.

However, we could also use the switch feature to simplify this logic. We will set this up now.

Create The Switch Map

To use switch statements in your S-Docs templates, you need to first create a separate switch map template. The switch map template will contain switch keys and switch values that will be referenced by the switch statement in your main template.

Add JSON as a Template Format Value

Switch map templates need to use the JSON template format, which isn't enabled for S-Docs templates by default. You will 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 "JSON" into the text field, then click Save.

Create the Switch Map Template

To create your switch map template, create a new template and set the Template Format field to JSON.

Navigate to the template editor to write your switch map. The basic syntax for switch maps is as follows:
[code lang="html"]{
"SwitchKey1" : "SwitchValue1",
"SwitchKey2" : "SwitchValue2",
"SwitchKey3" : "SwitchValue3"
}[/code]

Note: Make sure not to include a comma after the last switch value in your switch map.

Let's take a look at a switch map in the context of our example use case.

In this scenario, [1] the Stage field values for the Opportunity object represent the switch keys. [2] The custom instructions for each field value represent the switch values; these are the conditionally rendered contents that will appear in our Opportunity summary based on the value of the Stage field. The entire map needs to be enclosed in curly braces.

Write The Switch Statement

Now that the switch map is created, navigate to your main template to write the switch statement. The basic syntax for switch statements is as follows:

Note: Switch statements must be written in the Source of the template editor. Ensure that you are in the template Source before writing your switch statement.

[code lang="html"]<!--{{!
<switch>
<switchMap>Switch Map Template Name</switchMap>
<formula>{{!Object.Field}} == '{{!SWITCH_KEY}}'</formula>
<outputForEachMatch>{{!SWITCH_VALUE}}</outputForEachMatch>
</switch>
}}-->[/code]
Let's take a look at the switch statement in the context of our example use case.

[1] Switch statements are opened like related list LineItems or LineItemsSOQL statements, followed by the <switch> tag.

[2] The name of the switch map template is enclosed in <switchMap> tags. This line must include the exact same name that's listed in the Template Name field for your switch map template, with no extra characters or spaces.

[3] The render conditions are enclosed in <formula> tags. The example above will check the switch map for the switch key that matches the Stage field of the opportunity that this template is generated from. This accepts the same syntax as the S-Docs Render feature. Although we use "equals" in this example, you can use any of the operators accepted by S-Docs Render statements.

[4] The conditionally rendered contents are enclosed in <outputForEachMatch> tags. The example above uses the {{!SWITCH_VALUE}} merge field, which means it will render the switch value that matches the switch key (e.g. the custom instructions that match the Opportunity Stage field). You can also include static text within these tags.

[5] Switch statements are closed with the closing switch tag, followed by the syntax used for closing related list LineItems and LineItemsSOQL statements.

Let's See it in Action!

Now that we've seen how to create a switch map and write a switch statement, let's go back to our example use case and see the switch feature in action. Since we want to create an Opportunity summary template that includes different instructions based on the Opportunity's Stage field, we insert the switch statement at the bottom of the Source of our Opportunity summary template.

We then navigate to an Opportunity record to generate the document. Take note of the Opportunity's Stage field.

When we generate the document, the correct custom instructions appear where we inserted the switch statement. The switch map has been superimposed for reference.

As you can see, the Switch feature greatly simplified our template logic into just 7 lines of code.

Use Template Components in Switch Statements

The Switch feature also supports using template components as switch values (dynamically rendered contents). This can be useful if your switch values are very long, or require formatting that's not available in the JSON switch map template. There are only a few differences to consider when using components as switch values instead of static text.

In the switch map, input template component names into the switch value column instead of static text.

When you write the switch statement, simply enclose the {{!SWITCH_VALUE}} merge field within <template> tags.
[code lang="html"]<!--{{!
<switch>
<switchMap>Switch Map Template Name</switchMap>
<formula>{{!Object.field}} == '{{!SWITCH_KEY}}'</formula>
<outputForEachMatch><template>{{!SWITCH_VALUE}}</template></outputForEachMatch>
</switch>
}}-->[/code]
In the context of our example use case, a switch statement using the switch map above would look like this:

You can also include additional template tags to merge in other component templates as well.


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.


Top