Salesforce Flow Loop Basics | Clone or Share Files using Flows

How to Copy a File from one object to another using Flows in Salesforce? How to copy a File Link from one Record to another in Salesforce Flow? In this article we see how to use Loops in a Flow and how to use Assignment Elements in a Flow through this Use Case - Share or Copy a File from one Record/Object to another in Salesforce. Basically, we will see how to Share a specific File with Multiple Records which also includes a way to Copy a File from One Object to Another in Salesforce .There are many ways to achieve this (like using Apex etc.), but we will do File Sharing / Cloning using Flows. In this article, I will use an After Update Record Triggered Flow to show this use case.

Salesforce Flow Loop Basics | Clone or Share Files using Flows
We will get a basic idea about the File objects like Content Document Link and its role in File sharing or cloning from one record to another. Using this file Object (Content Document Link), we will see how can we Share a File with many different records in Salesforce.

Main Takeaways from this Article:

1. How to Create Multiple Records in a Flow without a Create Element inside a Flow Loop (Bulkify Flow)?

We will see how to Bulkify a Flow when we need to create Multiple New Records in a Flow. I will use an After Update Record Triggered Flow to show this. We will see how to create Multiple Records without using Create Element inside a Loop. 

Please checkout my old Post which covers this Topic of Creating Bulk/Multiple Records in a Flow in very detail with Videos and Step by Step Pictorial Explanation : BULKIFY FLOW: CREATE MULTIPLE RECORDS IN A FLOW

2. How to Share or Clone a File with many Records using a Flow? 

We will see how to use File Objects to share a File with other Records using a Flow.

3. How to use Loops in a Flow? Learn How to Use Loops in a Salesforce Flow

We will see how to effectively and properly Use Loops in a Flow and use Collection variable data of Get Elements in a Flow Loop. We will see how to avoid using Data Elements like Create Element inside a Loop and instead use Assignments to create Multiple Records at once. I will also show WRONG / INCORRECT way of using a Create Element inside a Flow Loop.

4. How to Use Assignment Element in a Loop in the Flow? Learn How to Use Assignment Elements in a Flow

5. How to Copy a File from one Object to Other in Salesforce

We will go through the concept of using Assignment Elements in a Loop to achieve Bulkification of Flows and to avoid using Multiple Create Elements or using Create Element inside a Loop. This is a very important step while creating Multiple Records in a Flow.

Before we see how to do it in Flows, if you are not familiar with Files and Content Document Link Object relationships in Salesforce, below is some background and info on the same. 

Note: If you are already familiar with Files and its Object's Relationships, you can jump directly to the Flow Use Case and skip the below part.

What are File Objects and Relationships in Salesforce?

Every File uploaded in Salesforce has three Objects which are in Relationship with each other

Content Document: It Represents a document that has been uploaded to a library in Salesforce CRM Content or Salesforce Files.

Content Version: Represents a specific version of a document in Salesforce CRM Content or Salesforce Files. In other words, this object stores document information similar like Attachment.

ContentDocumentLink: This object actually shares a File with Users, Records, Groups etc. We can create Multiple records to attach/share the same files with multiple records.

Every File record in Salesforce has a related record of an Object named Content Document Link which is a junction object between Content Document (File) and a Parent Object like Account, Case or any  Salesforce Object 

What is Content Document Link Object?

Content Document Link is the Junction Object between Content Document (Salesforce File) and the Parent Object (on which File is attached) which is referred in the field Linked Entity ID.

Basically, any File record in Salesforce can be Linked or Shared with many different records (even on different objects). For every single pairing of a particular File with a Record, a Content Document Link record is created which is a kind of link between File and Parent Record. Each record of this pairing is basically a record of the Object Content Document Link.

It has two main fields which we need to remember. First field is called Content Document Id which is actually the File Id. For a single file shared with 'n' number of records, there will be 'n'  number of Content Document Link records. But in all of these 'n' records of Content Document Link , the Content Document ID remains same since the File is same. But each one of these Content Document Link records will have a different value in the field name "Linked Entity Id" which is actually the Id of the record on which the file is associated.

For example, if a file (Content Document) with name AccidentalCoderSF.jpg is to be shared or attached on 4 records i.e. two different Account Records and two Case Records, then there will be 4 Content Document Link records created in the backend/database. 
All 4 records of Content Document Link will have same Content Document Id (File Id ) since the same file is attached to all these 4 records. But, all of these 4 records will have a different value in the field Linked Entity Id which will be Ids of these 4 records respectively.

