Winter '20 Release Note: If you are using S-Docs below version 4.53, you may experience an "Attempt to de-reference a null object" error when interacting with various forms of automation in S-Docs. In order to fix this bug, you can create a new SDocs Settings custom settings set. To do this, type "Custom Settings" into the Quick Find / Search bar in the Setup menu, and click Custom Settings. Click SDocsSettings, then click Manage at the top of the page. From there, click New. Fill out the following information:

Name: SDocsSettings
SD Jobs Batch Size: 30
SD Jobs Move to Top of Flex Queue:

Additionally, ensure that you have a Remote Site Setting for either (production), or (sandbox).

Note: This guide builds on automation features discussed in the one-click and zero-click guide (Automation Options Improving Efficiency and Compliance).

With the use of Salesforce logic in the S-Docs Apex button, you have an endless amount of possibilities for automating template selection and generation. You can easily modify the standard S-Docs button code so that when users click the button, S-Docs will automatically select or generate certain documents depending on the values in a record’s fields.

For example, suppose that we have multiple templates for a letter sent to contacts, and that this letter will vary depending on what a given contact’s department is. If the variation is small, we could handle this using render statements. But suppose these were completely different letters requiring completely different templates, and we don’t want to require our sales team to memorize the contact’s department, click the S-Docs button on the contact record’s page, and then have to click the appropriate letter template prior to document generation. We’d rather have a user in our org just click S-Docs and be immediately taken to their templates.

You can edit an object’s existing S-Docs button, or you can create a new button if you’d like users to have the option of using the normal S-Docs button in case they need to manually select templates. In this case, we’ll go with the first choice, and simply edit our existing S-Docs button.

In the following sections, we will be automatically selecting documents with the doclist Apex parameter. To use this, we simply append the following to the end of our S-Docs button code:


Template IDs can be found in the URL when you open a template detail record. They are the string of letters and numbers toward the end of the URL.

The doclist can include as many S-Doc template IDs as you’d like. If you just append the doclist parameter, templates will be automatically selected and generated. If you would like your S-Docs templates to be automatically selected, but not automatically generated, you can append &oneclick=false to your S-Docs button code.

Note: In all of the following cases, the template's plain text name can be used in place of the template ID for the "doclist" parameter. However, if there are multiple templates with the same name, they will all generate if one of them is referenced in your button.

Two Outcomes: True or False (IF Function)

Let’s suppose that members of every department except finance gets letters derived from the same template, and the finance department gets letters derived from a different, special template. This means that we have two outcomes to consider in our automatic template selection: the contact is in the finance department, or the contact is in some other department. So, we handle this with the doclist Apex parameter and an IF function that determines the template IDs to be included in the doclist.

Automating Conditional Template Selection (1)

We see that if the contact’s department is “Finance,” then the template ID will be a0236000005cAoB, which happens to be the S-Docs template ID for our special finance department letter. However, if the contact’s department is not “Finance,” then the doclist parameter will be a0236000005c53o, which is the template ID for our letter for all other departments.

More Than Two Outcomes (CASE Function)

Now suppose that members of technology departments will also receive a totally different letter. This means we can’t use an IF function, as we now have three outcomes; the contact could be in the finance department, the technology department, or in some other department. This means we’ll have to use the CASE function instead.

Automating Conditional Template Selection (2)

We see that the finance department will get their own letter, the technology department their own letter, and since else_result is “a0236000005c53o” (the same template ID used for all other departments in our IF function example), all other departments will receive letters derived from the same template.

Building a Doclist with Multiple Functions

Now, suppose that we’d like to send an account’s primary contact a questionnaire regarding how much they like our product. Additionally, suppose we have two true/false fields: Up_For_Renewal__c and Receives_Discount__c, which respectively denote whether the account is up for renewal and whether the account is eligible for a discount. We’re sending the account’s primary contact the questionnaire no matter what, and depending on the status of the other two fields, we may or may not send a letter informing them that they are up for renewal, and possibly some kind of coupon code or voucher if they are eligible for a discount. Let’s say the template ID for the questionnaire is a0236000005cSdH, the template ID for the up-for-renewal letter is a0236000005cAoB, and the template ID for the coupon code is a0236000005c53o.

Then, we could accomplish this like so:

Automating Conditional Template Selection (3)

Since we’re sending the questionnaire no matter what, its template ID is at the front of the doclist outside of the IF function (followed by a comma since our doclist must be a comma-delimited list without spaces). Then, we have two IF functions (separated by a comma since our doclist must be a comma-delimited list without spaces) that will return a template ID if their respective fields are true. So, if Up_For_Renewal__c and Receives_Discount__c are both true, our resulting doclist will be:

If  Up_For_Renewal__c is false and Receives_Discount__c is true, our resulting doclist will be:

If both of these fields are false, our resulting doclist will be:

In the last case, this is because value_if_false for our two IF functions is an empty string (specified as two quotation marks with nothing between them). Don’t worry about the additional commas; S-Docs will ignore these and just generate the document with the template ID a0236000005cSdH. We could place commas inside of our code’s quotation marks such that they would always yield clean-looking doclists. However, this might take a bit more thought and work to write, and could be more prone to mistakes (or you might think the opposite; it’s a matter of personal preference). No one’s really looking at the resulting doclist after your IF functions evaluate; it’s just used internally by S-Docs to find which templates to use. So, you don’t need to worry about what your doclist evaluates either, as long as the logic is correct and there is at least one comma between each template ID whenever the doclist evaluates.

Nested IF Functions
Our code’s structure in the previous example is very useful in plenty of cases. However, it might not make sense to send an account a coupon code along with the questionnaire if they aren’t up for renewal. We might want to send that coupon code only if they’re up for renewal. We can accomplish this using a nested IF function:

Automating Conditional Template Selection (4)

Let’s take this statement apart. Our questionnaire’s template ID, a0236000005cSdH, will be on our doclist no matter what. Now, what happens if Account.Up_For_Renewal__c is true? First, note that we included a comma at the end ofa0236000005cAoB; this comma is inside the string, since we don’t want to confuse our IF function with extra commas laying outside the string. We then followed this string with an ampersand (i.e. the concatenation operator) and a nested IF function. Whatever the nested IF function returns will be concatenated to the end of the following string: a0236000005cAoB,

So, if Account.Up_For_Renewal__c is true, and Account.Receives_Discount__c is false, our resulting doclist will be:

Then, if Account.Up_For_Renewal__c and Account.Receives_Discount__c are both true, our resulting doclist will be:

And finally, if Account.Up_For_Renewal__c is false and Account.Receives_Discount__c is true, our resulting doclist will be:

In other words, accounts will receive just the questionnaire if they aren’t up for renewal, even if they are eligible for the discount. No need to jump the gun on that coupon code!

Note: In our Apex button, note that the curly braces are only on the outside of the first IF function, but not the second. For a nested IF function, we do not need these curly braces; if you use the “Insert Selected Function” to insert a function inside of a function, Salesforce will make sure not to place curly brackets around your nested function. For this reason, we recommend using this button just to play it safe.

Using AND/OR Functions
AND/OR functions can be used with the doclist parameter as well. For example, say we become big fans of small business and decide to create a promotional period in which accounts with annual revenues less than $100,000 will also receive a coupon code, even if Account.Receives_Discount__c is false. To accomplish this, we can place an OR function inside of our IF function:

Automating Conditional Template Selection (5)