Files are stored in an object called ContentDocument. When a file is shared with a record or when it is directly uploaded to a record, Salesforce creates a ContentDocumentLink record in the system. ContentDocumentLink is a junction object between a ContentDocument (file) and a record. In order to share files with other records, you just have to create a ContentDocumentLink between the file and the target record. Read this Salesforce article to learn more about these objects.
ContentDocumentId and LinkedEntityId are the two main fields of the ContentDocumentLink object. ContentDocumentId represents the Id of the file and LinkedEntityId is the Id of the record that you want to share the file with. LinkedEntityId is a polymorphic relationship field. It means that it supports multiple objects. It can be a record, group, Salesforce CRM Content Library, or a Chatter user.
Let’s suppose that there is a record with some related files. You are creating a new record and you want those files to be related to the new record that you are creating. In this case, since those files already exist in the system, you don’t have to upload them again. You can use Salesforce Flow to share those files with the new record. When you do so, same files will be attached to multiple records. It is important to note that, when you delete the file itself, it will be removed from all of the related records. Consequently, delete the ContentDocumentLink records instead of deleting the file itself. Let’s create a record-triggered flow to automatically share all the related files of an account when a new case is created. You can use also the other Flow types to perform this.
Using Record-Triggered Flow to Share Files
1- Create a Record-Triggered Flow and select Case as the triggering object. Select the trigger to run when the case record is created. You can select the other trigger options too. Select optimize for Actions and Related Records. This option will make it an After-Save Flow.
2- Since it is a Record-Triggered flow, you can use the $Record global variable to reach to all the field values of the new case record. Because of this, there is no need to perform a get for the related account. You can directly perform a get for the ContentDocumentLink records in order to find the related files of the account.
In order to find the files of the account record, drag and drop Get Records from the toolbox. Select ContentDocumentLink as the object and filter the records by the LinkedEntityId field. This field value should be equal to the AccountId of the case record. Don’t forget to get all the results and not only the first one.
3- If there is no file under the account, then there is no need to continue. Add a Decision element to check if the system found any records in the previous step. If the ContentDocumentLink collection (flow automatically created it in the first step) is not null, it means there are files.
4- If there are ContentDocumentLink records, add a Loop element to iterate over each item in the collection variable. Read this post if you don’t know how to work with collections in Salesforce Flow.
5- Create a record variable for the ContentDocumentLink object. Add an Assignment element to assign values to this variable. ContentDocumentId is the Id of the file and it should be equal to ContentDocumentId field of the current item from the loop. Then map the LinkedEntityId field to the Id of the new case.
6- Create a new ContentDocumentLink record variable like you did in the previous step. However, this time mark it as a collection. After assigning values to the ContentDocumentLink record variable, you have to add this single record variable to the new collection variable that you created. In order to do that, add a new Assignment element.
End the loop after this step.
7- At the end of the 6th step, you have a collection variable with the records that you want to create. Now it is time to create them. Add a Create Records element to create all of the ContentDocumentLink records at once.
You can create the records inside the loop too, but it consumes one DML limit for each record creation. Consequently, you might hit the DML governor limit of Salesforce. On the other hand, flow’s performance becomes slower. It is recommended to work with a collection in order to create the records at once (like in this example). This way, it consumes only one DML limit.
At the end, your flow should look like this.
Salesforce Time account record has 2 files.
After creating a new case record, you can see that those files are automatically shared with the case.
There can be many files related to the account record and you want only specific ones to be shared with the case record. In this case, you can add a decision element inside the loop to check your condition.
Let’s assume that you want to share the files that contain “Salesforce” in their title. Add a Decision element to check the current file’s name. ContentDocumentLink doesn’t contain the title of the file, but it has a lookup to the ContentDocument record. You can find the title from the related ContentDocument record.
If it contains “Salesforce”, continue like you did before. If not, go back to the loop in order to continue with the next file in the collection.
At the end, your flow should look like this.
Salesforce Time account record has 4 files but only 2 of them contain “Salesforce” in their title.
After creating a new case record, you can see that only 2 files are automatically shared with it.
What happens if there are files under the account record but none of them meets the criteria?
Nothing. As you can see on this post, when you perform a create operation for an empty list of records, flow doesn’t fail. It just doesn’t create any records.