Important Note: The Field "LinkedEntityId" on Content Document Object's records cannot be updated or modified. So we basically cannot  update any existing Content Document Link record to reparent it to New Record. 
We can only share the same File with other records by creating new Content Document Link records for the same File.  

Checkout ScreenShot for more details about this Object. Check Salesforce Documentation for more details.

How to Copy/Share Files using Flow?

To Copy a File in Salesforce from one Record to another we need to create new Content Document Link record related to the File. 
For every new Share or Clone of the File to any other Record, we just need a new record of Content Document Link with the same Content Document Id as the File and the Id of the new Parent Record which is going to be populated in LinkedEntityId field of the Content Document Link. 

Clone / Share Files in Salesforce using Flows

The File Clone capability using Flows is possible using many different types of Flows like Auto-Launched Flows ,Screen Flows or Record Triggered Flows. But I am using a Simple Record Triggered Flow to show this functionality. 
Same Approach can be used in any type of Flow as the basic steps remain the same.

Use Case: On Case Records there can be multiple Files. We need to Share or Clone all these Files with the related Contact Record of the Case whenever the Case is Closed. In simple words, when a case is closed, share or clone all its files to the related contact record. 

We will achieve this by using an After Save Record Triggered Flow on Case Object which will Fire after Case is Closed and will Clone/Share all the Case Files with the respective Case's Contact Record Automatically.


Let's Jump Right into the Action.

Below is how the Final Flow will look like:

Share Files in Salesforce

Steps to Create this After Update Flow

1. Start Element: After selecting a new Record Triggered Flow, here we will choose the Type of the Flow. Since we need to do the File Sharing after Case is Closed or updated to Closed, we will use the After Update Scenario.

Also, we will choose the object as Case as Flow should fire when Case records are updated.

We will not Fire the Flow on every case update so we can put a condition to fire the Flow. The criteria to fire this Flow is simply, Case.IsClosed = True and ContactID not Null. Because we need to Fire the Flow is Case is Closed and Case has an associated Contact Record.

Also, we can choose to Fire this Flow only when our criteria is met after a particular update and not if the criteria was already true when update was made. It means we can only Fire the Flow if case is closed by an update and not every time the case is updated. 

After Update Flow

After Save Flow Salesforce

Note: When you work on a Record Triggered Flow, all the field values of the Record that Fired the Flow is available for us to use in variable $Record which can be used anywhere in the Flow.

2. Get Element : To Query all Existing Content Document Links Records for this Case.

As I have mentioned in this post earlier, for every File on this Case Record, we will have a Record of the Object "Content Document Link". ExampleIf I have a case with 5 files, it will return me 5 records of Content Document Link if I query on this object for that Record.

So we will just Query or Find all the Content Document Link Records for the Case Record that Fired this Flow. 
The simple criteria needed for this is "Linked Entity Id" field of Content Document Link record should be equal to the Case Id of the Case that fired the Flow. 

Note: If you do not understand why we do this here I recommend you go through the article again where I have shown the Importance  and usage of the field "Linked Entity Id".  This is a field which represents the Parent Id or the Id of the record which a File is associated to.

Clone Files using Salesforce Flow

Clone Files using Salesforce Flow
Important Note: When you use a Get Element and choose the Options of "Choose All Records" and "Automatically store all fields" as per the screenshot above the Get Element itself becomes a Collection Variable. It means it becomes a variable which can store multiple values automatically. This Collection variable can then be used anywhere in the Flow Later at any place where we can use a collection variable. 
In my example the name of Get Element is "Get Case Files" which now will behave as kind of collection variable in the Flow.
 
3. Decision Element : When we Query Records using Get Element it is not a guarantee that it will find some records for sure. If a case is closed and has no files than in that scenario the Get Element will not return any records. 

So as a best practise always use a Decision Element after the Get Element.

We will simply check if the collection variable of Get Element is Null or Not and only proceed in the Flow Processing if it's not Null.

Clone Records using Flow

Note: See how I used the Get Element's collection variable "Get Case Files " in the Resource Option. This is what I mentioned earlier that every Get Element with Multiple Records behaves like any other Collection Variable.


4. Loop Element : Till now we have made the Flow Run if Case is Closed. After the Flow Runes we queried on its Files Using Get Element. We also made sure Files are found for the Case that Fired this Flow.

