Wizard News is going to answer our first “Letter to the Developer.” This column was originally intended for developers, but, as I mentioned in last weeks post, we’re expanding it to Salesforce & Wizard questions in general.
For our first column, we hear from David with a flow question.
Hi, I've been playing around with headless flows and love them. I still need to get my head around collections, because they're not quite clicking for me (needing to populate a second collection based on assignments based on the first collection, in order to do a Fast Update). So.. the question I have is, is it possible using the Loop function or some other way within a flow to loop through a set of dates and create records based on them. Say I have a start and end date on object A. I want to loop through all days from the start to the end date and create records (1 / day) on record B. Is that possible, and if so...how? Thanks, David
Dear David,
After some forethought and some experimenting, this is something you definitely can do with flow! First let’s clarify what Loops, Collections, and sObject Variables are with Flow.
sObject Variable in flow represents 1 record of 1 specific object type. For example, it can be a single record of an Opportunity. Once defined we can set field values or create, update, and delete that record from Salesforce.
sObject Collection in flow represents multiple records of a single object. So it could be 5 opportunity records. Once defined we can create, update and delete all the records within that collection. We can also use an element to loop and do something with each record
Loop in flow represents an element that will take a sObject Collection and pass each individual record – one at a time – to the next element. Once all records have been “looped” through, it’ll go to the “end of loop” element. This is useful when you do a Fast Lookup and have multiple records that you want to review.
In the flow I’ll use today we’re going to create multiple records based on two date fields. I’m going to find multiple Opportunity records and look at each opportunity. Based on the Created Date and Close Date of each opportunity we’ll create a new task – one for each day between Created Date and Close Date. I’m not going to use this as a headless flow. Instead, I’m going to add screens to the flow so you can each see the major steps.
Here’s what we need in the flow:
- ThisDate – Variable using the date format
- NewTask – sObject Variable for a Task Object
- ThisOpportunity – sObject Variable for a single Opportunity
- ListInboundOpty – sObject Collection variable that will contain a list of all our Opportunities
- ListNewTasks – sObject Collection variable that will contain all the Tasks we’ll create
- OpportunityName – This is a screen input for this flow, but could be a variable if using Headless flow. This so we can query which Opportunities we want to include
I’ve also added a few extras for the “screens” that will show you the number of tasks that will be created for each iteration of the loop and the total number of tasks.
The flow elements, excluding screens, will be:
- Fast Lookup – to query for all the Opportunities. The flow will find any Opportunities where the name starts our ‘OpportunityName” input. This could also be a variable set by a flow trigger if using Headless flows
- Loop – Loops through the sObject Collection ‘ListInboundOpty”
- Assignment: Sets the “ThisDate” variable to the Created Date of “ThisOpportunity” which is the Opportunity record we’re currently looking at in the loop
- Decision: Compares “ThisDate” with the Close Date. If the “ThisDate” is less than or equal to the Close Date it goes into the task create elements. Otherwise, it’ll return us to our loop
- Assignment: Sets the values for the fields in the “NewTask”
- Assignment: Adds the “NewTask” to the sObject Collection “ListNewTasks”
- Fast Create: Creates all the Tasks in the sObject Collection “ListNewTasks”
The above overview includes some extra assignments and screens for demo purposes.
The Details
Fast Lookup
We start with the Fast Lookup. This can return one record or many records depending on what is specified in the filters. There are three very important parts of a fast lookup.
- Filters – The filters control which records will be returned. In this situation I’m doing a Name Starts With filter. I can add additional filters to make sure only the records I want to return go into the flow. This could be an ID of a record and often is if you’re using Headless flow
- Variable assignment – this is where the record(s) will be stored in the flow. It can be either a single sObject Variable (one record) or a sObject Collection (many records). To be safe, I recommend always doing an sObject collection unless there is NO POSSIBLE WAY of getting more than one record, for example, your filtering by record ID
- Fields – this will be the fields and values stored in your collection or sObject variable. Make sure to include only what you need, but include what you need. In my flow, I’m capturing the ID, CreatedDate, CloseDate and Name. I’m using the last 3 items within the flow and I like to capture the ID for any debugging purposes.
The Loop
The loop variable does something very simple and very important. It lets you take all the records within a sObject collection and review each individual record one at a time. There are two important components to the loop:
- sObject Collection – what are you looping through
- sObject Variable – What variable will hold the individual record you’re currently looking at within the loop
This is an important distinction. The Loop doesn’t loop through anything other than sObjects. Think of the Loop as a digital PEZ dispenser. It holds multiple pieces of candy (records) but only gives you one at a time. The loop lets you draw two lines, one for the “Next Element” which passes 1 record over and the second line for when you’re out of candy.
Decision
If you’ve been using Flow for a while, you’re probably familiar with the decision element. This is basically a big “If this then that” step. You define the “That” through “Outcomes” and then you define the “if this” as the criteria for each outcome. In my flow there’s two outcomes: “Still More Dates,” and “No more Dates”
My criteria for “Still More Dates” is simply “ThisDate” is less than or equal two ThisOpportuniy’s close date. This outcome means I have more tasks to create. The other, or default outcome, means there are no more tasks to create.
You MUST have at least 2 outcomes for a decision, but you can have multiple outcomes – each with their own criteria.
Assignment defining Field values
Assignment elements are wonderful things. They can be used to set variables within your flow and recently you can use them to specify field values for sObject Variables and add them to a sObject Collection. In this element, I’m setting the value for the Subject, ActivityDate and WhatID (related record) for “NewTask.” That’s it. I could also use this same element to add to a sObject Collection, but I like to keep this neat and use a second assignment element to do that.
I’m also using the Assignment element to add 1 day to “ThisDate” each time I go through the decision path. Each time I go to the Decision element I’m re-comparing to see if “ThisDate” is now greater than my Close Date. I keep adding 1 day to “ThisDate” until the Decision takes us to the “No More Dates” outcome.
Fast Create
Finally, our Fast Create element. This can create a single record from a sObject variable or create multiple records that are within a sObject Collection. I’m doing the latter in this flow. I’m creating all the records at once within the collection. I consider this a best practice and it prevents me from creating the records within the loop which may cause an error if I have too many records.
You need to keep your validation rules in mind when using Fast Create. Flows run under the same restrictions a user as if they were manually creating the records. If you have a validation rule that requires a field and you do not fill that field in – your flow will cause an error. Keep that in mind.
Overview
So there’s our flow. We start by querying our Opportunities and then we loop through each record. For each record, we compare our dates using a Decision element. If we need to create a record, we add 1 day to our date variable, assign values to our Task record (sObject Variable) and then add that Task to our collection. We then go back to the decision and compare the updated “ThisDate” to our Close Date. Repeat as necessary. Once we’ve created tasks for all the days between the Created and Close date we go to the next record in the loop. Finally, once we’ve looped through all the records, added all the tasks to the collection, we create the actual tasks.
Want to see what the finished result looks like? You can see a video of it here http://youtu.be/2PYHIY6zk18 Sorry there’s no audio to walk you through it. I haven’t quite figured out how to record audio and video without causing my computer to go on strike.
There are some considerations to this flow. A fast update element is limited to 200 records at a time. Plan accordingly, if your flow has a chance to create more than 200 records you’ll want to do a decision tree to do a fast create when you hit 200 records, then empty your collection and start adding new records. Rinse and repeat. This method also has an upper limit. You can only have 150 DML elements (Create, Update, and Delete) with a maximum of 10,000 records created from DML statements. Consider using asynchronous APEX if you have to create that many records.
You can find information on the limits of Flow here: https://help.salesforce.com/HTViewHelpDoc?id=vpm_admin_flow_limits.htm&language=en_US
David – and everyone else reading this – I hope you find this helpful.
Signed,
The Developer aka The Salesforce Wizard
Want more information about Loops and flow? Check out my video Wizard’s Apprentice Lightning Experience – sObject Variables, Collections & Loops Revisted
A Note From The Editor
A little secret about WizardNews posts. I hate writing Post Titles. I struggle with trying to write titles that are informative, accurate, and grab your attention. One of the more difficult parts is not to interject my sense of humor into the title – too much. For example, alternative titles for today’s post included:
- Yay! Someone used the Letters to Developer form!
- Once again into the flow dear friends!
- Loopy for Loops
- Want to come to my office and see my sObject Collection?
What other titles can you come up with for this week’s blog post?
-
[…] Letter to the Developer: The “Date Loop” to Create Records with Flow […]
Leave a Reply
This is so close to what I think I’m looking for…would it be possible to get more details. For example off the Loop you have an Assignment “Default Count to 0″….what are the details behind that assignment? I’d love to see that level as I think I can use this as a framework to solve a problem I’m working on!
Hi Virginia,
So the Flow may have more than 1 Opportunity which means they may be multiple tasks to be created for multiple opportunities. The TaskCount is something I used for information and debugging purposes. It’s counting the number of tasks being created for each individual Opportunity. This means when the next Opportunity comes up I need to re-set my task count to 0 so I don’t include the previous Opportunities tasks in the count.
Like I said it’s really just informational. When something goes wrong I can see how many tasks get created for each Opportunity and how many are created for the Whole process.
Thanks! That was just enough for me to see through the debug and get to the essence of what I needed and it worked!
Thank you again!
Hi David, really great post and was a a big help for some work i am doing on flows.
I have a follow up question if you don’t mind!
I have an oppty and oppty line items and i also have a Work order and work order items object,
i want to automate the creation of a work order and work order items from the oppty and oppty line items (source to target for a parent child relationship). I can do this “without” using the new Loop/collection/sobj variable/ fast create/ fast lookups, but wonder if i could use them?
I tried but i just could not get the work order items to be created from the oppty lines , apparently it might not be a good use case for these features as its not possible to use different objects when usign the new features? not sure why !
any steer would be great ! thanks
Same requirement as simon75uk only that the Flow I have in mind loops through the Account team and copies that list to the Sales team. Might seem simple but boy, did I spend (actually still spending) a lot of sleepless nights thinking about it!
Hello, I’ve read through this and I’m still not quite sure,
Is this explaining how to create a new record for each date between a Start Date field and an End Date field on the same record?
Or is this simply just creating a new record for each DIFFERENT record’s “Created Date” in the loop?
Nicholas Z,
This flow is assuming you’re getting multiple Opportunities in that “Fast lookup.” So the flow is actually create a new record for each day between the dates… for each Opportunity that is queried.
With the tools we have today, I would replace the lookup by Opportunity Name with the Opportunity Id and have this Flow called by the process Builder.
Thank you soo much
You’re Welcome so much!
Hi Brian. This is a great pointer to a solution for which I have a similar problem I cant figure out. I want to create a number of custom records called Tour Dates. The user is asked to specify the first day of the week that the tour date should start and then check any of seven day-of-the-week check boxes, (Mon, Tue, Wed, etc.) to indicate whether any of these days should be (chekcked = true) or should not be (Checked= false) tour dates. They then complete a field ‘No of weeks’ to specify how many weeks these tour date patterns should be repeated. I think I should be trying to generate a Collection variable called ListTourDates from the users input which I can then loop through to fast create a set of tour date records. However I cant figure out how to populate the Collection variable with a list of tour dates. I would be grateful for some advice on this. Many Thanks Mark Riley
Okay, assuming I understand this correctly. You have a screen element with a date and 7 checkboxes.
For each box checked you want to “save” that date for that.
What’ll you need to do is to create a decision tree. You’ll need 7 decision element, one to check each checkbox. If the checkbox = true, then go to an assignment element that will add the date to a collection variable (or alternatively create the tour date record and add it to an sobject collection). Then go to the next decision element.
Hi Brian, Thankyou very much for clearing the mists from my eyes! This is just the steer I needed
Can you help me understand the details behind the Screen elements? Thank you!
Hey Brian, thanks for this tutorial breakdown. Can you add a screenshot or expand on what the “Default Count to 0” actually does? Are you creating a custom variable (called something like “OppRecCount”) and then assigning it the value of 1? Is that the only operation you’re performing in that Assignment action?
That exactly what I’m doing. You have a custom variable and setting the value to 0
Thanks for clarifying! And what action are you performing in the Assignment Element ‘CurrentDateViewed’? What needs to be assigned?