How to create a Map collection in Flows by Narender Singh

Narender Singh form ForcePanda wrote a two blog series about using map collections in flows. The second blog makes good use of the new generic sObject support in flows coming in the Spring ’20 release

Part 1: https://forcepanda.wordpress.com/2019/12/17/how-to-create-a-map-collection-in-flows-part-1/

Part 2: https://forcepanda.wordpress.com/2019/12/18/how-to-create-a-map-collection-in-flows-part-2flow-map-methods-spring20delight/

Collection Processors for Flow (Sort, Filter, Find, Join, Map, and more)

This package contains new Flow actions that are designed to manipulate any SObject or collection of SObjects. This means that in one Flow you might use them with a collection of Accounts and in another flow a collection of Leads.

This Post was most recently updated on: 3/18/24

Current Version 3.2.2

Fixed intermittant test class error (index out of bounds) from the ReturnNRandomRecords component


v3.2.2 – 3/18/24 – Eric Smith – Production Sandbox
Fixed intermittant test class error (index out of bounds) from the ReturnNRandomRecords component

12/14/23 Version: 3.2.0

  • Added a new Return N Random Records action (Derek Camp)
  • Added a new Convert to/from CSV String and Text Collection (Eric Smith) *also available as a reactive screen component

9/13/23 – Eric Smith – Reactive Screen Components
I am making some of the actions also available as reactive screen components. See this article for more information.

  • Extract Strings From Collection (With Dedupe)
  • Collection Calculate

10/22/23 – Eric Smith – Added 4 new Collection Actions as Reactive Screen Components

  • Filter Collection
  • Find Common and Uncommon Records
  • Join Collections
  • Sort Collection

12/14/23 – Eric Smith – Added new Collection Action as a Reactive Screen Component

  • Convert to/from CSV String and Text Collection

*Available as a Reactive Screen Component


Note: If you are defining record collection variables in your flow and do not assign any value to them, many of these actions will fail with a “Missing required input parameter” when called from the flow. If there is a chance that your flow logic could bypass any assignment to the variable, be sure to add an Assignment element setting the collection variable to nothing before calling the action.


Install Current Version

Installation links at the bottom of this page.

Video Demo

Notes on Dynamic Inputs

Keep in mind that you can insert mergefields as dynamic inputs in these actions. A mergefield takes the form of a reference name surrounded by braces and an exlamation point: {!myUpstreamVar}. So for example, you can use Map Collection like this:

Rating” : “Warm”, “Industry” : “Banking

or like this:

Rating” : “Warm”, “Industry” : “{!myUpstreamVar}

To get the syntax right, use this rule: Flow Builder will replace everything between braces before passing the inputs to the invocable action.

Add or Insert Record

Takes as input a collection of records and a single record, and an optional index value. Returns the combined collection. If the index value is specified and is less than the length of the inputCollection, the

Inputs

List<SObject> inputCollection;

SObject inputRecord

Integer index

Outputs

List<SObject> outputCollection;

*Collection Calculate

Allows Add, Multply, and Average aggregate operations across a collection of records.

See documentation

*Convert to/from CSV String and Text Collection

See original documentation

Copy Collection

Takes as input a collection of records and returns the collection as output, allowing a new variable or reference to have the same value

Inputs

List<SObject> inputCollection;

Outputs

List<SObject> outputCollection;

Count Records And Fields

Takes a collection of records and returns a count. Optionally also takes a field name and a field value, and then also counts the number of records that have that particular value for that particular field. Returns both the number of matches and the total number of records. Added in V

Inputs

List<SObject> inputCollection;

String fieldName;

String fieldValue;

Outputs

Integer totalNumber

Integer matchedNumber

String errors

Dedupe Record Collection

Returns a set of de-duped records based on the field you specify. More Information

DeepClone

Clones a record and one or more sets of its child related records. More Information

*Extract Strings From Collection (with Dedupe)

Takes a collection and a field name, and returns a list of strings reflecting the values of those fields for the records. For example, if you pass in a list of Contacts and a fieldName of “Id”, you’ll get back a list of recordIds for the contacts.

Features

  • Extract a text collection or comma-separated string of any field for each record in a Record Collection
    • Particularly useful for Ids, Picklists, Multi-select picklists
  • Optionally de-dupe the values returned from all of the records.
    • Supports Multi-select picklists across all records in the collection
  • Useful when paired with the new AddQuotesToFields and ExecuteSOQL actions to pass in a set of strings wrapped in quotes
  • Ex. Select Name, Email from Contact where Id in (‘003023044333sDl’, ‘003023044333sKF’)

Inputs

  • inputRecordCollection
    • List of records to extract field values from
  • fieldAPIName;
    • API Name of the field you want returned
  • dedupeValues;
    • If true only unique values will be returned. The default value is true

Outputs

  • fieldValueCollection
    • Extracted fields in a text collection
  • fieldValueString;
    • Extracted fields in a comma-separated text variable

*Filter Collection

Filters a collection against a formula string which can be created by an included Expression Builder Flow Screen Component.

Inputs

List<SObject> inputCollection;

String formula;

Outputs

String errors;
List<SObject> outputCollection;

Details

For each member of the inputCollection, this action will evaluate the provided formula and add the member to the outputCollection if the formula is true.

The formula must be a string that can be processed by the Salesforce formula engine. The actual engine that evaluates this string is written in Apex and is included in the Collection Processors package.

It will use the recordId of the current member as context, replacing expressions in the formula string of the form $Record.fieldname. For example, if the formula is ‘$Record.Age__c > 21’ and the input Collection is a collection of Student__c, the evaluator will do the following:

Loop through the collection of Student records. For each record:

  1. use its ID and retrieve the record
  2. retrieve the values of any fields present in the formula string
  3. use the formula evaluator to evaluate the formula
  4. If the formula evaluates to true, add the current record to the output collection

Also see ‘Notes on Dynamic Inputs‘ at the top of this post.

Find Record in Collection