Now, if Files are found we need to make sure we Share each and every File Found with the Related Contact of the Case. This process will make use of Loops and Assignments which we will see later.

But for now, we will just Loop or iterate on all the Files that were Found one by one.

So when we use a Loop Element it requires a Collection Variable to Loop on. So we will directly Loop on the Variable of Get Element "Get Case Files" . As I have mentioned multiple times earlier, Get Element itself is a Collection Variable in our Case.

Clone Files using Salesforce Flow

In our Use case we are Looping on all the Existing Content Document Link Records.

Very Important : So, basically the thought behind is that for every single Loop Iteration(or basically for every single content document link record from Loop) we just need to create new Content Link Document Record. We will just basically clone all the existing Content Document Links one by one but with one field value change for the new ones. The only field value that we need to change for every new Content Document Link Records is the "Linked Entity Id " which will be changed from Case to Contact Id in the new Records. The Content Document Id remains same in all the New Records since the same file has to be shared with Contact.

Note: If you do not understand why we do this here I recommend you go through the article again where I have shown the Importance  and usage of the field "Linked Entity Id" and "Content Document Id". 
Learn Salesforce Development from Scratch

Now, before we move ahead, let's see a WRONG WAY of Creating Multiple Records inside a Flow Loop. 

The simplest  and a wrong way to create Multiple Records inside a Loop if we are not aware of Flow Loops and Salesforce Best Practises is by simply Putting a Create Element inside the Loop Element.

In our Use case we are looping on all the Existing Content Document Link Records. We basically just want to create a New Content Document Link with Contact Id in "Linked Entity Id". So we can just use a Create Element inside the Loop like the screenshot below:

How to Use Loops in A Salesforce Flow?

How to Use Loops in A Salesforce Flow?

How to Use Loops in A Salesforce Flow?

Here I am just using this Create Element inside a Loop to create new Records of Content Doc Links but simply using Content Document Id from the Loop Variable which basically represents every single iteration of the Loop. In our Case, the Loop is on Content Document Link Records of the Case so basically every loop iteration is on a single Content Document Link Record. 

So for every Loop Iteration we will have the values of a single Content Document Link from Get Element and we can use this iterator variable's values in any way we want inside for kind of operation in the Loop. 
So, in my case, I simply used the current Loops iterator's Content Document Id to create a new Content Document Link Record in the Create Element. Also, I assigned the Contact Id from the $Record variable which is the Record which triggered this Flow in the field LinkedEntityId since this new content doc link records has to be shared with Case's contact.

So, when our Loop will run it will create a new Content Document Link record for every existing content document link by cloning it and just changing the LinkedEntityId to Case's Contact Id and keeping the Content Document ID (File Id) same. 

BUT THIS IS A WRONG WAY! We must never use any Data Element (Get, Delete, Create, Update) inside a Flow Loop. Never! Because of something called Governor Limits! 

The CORRECT WAY of using Loops in a Flow to create Multiple Records

Below is the Correct Way to use Loops in a Flow to create Multiple Records.

Let's Rewind. So till now in Step 4 we created a Loop Element to Loop on all the Content Document Links of the Case record which we got from the Get Element in Step 2. Now let's see next Steps.

Please checkout my old Post which covers this Topic of Creating Bulk/Multiple Records in a Flow in very detail with Videos and Step by Step Pictorial Explanation BULKIFY FLOW: CREATE MULTIPLE RECORDS IN A FLOW

5. New Variables for Storing New Content Document Link Data 

Since we will not use a Create Element now inside the Loop so we need to figure out a way. The way is by using Assignment Elements inside the Loop. We need to use two Assignment Elements basically now inside the Loop.

Before we do that we need two Variables of type Record and Object (Content Document Link).

First Variable will be a Single Variable (Not a Collection) of Type Record and Object : Content Document Link. 
Use of Loops in a Salesforce Flow
Second Variable will be a Collection Variable of Type Record and Object : Content Document Link.
Loops in a Salesforce Flow

The idea behind is this that when we loop on Records of Content Doc Links, we will first do the same thing to a blank/new Single Variable that we did using the Create Element when I showed the wrong way. We will assign the values of the fields to this new/blank variable in every Loop Iteration and then add this to the collection Variable.

The second variable which is of collection type will be used to store all the new single records of Content Document Link so that we can use this variable to create all new content doc links at once at last.

