Salesforce Obscura: Auto-copy a File to a Rich Text Field with Flows

Option 2 of 2 — using ScreenFlows to upload the file from an Experience Cloud setting

Example Use Case and Solution Overview

For this article, we tackle a very common request from our clients: getting a Customer Community User to upload their own photo and displaying that photo in a rich text field for internal users to view and use.

  1. Prepare the Contact record with a Rich Text field to display the photo and a field to help control the Flow
  2. Create a Screen Flow and set up its Resources
    (2a) New Resource: ContactRecordID
    (2b) New Resource: CVID
    (2c) New Resource: UploadedCVIds
    (2d) New Resource: TypeOfFile
    (2e) New Resource: DocumentURL
    Getting the URL for the Image tag
  3. Create the initial logic and file upload screen
    (3a) New Get Records: Find Related Contact Record
    (3b) Decision: Do we have a contact record at all? With or without a photo?
    (3c) Add Element: Screen under “Yes — With Photo”
    (3d) Add Element: Screen under “No”
    (3f) Add Element: Screen under “Yes — No Photo”
  4. Process the uploaded file and update the Contact record
    (4a) Loop: Process Content Version IDs
    (4b) Assignment: Assign CVID variable
    (4d) Assignment: Set Photo Fields on Contact Record
    (4e) Update Record: Update Contact
    (4f) Save and Activate your Flow
  5. Embed the Screen Flow into the Experience Cloud page
    (5a) Add Flow to Contact Detail Page in the Builder
    (5b) Configure the Flow Component
  6. Test

(Step 1) Create 2 new fields on your object.

Add the following fields to your object:

  • A text field, 18 characters long, to contain the ID of the file you will upload. I called mine “Photo CV ID” (note, you could make this a checkbox or anything else, it just aids in routing your screen flow)
  • A rich text field to display the photo itself. I called mine “Photo” and just took the defaults for a rich text field.
Two new fields — one for the ID, one rich text, on your target object

(Step 2) Create a new Screen Flow and Set Up Resources

The overview of my Screen Flow is below. I am first confirming that I get the information I need (Contact ID from the Experience Cloud page, in this case) and then determining which of 3 screens to show — a “thank you” message, our main uploader, or an error screen.

The full Screen Flow overview, designed to be embedded in a Contact Record page
Create your Contact Record ID variable and ensure it is Available for Input so that it can be embedded properly
  • Resource Type: Variable
  • API Name: ContactRecordId
  • Description: This variable contains the ID of the Contact Record that embeds this flow
  • Data Type: Text
  • Make sure to check the box next to Available for Input
Create a variable to hold the ID of the Content Version of the file uploaded by the user
  • Resource Type: Variable
  • API Name: CVID
  • Description: Content Version ID for use in a formula
  • Data Type: Text
Create a collection variable to contain the Content Version IDs returned from the file uploader
  • Resource Type: Variable
  • API Name: UploadedCVIds
  • Description: This collection contains the record set required by the file uploader to get the Content Version IDs back
  • Data Type: Text
  • Check the box next to “Allow multiple values (collection)”
New variable TypeOfFile to help control the embedded display
  • Resource Type: Variable
  • API Name: TypeOfFile
  • Description: The uploaded photo can be one of several image types. This helps the rich text field display the photo correctly.
  • Data Type: Text
The formula that actually performs the photo embed
  • Resource Type: Formula
  • API Name: DocumentURL
  • Description: This is the formula that allows for the preview in the rich text field.
  • Data Type: Text
  • Formula:
    ‘<p><img src=”https://REPLACEME.file.force.com/sfc/servlet.shepherd/version/renditionDownload?rendition=ORIGINAL_'+{!TypeOfFile}+'&amp;versionId='+{!CVID}+'&amp;operationContext=CHATTER" alt=”Photo” height=”200" width=”200"></img></p>’
  1. Manually upload an image file to a Contact record
  2. Click on the file to open it in the File Preview. Right click (command+click on mac) and copy the preview to my clipboard.
  3. Paste from my clipboard into a Rich Text field on Contact and save my changes.
  4. Use dataloader.io to export only the record I’m testing with, and only my rich text field. The html for the working, pasted image will show up in plain text in the export, allowing you to mimic it in this formula field.

(Step 3) Add the Initial Logic and Screens to your Screen Flow

In Step 3 we will build the pieces shown in the image above: get the contact, decide what screen we need to show, and show the screens.
Use the ContactRecordID variable to find and store the full Contact record.
  • Label: Find Related Contact Record
  • Description: Look up the Contact record for the ID that was passed in to the ContactRecordID variable
  • Get Records of This Object: Contact
  • Filter Contact Records: All Conditions are Met (AND)
  • Filter Contact Records: Field: Id [equals] ContactRecordID
  • Sort Order: Not Sorted
  • How Many Records to Store: Only the first record
  • How to Store Record Data: Automatically store all fields
  • Label: Did we find a record?
  • Description: This screen flow can only be launched from a Contact page so we should always find a record. It is still a best practice to check for errors.