Returns all records from the inputCollection that have a field with name targetField that has a value of targetValue. Pass in the name of the object in targetObject (for example, if the inputCollection is a List of Contacts, set targetObject to Contact. There’s probably a way to determine this automatically but it’s not implemented in the action at this time). If there’s just a single result, the result is returned as singleOutputMember. Otherwise it’s returned as multipleOutputMembers. Version 1.20+: MultipleOutputMembers returns null if there are no results

Inputs

List<SObject> inputCollection;

String targetObject

String targetField

String targetValue

Outputs

SObject singleOutputMember;

List<SObject> multipleOutputMembers

*Find Common and Uncommon Records

Compares & Contrats two record collections – even different sObject Types!

Post here

Generate Collection Report

Given a collection and a comma-separated list of field names, generates a string that includes all of the field values for every member of the collection. There are now two modes you can use. displayMode ‘simple’ simply throws the information out in simple groups. Useful for some debugging. displayMode ‘table’ generates HTML table markup that’s great for insertion into emails:

For full information on this action, see this post.

Inputs
List<SObject> inputCollection;
String shownFieldsa comma-separated list of the fields you want to show in the table. Make sure to use the full api names, including ‘__c’ for custom fields.
displayMode‘simple’ or ‘table’. defaults to simple
tableStyleStringwill be inserted into the table html as a style attribute: <table style=”[tableStyleString]”>
headerStyleStringwill be inserted into the <th> tags as a style attribute
rowStyleStringwill be inserted into individual row tags (<tr>) as a style attribute
showHeaderBoolean
Outputs

String reportString

Get Child Collection

Takes a record and returns a specified collection of child records related to the input record.

Pass in either a record or a recordID (as a string), but not both. Specify the childRelationshipName, which should be the name of the child Object. Example. If you have an Opportunity and want to retrieve all of the OpportunityContactRoles associated with the input, specify a childRelationshipName of OpportunityContactRole. Note that this should also be specified as the Output Collection.

In childRecordFieldsCSV, specify the fields you want returned as a comma-delimited string. Example: Id,Name

For more information, see https://unofficialsf.com/automate-junction-updates-with-getchildcollection-and-getlookupcollection/

Inputs

SObject inputRecord;
String inputRecordId;
String childRelationshipName;
String childRecordFieldsCSV;

Outputs

List<SObject> childCollection;
String errorText;

Get First

Returns the first member of the inputCollection. The inputCollection is not modified by this action. Make sure that the types of your inputCollection and outputMember match.

Inputs

List<SObject> inputCollection;

Outputs

SObject outputMember;

Get Lookup Collection

Takes a collection of records and the name of an object related via a Lookup, and returns a collection of objects.

Pass in either a collection of records or a collection of string record ID’s. Pass in the name of the related object. Example: You start with a collection of OpportunityContactRoles and you want to get the Contacts associated with your OpportunityContactRoles via the ContactId Lookup field. In this case you would set lookupObjectName to Contact.

In lookupRecordFieldsCSV, specify the fields you want returned as a comma-delimited string. Example: Id,Name

For more information, see https://unofficialsf.com/automate-junction-updates-with-getchildcollection-and-getlookupcollection/

Inputs

List<SObject> inputCollection;
List<String> inputIds;
String lookupRecordFieldsCSV;
String lookupObjectName;

Outputs

List<SObject> lookupCollection;
String errorText;

Get Records from Ids

The Collection Actions package of utility actions now has a new action that takes a collection of recordIds (i.e. a List of Strings) and returns the corresponding records. It carries out a SOQL query and obtains the fields that you specify by name. The records are returned both as a collection of records and a serialized (JSON) string.

Inputs

String objectName;
String fieldNames;
global List<String> inputIds;

Outputs

List<SObject> records

String recordString

More information.

*Join Collections

Takes two collections (of the same type, please!) and returns their union as a single collection.

Inputs

List<SObject> inputCollection1;

List<SObject> inputCollection2;

Outputs

List<SObject> outputCollection;

Map Collection

Takes a collection and a set of key value pairs. Example:

Rating” : “Warm”, “Industry” : “Banking

Goes through the collection and changes each field with a name matching the key to the specified value.

Note that dynamic inputs are supported: “Rating” : “Warm”, “Industry” : “{!myUpstreamVar}“. See above for more.

NOTE: this currently only works for string values.

Inputs

List<SObject> inputCollection;

String keyValuePairs;

Outputs

List<SObject> outputCollection;

String errors;

Map Collection supports mapping of Time fields.

Example:
The Account object has a time field, and you want to use that time field on every case created. You can get the time variable from the Account and convert that to a string by using a formula, TEXT(Account.TIME). Then use that formula variable to assign that to the case.

Remove Record from Collection

Takes a collection and an index integer. Uses the Apex List class remove method to remove the member of the collection at the index location.

Inputs

List<SObject> inputCollection;

Integer index;

Outputs

List<SObject> outputCollection;

Return First N Records from Collection

Takes a collection and an integer count and returns that count of records from the beginning of the collection. The entire collection will be returned if it doesn’t contain more records than the record count attribute.

Inputs

List<SObject> Input Collection;

Integer Record Count;

Outputs

List<SObject> Output Collection;

Integer Return Count;

Return N Random Records from Collection

Documentation

Takes a collection and an integer count and returns that count of records randomly from the collection. The entire collection will be returned if it doesn’t contain more records than the record count attribute.

Inputs

List<SObject> Input Collection;

Integer Record Count;

Outputs

List<SObject> Output Collection;

Integer Return Count;

*Sort Collection