In very simple words, I will first we will create (but not save or insert) a single record of Content Document Link by using an Assignment Element. And after this , we will add this single record to the collection variable with the same loop iteration. This will be more clear in the later Steps.


6. Assignment Elements:

First Assignment Element: As I mentioned above, the First Assignment is to assign the Field Values to the single and blank Record Variable named as ContentDocumentLinkTemporary. We will just assign two field values similar to what I showed in the Wrong way when we used the Create Element Inside the Loop.

To this blank record variable of Content Document Link, we will first assign ContentDocumentID equal to the Loop Iterator's ContentDocumentId.
Also, similarly we will assign the LinkedEntityId as the Contact ID of the case using the global $Record variable.

Use of Loops in a Salesforce Flow

Second Assignment Element: 

Here we will just add the single record of Content Link Document created in last step to the bigger Collection Variable of same type and object. 
Assignment Element in a Flow


7. Create Element: At Last, we will just create all new records outside of the Loop at the End using a single Create Element by using the collection variable which we used in last steps.The collection variable we created was named "NewDocumentLinksToCreate" .
Loops in a Flow

And We are Done!

Below is a Quick Recap of all the Flow Steps again in a short Video. For any confusion refer my article and screenshots again.

Please checkout my old Post which covers this Topic of Creating Bulk/Multiple Records in a Flow in very detail with Videos and Step by Step Pictorial Explanation : BULKIFY FLOW: CREATE MULTIPLE RECORDS IN A FLOW

Hope this Helps! Reach out to me here or on LinkedIn for any questions, issues or suggestions. Happy to Help!

Don't Miss Latest Posts :  CLICK HERE TO SUBSCRIBE TO THIS BLOG

Checkout this Article for all Flow Related Scenarios : All Flow Examples
Learn Salesforce Development from Scratch


See you next time..

Comments

  1. brilliant post. ty

    ReplyDelete
  2. What should be the process if I want to associate an existing file in Salesforce every time a case record is created?

    ReplyDelete
  3. Content Document Link object show no fields so I can't address the ContentDocumentId. I can't find any information on this matter. Any help would be greatly appreciated!

    Thanks.

    p.s. Great Article!

    ReplyDelete
  4. I am attracted by the presentation of this article. This information about file sharing is really good. I really appreciate your work. It is a gainful article for us. Keep posting. Thank you.
    Wetransfer free

    ReplyDelete
  5. THIS IS AMAZING.. I FEEL LIKE I JUST FOUND MY GO TO PLACE FOR SOLUTIONS ON BUILDING FLOWS.

    ReplyDelete
  6. I was blind but now I see! Learned so much about Flow best practices and how to avoid all the governor limits that have plagued me in the past. Thanks so much!

    ReplyDelete
    Replies
    1. Is there a simple way to add a check into the flow to see whether a Content Document Link already exists for each file that associates it with the target record (in your case, whether there is already a CDL linking the file to the Contact)? My issue is that doing this based on a record update (like closing a Case or completing a task which is my use case) means that it is a one time thing and if for any reason someone were to reopen the case or task and try to close it again, they will encounter an error.

      Delete
  7. Thanks for shearing this kind of information clone

    ReplyDelete
  8. Lovely blog thanks for sharing

    ReplyDelete
  9. I'm creating a case when an opportunity is closed and want the files to me copied over onto the case. I get stuck on the assignment part where you assign the temp to a contact ID, where did you get that from? I was only able to drill into the opportunity that started the flow

    ReplyDelete
  10. This doesn't clone a contentversion only creates a new share in contentdeocumentlink . Nay changes or upload new version actions with update teh contet/file anywhere it is linked.. This does not clone the file/content

    ReplyDelete
  11. getting this error when trying to move notes: This error occurred when the flow tried to create records: REQUIRED_FIELD_MISSING: Required fields are missing: [ContentDocumentId]. You can look up ExceptionCode values in the SOAP API Developer Guide.

    ReplyDelete

Post a Comment

Thanks for your Feedback!

PLATFORM APP BUILDER CERTIFICATION - 78% OFF

POPULAR POSTS

Salesforce Flow Examples : Flow Use Cases and Scenarios

Flows | Use Flows to Bulk Update Records from List View in Salesforce

Flow Bulkification | Mass Update Records from Flows in Salesforce


Never Miss Latest Posts