Decision part 1: We have a Contact record and it already has a photo
  • Label: Yes — With Photo
  • Condition Requirements to Execute Outcome: All Conditions are Met (AND)
  • Set up the first condition: Contact from Find_Related_Contact_Record [is null] False
    In this condition, we are asking if the record itself is null / did we get anything back from the lookup in step 3a. Under Resource, choose the Find Related Contact Record result that was automatically created when you set up step 3a. Click on it. It will populate your field with {!Find_Related_Contact_Record.} and prompt you to select other fields.
Look for the record related to Find_Related_Contact_Record, or whatever you named your Get Records in (3a)
This is what your first condition should look like: {!Find_Related_Contact_Record} with no period
  • Set up the second condition: Contact from Find_Related_Contact_Record.Photo_CV_ID__c [is null] False
    In this condition we are asking the simpler question of whether the Photo CV ID on the Contact Record is empty or not. Follow the same steps as the first condition but this time look for the Photo CV ID field when prompted for a field selection.
Outcomes two — nearly identical, except we want to detect that the Photo CV ID is empty this time.
  • Label: Yes — No Photo
  • Condition Requirements to Execute Outcome: All Conditions are Met (AND)
  • Set up the first condition: Contact from Find_Related_Contact_Record [is null] False
    This condition is set up exactly as you did for Outcomes 1.
  • Set up the second condition: Contact from Find_Related_Contact_Record.Photo_CV_ID__c [is null] True
    This condition is set up exactly as you did for Outcomes 2 except you want True instead of False. For this decision, we care about a Contact that exists but does not yet have a photo.
The completed, very simple confirmation that we already have a photo for this person.
  • Click + under “Yes — With Photo” and choose “Screen”
  • Screen Properties: Label: Confirm Photo
  • Screen Properties: Description: This contact already has a photo or has successfully uploaded one.
  • Optional: Configure Header: I also chose to configure the header and uncheck “Show Header” to make the embedded Screen Flow a bit more seamless
  • Optional: Configure Footer: I chose to uncheck Show Footer entirely. This is informational only, no actions are needed so no buttons should be visible.
  • API Name: ConfirmPhoto
  • In the rich text editor, to display your message: We have received your photo. Thank you.
The finished result of a simple Contact Error Display Text screen under the “No” (default) decision
  • Click + under “No” and choose “Screen”
  • Screen Properties: Label: Error Contact Not Found
  • Screen Properties: Description: This screen only appears if there is a problem passing the Contact ID or a problem with the end user reading the Contact Record.
  • Optional: Configure Header: Uncheck “Show Header” as above
  • Optional: Configure Footer: Uncheck Show Footer as above
  • API Name: ContactError
  • In the rich text editor, to display your message: We can’t find the Contact ID, sorry.
Screen properties for our File Upload Screen with Header and Footer configured
  • Click + under “Yes — No Photo” and choose “Screen”
  • Screen Properties: Label: Upload Your Photo
  • Screen Properties: Description: Upload a photo of yourself to share with our team.
  • Configure Header: Check “Show Header” and (optional) Show Help Text.
  • Configure Footer: Check “Show Footer”.
  • Configure Footer: Next or Finish Button: Use a Custom Label (“Save File”)
  • Configure Footer: Previous Button: Hide Previous
  • Configure Footer: Pause Button: Hide Pause
Upload File with the settings shown in the right-hand part of the screen.
  • API Name: UploadPhoto
  • File Upload Label: Upload
  • Accepted Formats: .jpg,.png,.gif
    Note: you can just type in a comma-separated list of accepted formats
  • Allow Multiple Files: False
    Note: click into this field and type false. It will set the field to {!$GlobalConstant.False}
  • Content Document IDs: leave this blank
  • Content Version IDs: LEAVE THIS BLANK
    This version of the settings will not do what we want. We’ll handle this in Advanced, below.
  • Disabled: leave this blank
  • Hover Text: leave this blank or put some sort of help text in if you prefer
  • Related Record ID: {!ContactRecordID}
    Find the ContactRecordID resource you set up in step 2a.
  • Uploaded File Names: leave this blank
  • Optional: Set Component Visibility: I have left this to “Always”
  • Check the box for “Manually Assign Variables”
  • Leave everything else blank except for Content Version IDs
  • Content Version IDs: {!UploadedCVIds}
    Find the UploadedCVIds collection resource you created in step 2c.
  • Revisited Screen Values: Check next to “Refresh inputs to incorporate changes elsewhere in the flow”
The Advanced options for File Upload are the same as the standard ones, but you must set the Content Version IDs here instead of in the standard settings for this example to work.

(Step 4) Process the uploaded file and update the Contact record