Takes a collection and a sortKeys string formatted as key value pairs (example:

“Name”:”ASC”,”Rating”:”Warm”

Known Issues:

1. Picklist fields are not supported.
2. If some of the records in your collection have a blank value for the field you’re sorting on, it will display the blank ones first no matter which direction you sort
3. The sorting priority is reversed from what I would have thought. It sorts first on the last key pair and then works backwards to the first.

Inputs

List<SObject> inputCollection;

String sortKeys;

Outputs

List<SObject> outputCollection;

Upsert

Upsert will either save or update a collection, depending on whether the collection already has ID’s

AttributeType
inputCollectionList<SObject>
inputRecordSObject
externalIdFieldNameString
allOrNoneBoolean
serializedRecordDataString. This should be a JSON string of key value pairs where the keys are the names of fields on a single object. for example: {‘AnnualRevenue’: ‘400000’, ‘Rating’: ‘Hot’}
objectNameString. the name of the object that the serialized key value pairs belong to. Example ‘Case’. Only used to classify a passed in serializedRecordData

For more info, see https://unofficialsf.com/create-or-update-with-the-new-upsertrecords-action/

Are you an Apex Developer?

Looking for a fun project? Consider one of these requested enhancements!

NameWhat it DoesWhat should the inputs be?What should the outputs be?Suggested ByDiscussion
EXAMPLE: Change OwnerSimilar to Map Collection, but specialized for changing the owner field, and so a little easier to configureBesides the input collection, a string that can either be a username or a user recordIdstandard success vs. error return values
Limit XSimilar to the First collection, but allow user to specify how many records to return from the collection. For example, they can pass an sobject collection and have up to X number of records returned in a new collection.record collectionupdated record collectionChris Van der Merwe
IN ClausePass two object collections and do IN comparisonrecord collection, record collection2, field to check from record collection, field to compare against record collection 2record collection with records as result on IN ClauseChris Van der MerweThis comes up all the time, and is challenging for governor limits in flwo.
Object API Name From Record IdPass in a record id of any object and get back the Object API Namerecord idObject NamePatrick LoughranThe code for this is written if it makes sense to publish.
Recaptcha ComponentUse caseAvailable as a project!
Report FolderReturn a list of report foldersno inputsreturn folder name and id
Report ListReturn a list of reportsoptional filter for folder id, report type, last view, last runreturn report name, report format,
Record List from ReportReturn a sobject collection of all the records on a specified reportinput report idsobject collection of records and fields on the reportGoal is to allow end-user to select a report of records that they defined using a report and perform a screen flow against those records. For example, mass create child records, mass update, mass delete etc
Record List from ListViewReturn a sobject collection of all the records on a specified list viewinput listview idsobject collection of records and fields on the list viewGoal is to allow end-user to select a report of records that they defined using a list view and perform a screen flow against those records. For example, mass create child records, mass update, mass delete etc
Compare Collections and return unique and common valuesFunctionality to be the same as here, but for record collections.Two collectionsThree collections (common, unique to coll1, unique to coll2)Peter KaszasI am using the datable from unofficialsf.com and would like to be able to get the difference between the total list and the selected list.
Slice A big collection (Take first N Records)It takes an input sobject collection and spits out 2 collections based on the first N records of a number you provide, and puts the rest in another collectionOne sObject CollectionTwo sObject CollectionsAdam WhiteMany times it is useful to chunk out operations to abide by Salesforce limits – it’s especially useful in Screen flows when its easy to maintain limits by keeping tabs on your DML and then letting the user hit ‘Next’ if Flow detects you’re approaching a limit. This would be a handy action to have for that
Output formula value for each record in Collection1. Return value from a formula input using available columns in an sObject Collection Variable
2. Add values to a Collection Variable
3. Optional: output unique values
One sObject Collection VariableOne Collection VariableRick HaagFormulas fields are often created for the purpose supporting automation and are not shared via the UI to users. This option can reduce the overhead of multiple formula fields in place soley for the purpose of automation.
Support Apex Defined ObjectsUpdate the processors to support Apex Defined Objects in addition to SObjectsOne Apex Defined Collection VariableOne Apex Defined Collection VariableEric Smith
Map more than stringsAdd at least number and date to the mapping.I suppose the tricky bet is how to describe the value of the mapping pair. I suggest leaving it as text and converting to number and converting to date inside the map code.Terry ColeMapping of text area works. Mapping of picklist value works (from string). Mapping of long text area seems to generate fault. Mapping of number (from string) and date (from string) runs but does not make changes.
Count Records and FieldsDocumentation says field and value are optional, but screen configuration shows them as requiredJust wants a quick count. Can so with collection count feature of assign, however. Just wanted cleaner solution.
Minimum dateInsert a list of dates, and returns the minimum. Quite cumbersom via formulas, seems easier in apexCollection of dates
Strip NullsRemove null records from a record collectionCollection of sObject recordsNew collection of sObjects with null records removedCharles ThompsonAnything you can do to avoid a loop is great! As it is, to remove null records, it appears you have to compare each record against a single record variable (of the same sObject) that has not been initialised.
Get Child CollectionsPass in a *collection of records* and get a single collection of *the children of all of the input records* of a particular object type1) Collection of object records (or list of IDs)
2) Name of child object
Collection of records of the object type specifiedRachel BeachBasically “Get Child Collection” but you can pass in a list of records rather than having to create a loop and call the action for each parent record
Get Records where Field in CollectionGet all records where a field is equal to one of the values in a collection (select * from [object] where [field] IN [input collection])1) Name of object
2) Name of lookup field
3) Collection of record IDs
Collection of records of the object type specifiedRachel BeachNot sure if this needs to be different for lookup fields vs other types of fields but I personally want it for a lookup field

Installation

Install Prerequisites

Before installing this component, you need to have in your org the Screen Component and Action Base Packs.
Install those here

Current Release

v3.2.2 – 3/18/24 – Eric Smith – Production Sandbox
Fixed intermittant test class error (index out of bounds) from the ReturnNRandomRecords component

Old Versions

v3.2.1 12/20/23 Production Sandbox Contains additional tests and cleanup courtesy of Jeroen Burgers

v3.2.0 – 12/14/23 – Eric Smith – Production Sandbox

  • Added a new Return N Random Records action (Derek Camp)
  • Added a new Convert to/from CSV String and Text Collection (Eric Smith) *also available as a reactive screen component

3.1.1 5/14/23 Production Sandbox

3.0.4 10/10/22 Production Sandbox – improvements to FindCommonAndUncommon and MapCollection

3.0.3 Unmanaged 4/21/22 (Production or Dev)

