Using a dynamic choice to select multiple records in visual workflow
With a small trick, Dynamic choice elements in visual workflow can be used to display multiple records, and only act on the selected record(s).
In a previous post, I described how to create a button that could copy all attachments from an email to the parent case.
I’ll now describe a more advanced version, which uses a dynamic choice to display a checkbox for each attachment, and only attaches the selected item(s).
The dynamic choice flow resource makes it straightforward to display multiple records as checkboxes. However, it does not provide a clear mechanism to take action when multiple records are selected. Dynamic Choices can only be mapped to a sObject variable, not a sObject collection. sObject variables can only store a single record, and therefore per the docs, only the most recently selected record that will be stored.
When a multi-select choice field uses a dynamic record choice, only values from the last record that the user selects are stored in the flow variables.
That makes multi-select dynamic choices effectively useless. However, it turns out the flow can write all of the selected IDs from the screen multi-select field itself, which makes magic possible. The dynamic choice itself can map to anything - it doesnt matter. You just need to ensure that the choice stored value is the ID, and then you work with the screen multi-select field.
Credit for this approach goes to a great tip on developer.force.com by Joe Cook (See his comment from Dec 24 2014 - its not selected as best answer but should be!)
The approach is as follows:
- use a fast lookup with the same criteria as the dynamic multi-select choice to populate a sObject collection with same initial set of records as the dynamic choice.
- Determine which records were selected by looping through the sObject collection and checking if the record ID is present in the screen multi-select field. If it is present, then that means it was one of the selected records, and it can be added to a ‘selected’ collection. If not, move on to the next one.
So that is the theory. This is what it looks like in practice:
- fl Get Email: lookup email and get parent ID (could pass in via url, i normally do a lookup anyways)
- fl Get Attachments: populates sObject collection with ALL attachments on the email
- scrChooseAttachments: this screen has the dynamic choice, which writes the IDs for all selected records to a text variable
- loop through attachments: loops through the sObject collection of attachments from step 2
- decision decIncludeThisAttachment: evaluates if the text variable from step 3 contains the attachment ID. the ‘include’ outcome is when there is a match, and the default outcome returns back to the loop to evaluate the next record
- assignment Set Parent Id: sets the parentID on the attachment loop variable to the CaseId from the email.
- assignment add Attachment to New Collection: adds the loop variable to a new sObject collection that will be used in a fast create at the end of the flow
- loop back through the other attachments and run through step 5-7
- fast create create attachments: once loop is complete, there will be a sObject collection that contains the selected attachments with parentID set to the case. The fast create will create new attachments on the case for the attachments that were selected in the case
Dynamic Choice (3): stores ID, displays name
Decision element (5) - this is where we evaluate if the loop variable ID is present in the screen multi-select choice element. That is the trick and the magic.
As noted on the previous post, this approach with attachments goes against the documentation and could stop working, but the approach for parsing multi-select dynamic choices is, to the best of my knowledge, valid and good.
And one last enhancement - in the final version I added some logic so the attachment selection screen is only displayed if there is more than 1 attachment. 1 less click! This fully built solution can be installed from this package for testing purposes only. This is provided for demonstration purposes only and is used completely at your own risk. Please let me know if you have feedback.
And some final thoughts - It could be better, but is more complex, to loop through the list of selected IDs, as there would be fewer records to loop through - but overall the difference should be minimal for most use cases. Rakesh Gupta offers a managed package that can parse a multi-select choice to a collection variable here. As its a managed package, you cant open the flow to see how it works, but he has details on how the parsing process works here. Its some smart thinking - but I have not been able to internalize it, and since I cant open the flow I cant explore and dig into it. I would like to try and make my way through each screenshot someday, but for now I’ll use the simpler approach outlined in this post!