Still in the “Yes--No Photo” logic branch, this last step of the Flow will process the uploaded file so that it is put into the Contact Rich Text field. It’s a little unintuitive if you’re not a programmer, but basically even though we are limiting the File Uploader to only one file, it will return our Content Version ID in a collection. So we have to process that collection as if there were more records in it, even though there aren’t.

The portion of the Flow we are working with in Step 4 — directly under the Upload Your Photo screen
Set up a Loop to process the UploadedCVIds from the file uploader
  • Click + under the Upload your Photo screen icon
  • Choose Loop
  • Label: Process Content Version IDs
  • Description: Although we only allow one file to be uploaded, the value is returned in a list so we have to process it in a loop
  • Collection Variable: {!UploadedCVIds}
    Use the UploadedCVIds variable you created in step 2c and populated from the Flow Uploader Advanced Setup in step 3f
  • Direction: First item to last item
Assign the current item from Loop’s value to the CVID variable.
  • Click + under the loop you added in step 4a
  • Choose Assignment
  • Label: Assign CVID variable
  • Description: Although we only allow one file to be uploaded, the value is returned in a list so we have to process it in a loop
  • Set Variable Values: Variable: CVID
    Use the CVID resource you created in step 2b
  • Set Variable Values: Operator: Equals
  • Set Variable Values: Value: Current Item from Loop Process_Content_Version_IDs
Find the Content Version record for the CVID in this loop
  • Click + under the Assign CVID variable you added in step 4b
  • Label: Get CV from ID
  • Description: Use the ID of the Content Version to obtain the file type
  • Get Records of This Object: Content Version
  • Filter Contact Records: All Conditions are Met (AND)
  • Filter Contact Records: Field: Id [equals] CVID
    Use the CVID resource you created in step 2b
  • Sort Order: Not Sorted
  • How Many Records to Store: Only the first record
  • How to Store Record Data: Choose fields and assign variables (advanced)
  • Where to Store Field Values: In separate variables
    Store the Content Version’s File Type field in the resource TypeOfFile you set up in step 2d
  • Field: File Type
  • Variable: TypeOfFile
Add this step on the “After Last” line by clicking the + indicated by the arrow, then choosing Assignment
Set the assignments for the Contact record that started our flow
  • Click + on the “After Last” line
  • Choose Assignment
  • Label: Set Photo Fields on Contact Record
  • Description: Set the Photo-related fields on the Contact we found to start this flow
  • Set Variable Values: Variable: Contact from Find_Related_Contact_Record.Photo__c
    Use the Find Related Contact Record that was automatically created for you in step 3a, and select the rich text Photo field you created in step 1. We are populating this field on the Contact record.
  • Set Variable Values: Operator: Equals
  • Set Variable Values: Value: DocumentURL
    Use the DocumentURL formula resource you created in step 2e to populate the rich text field Photo on Contact.
  • Set Variable Values: Variable: Contact from Find_Related_Contact_Record.Photo_CV_ID__c
    Use the Find Related Contact Record that was automatically created for you in step 3a, and select the text Photo CV ID field you created in step 1.
  • Set Variable Values: Operator: Equals
  • Set Variable Values: Value: CVID
    Use the CVID resource you created in step 2b to populate the rich text field Photo on Contact.
Update Contact just uses the record we’ve been working with this whole time and is the last step in the flow setup.
  • Click + under the Assignment you created in the last step
  • Choose “Update Records”
  • Label: Update Contact
  • Description: Update the Contact that started this Flow with the data collected from the file upload
  • How to Find Records to Update and Set Their Values: Use the IDs and all field values from a record or record collection
  • Record or Record Collection: Contact from Find_Related_Contact_Record
    Use the Find Related Contact Record that was automatically created for you in step 3a.

(Step 5) Embed Your Flow into Experience Cloud

This last step is really just icing. And don’t worry, it’s very simple! If you already know how to embed a Screen Flow on a Record Page in Experience Cloud, you can skip ahead to the testing.

In Experience Cloud Builder, on Pages, we are working with a Salesforce Object page, Record Detail layout.
Drag the Flow component into your page canvas
  • Click on the component to open up its contextual configuration window.
  • Flow: Upload Photo From Community
    or whatever you named the flow you created in steps 2–4
  • Check the box next to “Pass record ID into this variable” under the “ContactRecordID” variable.
  • Save and publish.

(Step 6) Test it out

Please note that it is beyond what I can tackle in this article to address all of the permissions issues and things that could stand in your way in a Customer Communities license setting, so make sure the user you’re testing with can actually edit their own Contact record and upload files before testing your solution.

  • A File attached to the Contact record for the user you are logging in as
  • A value in the Photo CV ID field
  • A 200x200 view of your file in your rich text Photo field

--

--

Operationalizationer — one who defines a fuzzy concept so it becomes clear, measurable, and empirically observable. Founder @ deepwhydesign.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jenn Taylor

Operationalizationer — one who defines a fuzzy concept so it becomes clear, measurable, and empirically observable. Founder @ deepwhydesign.com