3.0.3 Unmanaged 4/18/22 (Sandbox)

3.0.1 Unmanaged 4/18/22 (Production or Dev)

3.0.1 Unmanaged 4/18/22 (Sandbox)

3.0.0 Unmanaged 4/17/22 (Production or Dev)

3.0.0 Unmanaged 4/17/22 (Sandbox)

1.34 Unmanaged 2/25/22 (Production or Dev) – bug fix for upsert

1.34 Unmanaged 2/25/22 (Sandbox)

1.33 Unmanaged (GetRecordsFromIDs now additionally outputs records as a JSON string)

1.32 Unmanaged (enhances Upsert to support JSON record data)

1.31 Unmanaged (adds support to Map Collection for mapping numeric fields )

1.30 Unmanaged (bug fix)

1.29 Unmanaged (adds permission set 6-19-21)

1.28 Unmanaged (adds CollectionCalculate 5-23-21)

1.27 Unlocked (add Dedupe Records)

1.25 Unlocked (add Get Records from Ids 3-8)

1.23 Unlocked (add Find Uncommon and Common 2-13)

1.20.2 Unlocked (some bug fixes)

1.20.1 Unlocked (adds bulkification to remaining unbulkified actions)

1.19.3 Unmanaged (fix bug in Generate Collection Report)

View Source

Source

Let’s Get Toasty!

There has been a simple Show Toast action available on unofficialsf.com that you could use in a Flow to display a pop-up toast panel with a message of your choice. Recently I’ve seen users asking for things like being able to control the display time or including a clickable link in their message.

I decided to add those options to the component along with additional features such as the display mode, custom icons and a title.

Read on to see how you can install and use this enhanced component in your own org.

How It Works

This action uses the force:showToast event

It takes multiple attributes. You can control the message, display type and mode, duration and even include a clickable link in the message.

Using the Component

You can use this Lightning Component in a Flow to configure and display a Toast message.

Parameters

(Required)

  • Type – Success (default), WarningErrorInfo Other
    • Other is styled like Info but is displayed without an Icon unless you specify a custom icon to use.
  • Message – The message to display in the toast
    • To include a clickable link in the message, place the characters {url} in your message and provide values for the URL Link and URL Label parameters.

(Optional)

  • Title – Text to appear above the message in a slightly larger font
  • Icon – The name of the Utility icon to display when choosing a Type of Other
  • Mode – Dismissible (default), Pester Sticky
    • Dismissible will display the toast message until the close button is clicked or the duration time has elapsed.
    • Pester will display until the duration time has elapsed. No close button will be available.
    • Sticky will remain displayed until the close button is pressed
  • Duration – The default is 10 seconds and the minimum is 5 seconds.
    • The duration attribute only applies to Dismissible and Pester modes
  • URL Label – This is the Label for the link in your message
    • To include a clickable link in the message, place the characters {url} in your message. At run-time the message will be updated to replace {url} with the value of your URL Label parameter and it will link to the address you specified in the URL Link parameter.
  • URL Link – This is the URL for the link in your message

Sample Usage

This first example shows how a Toast Message can be activated with just a message and defaults.


This example generates a Warning message with a Title, 15 second duration and no close button.


This example generates a Toast Message with a Custom Icon and will be displayed until the close button is clicked.


This last example includes a Link to a newly created record from the Flow.

{!vContactId} holds the record ID of the new Contact
In the message, {url} will be replaced with a Link defined by URL Label and URL Link
This is the URL Label
This is the URL Link

fContactRecordURL is a special formula you can use to combine the correct URL with the currently running domain name and the recordId you want to display.

LEFT({!$Api.Partner_Server_URL_340},FIND("/services", {!$Api.Partner_Server_URL_340})) & {!vContactId} 

Eric Smith – December 15, 2019

Spring ’20 Flow Feature Preview

I’m pleased to share some of the upcoming highlights of Spring ’20.

Trigger on Record Change Events

Flow Builder now allows you to trigger on record changes, but there’s a catch: in Spring ’20, our support extends to “Before Save” triggers but not “After Save” triggers. The practical ramification of this is that when you trigger on a record change in Spring ’20, you’re going to be limited in the Flow elements you have access to. Here’s what the palette looks like:

Note the absence of Update Records and Create Records. “Before Save’ triggers require a bit of a shift in thinking. The best way to think about “Before Save” triggers is that they allow you to do one thing really well: modify the record that caused the trigger to fire. The key is understanding what’s implied by the words “Before Save”: Flow gets notified when the triggering record is starting to get saved, giving you a chance to make changes to that specific record before the save actually happens. The saving will happen automatically after the flow ends, and so there’s no Update Records.

Because of this special location in the save order, you get positive and negative effects. The main positive effect is performance: Before-Save triggers carry out field updates 10x faster than the standard Process Builder trigger (which is an ‘After-Save’ trigger). The downside is that you don’t get access to Actions and Subflows and you can’t update related (or unrelated) records.

Access the new triggers by double clicking on the Start element in Autolaunched Flows:

We’re working on building out additional triggering capability for delivery in 2020.

Flow Simplification – Automatic Field Discovery and Automatic Output Handling for Actions and Create Record

Flow Simplification is a major multi-release campaign that focuses on making flows easier and faster to build. In Spring ’20, the big announcement is the elimination of the much disliked requirement to specify, in the Get Records element, the entire set of fields that you want to use later in the Flow. That’s over now. Flow automatically detects the fields you use and makes sure to retrieve them. Note that you can still choose to specify these fields manually, and for existing flows, we stay in this new ‘manual’ mode rather than try to do any conversions.

Automatic Output Handling was introduced in Winter ’20 for Get Records and screen components. It is now supported in Actions and Create Records as well.

Invocable Actions can use Generic SObjects with Flow

This enabling technology allows the construction of invocable actions that are designed to operate on any sObject, or any collection of sObjects, that are passed in to them. As a non-developer, you’ll experience the benefit of this in the form of a range of highly-useful new Flow Actions that work on any collection you throw at them. Here are some unofficial actions that we’re experimenting with:

Note that in the image above, although some of the actions are labeled with the word “Account”, those actions are actually called things like Sort Collection and Remove First Record, and can be used in the next flow over against Leads, or your custom objects. In most cases, you _can_ already do these things in Flow, but you often have to set up loops, assignments and updates, and these actions eliminate all of those steps.

As a user of these actions, you play an important role in declaring which specific Sobject or SObject type you’re going to use for this particular action.

For example, in the Flow above, the Sort action has been configured to sort accounts. Suppose that you want to use it to sort a custom object called BakedGoods__c. When you drag it onto the canvas, you start by declaring the specific objects you’re going to assign to each generic attribute. You initially see this:

The declaration has to be completed before the rest of the inputs and outputs are displayed:

An unmanaged package of collection actions is available for installation here on Spring ’20 orgs.

Invocable Actions can provide Custom Property Editors (PILOT)

You will be able to request from Support that your org be enabled for this pilot, which allows invocable actions to use custom property editors. In the slide below, you can compare the baseline, one-size-fits-all property editor that is provided to all actions with a custom property editor built for an Update Field action:

Internal Salesforce teams are already working on sophisticated applications of this, such as this specialized Email action being built for a marketing application that uses Flow:

Run Flows in System Mode

Set your flow to run in system context with sharing. The flow still respects org-wide default settings, role hierarchies, sharing rules, manual sharing, teams, and territories, but it ignores object permissions, field-level access, and other permissions of the running user.

Additional Goodies

Multi-level Field Traversal

You can now traverse through multiple levels of related records/lookups in Flow Builder popup menus:

Deactivate from inside of Flow Builder

Conditional Field Visibility now immediately detects newly created screen fields

Improvements to Keyboard Shortcuts – Click on the canvas and type ‘/’ to see the updated list of available shortcuts

Improved searching in the Toolbox

Session Videos from Dreamforce

Here’s a list of all of the Flow sessions and their video links and slides(where available). Sorry about the formatting.

Credit: Sam Reynard and Dary Hsu

Session NameRecording (only available for breakouts)SlidesSpeaker(s)TrackFormat
The Future of Automation on the Customer 360 Platformhttps://www.salesforce.com/video/7772150/John Kucera, VP Product Management, SalesforcePlatformBreakout
10 Game Changing Flow Solutions And Templates To Level Up Your Orghttps://www.salesforce.com/video/7765225https://success.salesforce.com/0693A000007QoI6Sam Reynard, Product Manager, Salesforce; Sharon Klardie, Salesforce Labs Evangelist, SalesforceAdminBreakout
Agility and Innovation: The Business Case for Automation and FlowMissing video due to audio issueshttps://success.salesforce.com/0693A0000081uQSJason Teller, Sr. Director, Product Management, Salesforce; Adam Dalton, Applicaiton Product Manager, Facebook; Kristy Wong, Business Value Services Director, SalesforcePlatformBreakout
Advanced Flow for Admins: Become A Salesforce Developer Using Clickshttps://www.salesforce.com/video/7785200Slides not uploadedAlex Edelstein, Sr. Director, Product Management, SalesforceAdminBreakout
An Admin’s API Integration: External Services and Flowshttps://www.salesforce.com/video/7829516https://success.salesforce.com/0693A0000081ucTAmi Assayag, Founder, CRM Science; Kirk Steffke, VP, Technology, CRM ScienceAdminBreakout
Automate & Personalize with Lightning Flow in CommunitiesMissing videohttps://success.salesforce.com/0693A0000081udlPhil Weinmeister, VP, Product Management, 7Summits; Jarrod Kingston, Director of Solution Engineering, 7Summits; David Litton, Director, Solutions Architecture, Ad Victoriam SolutionsAdminBreakout
10 Ways to Get Creative with Lightning ComponentsMissing videohttps://success.salesforce.com/0693A0000081ugpEric Smith, Director of Software Development and Engineering, GWIAdminBreakout
Put Predictions into Action: Einstein Prediction Builder and Next Best Actionhttps://www.salesforce.com/video/7829463Slides not uploadedSara Asher, Director, Product Management, Salesforce; Alex Edelstein, Sr. Director, Product Managemenet, Salesforce; Tejas Sanghavi, Director, Product Management, SalesforceEinsteinBreakout
Strike Lightning with Lightning Flows to Automate your Business Processeshttps://www.salesforce.com/video/7810491Slides not uploadedStephen Spencer, Sr. Solution Architect, LevAdminBreakout
Build Your First Flow With Our Top 5 Tipshttps://www.salesforce.com/video/7805543Slides not uploadedKristi Brown, Architect, Altium; Tracie Hart, Salesforce Administrator, AltiumAdminBreakout
Deliver Repeatable ISV Solutions With Flow Templateshttps://www.salesforce.com/video/7830069Slides not uploadedLizz Brooks, ISV Technical Evangelist, Salesforce; Danny Chang, ISV Technical Evangelist, SalesforcePartner CommunityBreakout
Prebuilt Business Processes with Flow Templateshttps://www.salesforce.com/video/7823752/https://success.salesforce.com/0693A0000081upSJason Teller, Sr. Director, Product Management, Salesforce; Phil Weinmeister, VP, Product Management, 7SummitsPlatformBreakout
Developing Modern Enterprise Apps with Flow and Next Best Actionhttps://www.salesforce.com/video/7828490Slides not uploadedAlex Edelstein, Sr. Director, Product Management, SalesforceDeveloperBreakout
Custom Notifications with Flow Builder: An Alternative to Email Alertshttps://success.salesforce.com/0693A000007QlFJAdam Marks, Founder, Cloud Think ConsultingAdminTheater
Use a Lightning Web Component in Flowhttps://success.salesforce.com/0693A000008b8ioSri Kolagani, Member of Technical Staff, Salesforce; Charleen Shakman, IT Business Relationship Manager, Johnson ControlsAdminTheater
Create Integrated Flows with External ServicesSlides not uploadedXintong Zhang, Product Manager, Salesforce; Belinda Wong, Director, Product Management, Salesforce; Jennifer Jin, Software Engineering MTS, SsalesforceDeveloperTheater
Flow and Apex Showdown!https://success.salesforce.com/0693A0000081uTMTim Peng, Product Manager, Salesforce; Chris Peterson, Product Manager, SalesforceDeveloperTheater
Build Seamless Interactions with Lightning Flowhttps://success.salesforce.com/0693A0000081uV3Dary Hsu, Product Marketing Manager, SalesforcePlatformTheater
Increase Productivity with Screen Flowshttps://success.salesforce.com/0693A000008b51vShannon Hale, Sr. Director, Product Management, SalesforceAdminTheater
Flexing Admin Muscles – Tricks with Lightning, Flow, & Working with Developershttps://success.salesforce.com/0693A0000081X9sRich Englhard, CEO, Englhard ConsultingPlatformTheater
Lightning Flow: The Best Feature You’re Not UsingSlides not uploadedChris Emmett, Pre-Sales Consultant, MakepositivePlatformTheater
Flow Basics for Nonprofit Adminshttps://www.salesforce.com/video/7829411Slides not uploadedJessie Rymph, Success Content Specialist, SalesforceSalesforce.orgTheater
AppExchange Flow Solutions Made Easy: Conquer Your Fear of Flowhttps://success.salesforce.com/0693A000007QiksSam Reynard, Product Manager, SalesforceAppExchangeTheater
Share Records using Lightning Flowhttps://success.salesforce.com/0693A0000081ueoKatharine Anderson, Salesforce Project Manager, The Nature ConservancyAdminTheater
Building an Intuitive User Experience with Context-Aware Lightning Flowhttps://success.salesforce.com/0693A0000081ufrSunil Damle, Salesforce Technical Architect, Fannie Mae; Saheb Samanta, Salesforce Architect, Fannie MaeDeveloperTheater
Unleashing the Power of Apex, LWC, and Flow in Lightning ExperienceSlides not uploadedParth, Sevak, Solution Architect, Slalom ConsultingPlatformTheater
Use External Services in Flow Because APIs are not just for Developershttps://success.salesforce.com/0693A0000081uhnCharles Stevenson, Salesforce Manager, PartnerizeAdminTheater
Designing High Performance Flowshttps://success.salesforce.com/0683A000008Q1tXNathan Lipke, Principal Member of Technical Staff, SalesforceArchitectTheater
Supercharge Processes and Flows with Invocable Apexhttps://success.salesforce.com/0693A0000081uquDonald Bohrisch, Salesforce Leader, MST Solutions; Pat McClellan, Chief Lightning Officer, Proton 7 GroupDeveloperTheater

Creating a unique collection in flow by GORAV SETH

GORAV SETH shared a quick tip on his blog about a way to create a unique collection in flow
https://goravseth.com/creating-a-unique-collection-in-flow

The Record Detail Component

This Post was most recently updated on: 7/6/23
Current Version: 1.9.1

The RecordDetail component provides new ways to display record fields in Flow screens. Flow excels in providing fine control over field combinations, but sometimes you just want to show a bunch of fields from a record in one place without a lot of configuration. This component handles all the formatting, provides 2 column layout, and takes advantage of additional goodies that the platform provides.

If you don’t provide a specific set of fields, this component will show the entire record:

But you can pass in a specific list of field names:

…and you’ll get just the fields you asked for:

If you set the mode attribute to ‘edit’, you can make changes inline and save them immediately with a save button. Note that unlike everything else in Flow, changes you make inside of this component do not get output for use downstream in the flow. In other words, this component will not output a full record. So if you want to use the data that has just been entered and saved, you’ll need to add a separate downstream Get Records element to pull the full record ‘back’ into Flow.


Earlier versions displayed the fields without any separation between lines.

This update adds underlines when in View Mode to improve readability. This more similar to a standard record detail view.

The underlines will not appear when you are in Edit Mode.


Styling Options

You can apply SLDS classes to the MAIN BOX of this Screen Component.

The major classes for themes are: 
slds-box slds-theme_default
slds-box slds-theme_shade
slds-box slds-theme_shade slds-theme_alert-texture

More Details: https://www.lightningdesignsystem.com/utilities/themes/

To use this, set the input attribute

The default values is “slds-box slds-theme_default”

But not limited to these classes but you can also add other classes like padding, margin, grid, alignment, visibility, and custom CSS classes as well (especially if you’re using this screen component in Lightning Flow within a community)

Attributes

recordIdInput – This is the ID of the record to display or 
Output – The ID of a newly created record.
recordTypeId When provided, picklist values will be filtered for the selected record type. Note that if the
object has multiple recordtypes, you _must_ provide a record type Id. Note that it’s easy to provide a picklist that lets the flow user select a record type.
objectApiNameIf you pass in no recordId, an Object API Name, and mode of Edit, the component will open in edit mode and create a new record on save.
modeMode (View or Edit)
fieldsA comma-separated list of field names from the recordId’s object type. If this is not provided, this component will display all fields accessible to the running user’s profile.
flowNavigationOnCancelDirection Specify Previous or Next for the flow navigation direction after the Cancel button is clicked.
flowNavigationOnCancel Check if you would like the flow to navigate to the Previous or Next screen when clicking Cancel.  
For best results, hide the page footer in the flow screen.
flowNavigationOnSave Check if you would like the flow to navigate to the Next screen (or Finish) when clicking Save.  
For best results, hide the page footer in the flow screen.
isCancelButton Output – This value will be set to True is the user selected the Cancel button.
showCancelButton = false;
Can suppress the Cancel button
suppressToast = false;Provides a way to suppress the toast that normally displays
suppressUnderline = falseProvides a way to suppress gridlines
SaveBtnLabel = ‘Save’;Allows changing the label for Save
CancelBtnLabel = ‘Cancel’;Allows changing the label for Cancel
columnsize = 2;Sets custom width, out of 12
boxclassapplies css classes to the frame of thecomponent. The default values is “slds-box slds-theme_default” See “Styling Options” above
versionUsed only to display the current version of the component. No entry is required.

Installation

This component requires that you first install the Flow Base Packs

FlowActionsBasePack Version 3.15 or later
FlowScreenComponentsBasePack Version 3.2.0 or later

7/6/23Eric Smith

Fixed bug where no fields were displayed when the recordId was not provided by a reactive component on the same screen

Production or Developer Version 1.9.1
Sandbox Version 1.9.1

Old Version Notes

6/9/23Eric Smith

Updated the dependencies for the required Base Packs

Production or Developer Version 1.9.0
Sandbox Version 1.9.0

Version 1.7.4 (Production/Dev) 3/18/21

Fixed a reference to the old base components. Credit to MattyZee

12/26/20Eric Smith
Refactored to use new FlowScreensBasePack instead of the older Flow Base Components
Version 1.7.3 Unlocked

Version 1.7.2 Unlocked 10-5-20 -Adds ‘boxclass’ attribute for styling

Version 1.7.1 Unlocked 8-9-20

1.7.1 Enhancement by Eric Smith

  • Added way to turn grid lines on/off

1.7 Improvements by MHamza

1.6 – Bug Fix by Eric Smith (4/29/20)

1.5 – Enhancements by Eric Smith (4/16/20)

  • Added underlines to fields when in View Mode to improve readability

1.4 – Fix for required system fields on record create screen (2/9/20)

1.3 – Enhancements by Eric Smith (1/24/20)

  • Added a feature to display and handle a Cancel button when in Edit mode
  • Added an option to support flow navigation on record save and cancel
  • Included descriptive labels and help text for Flow parameters

1.2 – Adds ability to pass in a Record Type Id

View Source

View Source

Synergies

You can have RecordDetail automatically display the subset of fields that’s tied to a particular combination of profile and record type by using actions like:

There’s a good video of this here.

Considerations

This component uses the recordEditForm and recordViewForm base components and is constrained by their limitations. It doesn’t support all Salesforce standard objects. For example, the Event and Task objects are not supported. This limitation also applies to any record that references a field that belongs to an unsupported object. The list of supported objects is here.

If you are creating a new record and don’t select a list of fields, the component will include some system fields a required such as Created Date and Date Last Modified.

This component responds to your Display Density settings (“Comfy”, “Compact”, etc…).

For behavior like Required and Validation, think of this component as ‘listening’ to the object and field manager in Setup instead of to Flow Builder. I.e. if the field is configured in Setup required in Setup it will be required in this component. If there’s a validation rule on the field in Setup, it will run on save here.

See more Flow Screen Components

Archived Versions

Version .1.7 Unlocked

Version 1.5 (Unmanaged) Production
Version 1.5 (Unmanaged) Sandbox

Version 1.4 (Unmanaged) Production
Version 1.4 (Unmanaged) Sandbox

Version 1.2 (Unmanaged)

Version 1.1 (Unmanaged) (only installs on Spring ’20)

Version 1

How to Include Chatter Posts on Printable Views

This image has an empty alt attribute; its file name is chatter-logo1.png

In Spring ’19 Salesforce added a Printable View button to many Standard and all Custom Objects. The Printable View includes the current user’s page layout and related lists. What it does not include are any Posts that users have added to the Chatter Feed.

In this Blog Post, I’ll show you how to add a button to your Lightning Record Page that will create your Printable View including Chatter Posts.

This post covers how to add this capability to the Case object. You can apply all of these same steps to support this feature in other objects of your choice.

The first step is to add a custom field to Case to store the details from the Chatter Posts.

Here I create a Rich Text field called Case Chatter Feed with a default length of 32,768 characters.

The next step is to update my Page Layout to include this new field. In this example, I have also added a new Section to put it in.

Now, when I want to create a new Printable View of my record, I must first populate this field with the current content of the record’s Chatter Feed. I can handle this step by running a Flow. The only attribute I need to pass into this Flow is the record ID (varCaseId) from the Case page.

In this body of this Flow I get all of the user created Chatter Posts and Comments and insert them into my new custom field. Later in this post I will show you how the first and last steps in this Flow tie everything together.

In the first Get Records step, I get all Feed Item records related to the Case and specify the fields I will be using later in the Flow.


I then Loop through each of those Feed Items by referencing the collection variable {!Get_Feed_Item_Records} that was automatically created by the Get Records step. Here I also create a new single Record variable {!loopFeedItem} to store each record inside of the loop.


In the Decision step, I skip any Feed Items records with a blank body. This way I’m only processing user created posts. You can modify this logic if you want to include more details.


Because the Feed Item records only include the user’s ID, I use a Get Records step to get the user’s name to include in my Chatter Feed field.


In the Assignment step, I build out each of the Feed Item fields I want to show as part of the Post as well as the formatting of the information. This is done by using the Add operator to build out the full feed one piece at a time.


We end up turning this from the Chatter Feed:

Into this in our custom field:

I’ve used a combination of Formula resources and Text Template resources to build out each post.

  • ttLineSeparator (Text Template)
    • ~
      ~
  • fSpaceSeparator (Text Formula)
    • ” | “

For each Feed Item I do another Get Records to find any Feed Comments associated with the current Feed Item.


I then Loop through each of those Feed Comments by referencing the collection variable {!Get_Feed_Comment_Records} that was automatically created by the previous Get Records step. Here I also create a new single Record variable {!loopFeedComment} to store each record inside of the loop.


Just like I did with Feed Items, I skip any Feed Comments with a blank body in the Decision step.


Because the Feed Comment records only include the user’s ID, I use a Get Records step to get the user’s name to include in my Chatter Feed field.


I continue to build out my chatter posts field by adding Feed Comments and formatting in the Assignment step.

Here I’ve used some additional formatting variables.

  • ttCommentSeperator (Text Template)
    • .
  • fCommentIndent (Text Formula)
    • ” —– “

After the Feed Comment Loop is completed, I add one more Assignment step to add a separator before the next Feed Item.

  • ttItemSeparator (Text Template)
    • ______________________________________________________________________________________________

After the outer Feed Item Loop is finally completed, I add one more Assignment step to cleanup the separations between the lines.

This is a little trick you can use to put line separators (Carriage Return, Line Feed) inside of a text field. Text Templates support separate lines but they can’t contain just a single separator so my ttLineSeparator Text Template includes a single special character on each line that get removed by my fFixCRLF Formula.

  • ttLineSeparator (Text Template)
    • ~
      ~
  • fFixCRLF (Text Formula)
    • SUBSTITUTE({!varBodyText},”~”,””)

The last piece needed to get my Chatter Posts into the Case record so they can be displayed is to add an Update Records step to save the record with the newly built Chatter Feed details.


Now I will show you how to add a couple more pieces to this Flow so we can use it on a Lightning Record Page and have it open a new Tab with the Printable View.

I want to put this Flow on the Case Lightning Record Page but I don’t want it to run until selected by the user. I handle this by adding a Screen to the beginning of the Flow that displays a custom image and waits until the user clicks on it before continuing with the rest of the Flow. Here I’m using the Image Button Flow Screen Component from unofficialsf.com. I’ve added the display, hover and pressed images for the button as Static Resources to my org so they can be referenced by the Image Button component. (Follow the Image Button link for complete documentation on this component)

Select the display image and the action to take when clicked
Select the images to display during mouse hover and mouse press
Select the size of the image

The final step in my Flow is an Action that opens a new Tab with the URL for the Printable View of the Case record. Here I’m using another component from unofficialsf.com. This one is the Open URL Flow Action. (Follow the Open URL link for complete documentation on this component)

The URL for the Printable View is created with a formula that combines the Base URL for the running org with the Case Record Id and the Printable View URL identifier.

  • fPrintableViewURL (Text Formula)
    • LEFT({!$Api.Partner_Server_URL_340}, FIND(‘/services’, {!$Api.Partner_Server_URL_340})) & {!varCaseId} & “/p”

All I need to do now is to activate then add this Flow to the Case Lightning Record Page and configure it to pass in the recordId to my varCaseId input variable.


I’ve created a couple of Installation Packages for those who want to try this out in their orgs. The first package includes both the Image Button and Open URL components. That package will only install in your org if you have neither of those components already installed. The second package does not include those components and the provided Flow must be edited to access them. I’ve provided instructions in the Flow showing how to do that.

1 – Install Package with Custom Case Field, Components, Image Static Resources and Sample Flow

Production
Sandbox

Post Package Install Instructions

  • Add the new field ( Case Chatter Feed ) to the Case Page Layout
  • Activate the Flow ( Case – Printable View with Chatter Posts )
  • Add the Flow to the Case Lightning Record Page

2 – Install Package with Custom Case Field, Image Static Resources and Sample Flow (No Components)

Production
Sandbox

Post Package Install Instructions

  • Make sure you have the current version installed for the Image Button component
  • Make sure you have the current version installed for the Open URL component
  • Add the new field ( Case Chatter Feed ) to the Case Page Layout
  • Edit the Flow ( Case – Printable View with Chatter Posts – Template )
    • See the instructions in the 2 Flow Screen elements
  • Activate the Flow
  • Add the Flow to the Case Lightning Record Page



Using SFDX to Easily Create Packages

My packaging pipeline has really improved in the last few months, thanks to sfdx and packaging commands that are now available. I thought I’d put together a video showing how to take a Flow/NBA app (or really any Salesforce app) and easily package with the most effective tools.

Enhance your Flows with Data Tables – Part 4 (Inline Editing)

Lightning Flow Screen Components are a great way to add power to and improve the look of your Flows.  In this four-part series, I’ll show you how a single component, designed to display a list or table, can enhance your Flows.

The unofficialsf.com website includes Datatable as one of many Flow Screen Components you can use for your own organization.

This component is derived from the datatable Lightning Base Component.  I recently enhanced the base component to be more powerful and Admin friendly.

I will be showing you some examples about how the Datatable component:

  • Can be used in place of a Record Choice Set (Dynamic Record Choice) for selecting a record while displaying more than a single field
  • Can be used to select multiple records from an object then perform additional actions on them
  • Can be used to present your data in an interactive and visually enhanced format
  • Can be used to display and inline edit a collection of records

Part 4: Inline Editing

In November of 2019, Kirill Boyarkin, updated this component to support inline editing. Now you can specify individual columns as editable and the changed values will be passed back to your Flow so you can update the object records.

In this example, I created a simple Flow to present a list of Account records with the Annual Revenue column set to editable.

The Get Records node populates an SObject Collection variable with the records and fields I want to display in my datatable.

I pass that collection into the datatableFSC component on my Flow Screen, define the columns I want to display and set the Revenue column to be editable.

This component has a lot of attributes, so make sure you assign any output attributes in the Output Values section. For my output attributes, I select “Manually assign variables (advanced)” and assign my new SObject collection variable to the same Collection – Accounts attribute I used to pass in my records.


NOTE: The output attribute for selected records (Output Selected Accounts) is only used for identifying selected records in the datatable and may not contain the updated values. When you are combining editing and selecting in a single table, use the “Output Selected Accounts” attribute to get the list of selected records and their IDs and use the “Collection – Accounts” attribute to access the edited records.


The final Update Records node in my Flow is to update the Account object with my collection of edited records.


If you Show the checkbox column with your datatable, you will be able to select multiple rows and optionally apply an edit to all of the selected rows.

By default, the component will display Cancel and Save buttons once you start making edits. You can bypass this option by setting the “Show Save and Cancel Buttons?” attribute to False. Any edits will then be automatically saved once you hit the Next button.

Note: If there are a large number of records in the datatable, the Next button will always display at the bottom of the screen, but the user will have to scroll to the end of the table to see the Cancel and Save buttons.


See the complete series on how you can use the datatable Flow Screen Component in your Lightning Flows.

Part 1 – Use a Datatable to present a dynamic choice for record selection in a Flow.
Part 2 – Use a Datatable in a Flow to select and act on a collection of records.
Part 3 – Use a Datatable to display a formatted, interactive table in your Flow.
Part 4 – Use a Datatable to inline edit a group of records.