Andy in the Cloud

From BBC Basic to Force.com and beyond…

Visual Flow with List View and Related List Buttons

86 Comments

Last years blog Clicks not Code with Visual Flow Custom Buttons has continued to be quite well received, so i thought i would explore what more could be done and address a few questions that have come up since. This blog does make some assumptions that you are already familiar with the approach from my previous blog.

This time i want to focus on using Visual Flows with list Custom Buttons, such buttons can be placed on List View layouts and Related List sections on Detail layouts. Salesforce also provides a means for the user to select specific records to process. These buttons apply to both Salesforce Classic and Salesforce Lighting Experience.

AccountFlowListView

As before we are keeping in the spirit of Clicks not Code, well with a little bit of reusable Visualforce code. But don’t worry you can easily copy and paste to adapt with a few changes. Critically with this approach you don’t need to resort to JavaScript based Custom Buttons, which will no longer be supported in Lighting Experience.

Handling Record Lists from Custom Buttons

First things first, ensure you have created a SObjectCollection variable in your Flow and ensured its designated as Input. For this blog we are simply going to display a step in the UI for each selected record. Using the Loop and Screen elements. One thing to keep track of is the fields your referencing within the Flow, in this case i’m using Account Name and Annual Amount.

SelectedAccountsFlow

List View Custom Button Example

Lets get started with a Custom Button on the Account List View. When adding a List Custom Button you have two choices, do you want the user to be able to select records or not? If not, then your button will pass all the records in the List View (currently limited to 2000).

So if when creating your Custom Button you plan to select the Display Checkboxes (for Multi-Record Selection) option. Then create the following Visualforce page, changing the object name and list of fields accordingly. This will ensure selected records are passed to your Flow.

<apex:page standardController="Account" tabStyle="Account" recordSetVar="AllAccounts" >
    <!-- Add below each field you reference in your Flow -->    
    <apex:repeat value="{!AllAccounts}" var="row" rendered="false">
        {!row.Name}
        {!row.AnnualRevenue}
    </apex:repeat>
    <!-- Runs your Flow -->    
    <flow:interview name="SelectedAccounts" 
          finishLocation="{!URLFOR($Action.Account.Tab, $ObjectType.Account)}">
        <apex:param name="SelectedRows" value="{!Selected}"/>
    </flow:interview>
</apex:page>

IMPLEMENTATION NOTE: If you want to avoid bothering with changes between lines 3-6, simply re-query the records in the Flow using the Fast Lookup element. Thought it’s less efficient this way since your not leveraging the query made by Visualforce.

If you don’t want the ability for the users to select records and want all records, the main difference to the above is a change to the line 10, passing in the AllAccounts binding.

    <!-- Runs your Flow -->    
    <flow:interview name="SelectedAccounts" 
          finishLocation="{!URLFOR($Action.Account.Tab, $ObjectType.Account)}">
        <apex:param name="SelectedRows" value="{!AllAccounts}"/>
    </flow:interview>

Don’t forget to add your button to the List View layout, select some records and give it a try!

SelectedAccountRow

Related List Custom Button Example

In this case the Visualforce page is much the same, accept that of course your placing the associated button on the Layout of the parent object by editing the applicable related list section. The following example shows a button on the Opportunities related list on the Account object.

<apex:page standardController="Opportunity" tabStyle="Opportunity" recordSetVar="AllOpportunities">
    <!-- Add below each field you reference in your Flow -->
    <apex:repeat value="{!AllOpportunities}" var="row" rendered="false">
        {!row.Name}
        {!row.Amount}
    </apex:repeat>
    <!-- Runs your Flow -->
    <flow:interview name="SelectedOpportunities" 
          finishLocation="{!$CurrentPage.parameters.retURL}">
        <apex:param name="SelectedRows" value="{!Selected}"/>
    </flow:interview>    
</apex:page>

RelatedListFlowButton

IMPLEMENTATION NOTE: Note that the above Visualforce page code uses a URL parameter retURL, which is not available in Lighting Experience. It still works, but leaves the user on the finish page.

Summary

For more information on passing values to Flows using Visualforce check out the docs here. With the exception of the retURL hack above, i’m pleased to see support in Classic and Lighting Experience. Though the later, has yet to obtain support for providing the record selection support, so only the all records use case is available.

At present Visual Flow styling does not quite look at home either in Lightning Experience, which made me wonder about trying SLDS styling with Flow’s CSS customisation abilities (i will let everyone known how successful this is!)…

AccountFlowListViewLEX

FlowInLEX

Finally both these approaches will also work equally well with Automation Flows (aka Headless Flows), just in case, as with the example in my earlier blog you just want to do some kind of calculations without prompting the user.

86 thoughts on “Visual Flow with List View and Related List Buttons

  1. I tried this for Opportunities but it will only show one record without looping and I the related list has more than 5 entries the checkboxes do not appear after selected Go to list (xx).

    • Yeah i hit this at first. Its not that obvious for a single element loop. But you have to connect your Screen element step back to your loop element. Note that mine has arrows point back and forth between the loop element.

  2. Thanks Andy, that was it.

    Is it possible to do a similar flow with Opportunity Line Items as the related list?

  3. Hello Andy, I am trying to use the Process Builder to Update the Quote Line Items retrieving the values from another object.
    For example:
    in Quote Line Items I have a custom field Route (example : Japan-Italy ) and Rate
    also I have a custom Object “Route” which stores the rate for a specific route.

    How can I update the Rate field QuoteLineItem records by record lookup on Object Route ?
    I created an Auto launch flow for Record Lookup and Update , but I can I pass the variable to the autolaunch flow for query?

    Thanks in advance
    Dimi

    • Yes you can pass the record itself or fields from the record. Create variables (of sobject type or text for example) in the flow and mark them as input, then they will appear in process builder to map to.

  4. Can this be done without creating a visual force page? Like if we just wanted to use the “list button” with option for “Display Checkboxes (for Multi-Record Selection)”. If so what would we pass to URL or ForURL fuction?

    • I don’t see how this can be done with just url only as it there is no way to encode multipe times. Why don’t you want to use vf page out of interest?

      • Visual force pages don’t have drag & drop layouts. That and why have an option to use related list checkbox if the checked IDs can not be passed as a value to URL or flow?
        It looks like there’s some javascript that will allow a button to determine is there has been greater then 0 boxes checked but its not clear how to pass that result to a flow & then the whole javascript end of support issue. I guess we could value “selectedOpportunityIds” to URL if using this javascript https://developer.salesforce.com/forums/?id=906F00000008ojdIAA

      • The option is available for Visualforce pages and JavaScript buttons. JavaScript buttons will not be supported in the new lightning experience ui so be careful with those. I am not sure what you mean by not having drag and drop layouts, your not really using Visualforce here for any ui, just as a means to launch a flow.

      • Also there is no string manipulation operations in flow to unpack your string.

  5. Pingback: Visual Flow with List View and Related List Buttons | SutoCom Solutions

  6. A note to those who might have been wondering like I did, the “param name” in the “flow:interview” is what your input variable name should be.

    Scott

  7. Hi Andrew,
    That’s a great post but I have one issue though.
    If I use relationships,some how they dont seem to work in Flows.
    Sales engineer is a custom lookup field to the user object on my opportunity and I added this {!row.Sales_Engineer__r.name} and turned the rendered on repeat to true which works perfectly fine but the flow fails saying “The flow failed to access the value for name.Sales_Engineer__r.Name because it hasn’t been set or assigned”.
    Everything else is similar to what you did.
    Any idea the reason and how to resolve this.

    • Hmmm that’s odd, it must be Salesforce is cloning the standard controller records, and only doing a shallow clone? You will have to query in the flow itself it seems. I am away from my computer at present, but if you want to send me a Gist snippet of your VF page and the bit of your Flow that is failing I can look later. Also try to enable the Workflow debug levels and see if they yield anything of interest.

  8. Sorry for all the duplicate comments, Apex tags were not getting rendered in the comments and I could not delete the comments later.

    Please see the code here http://pastebin.com/QvVTUJNr

    • I’ve reproduced this scenario and it partially works. I created a Test Custom Object and then added a Test__c lookup field to Account. I used {!row.Test__r.Name} in my VF page and in the Display Text element. What i found is it displayed correctly for records that had the Test__c field populated. But for records where this lookup field was not populated it bombs with platform error (maybe this can be worked around in the Flow formula to avoid this). I notice that the UI in the Flow designer does not support selecting relationship. My recommendation is you raise a support case with Salesforce to look into this. Or if it can work for you, create a Formula field on the Opportunity object that references Sales_Engineer__r.name. Finally it should not make a difference but try ‘Name’ instead of ‘name’.

  9. Hi Andrew,

    Thank you for this post. Concerning “Though the later, has yet to obtain support for providing the record selection support, so only the all records use case is available.” As I understood the multiselect (when checked ‘Display Checkboxes (for Multi-Record Selection)’ on a list button does not work for lightning so we have to pass AllAccounts into recordSetVar and create custom vf list view with check boxes for multiselect. Is this the only option for lightning if we need multiselect?

  10. Andrew, Thanks for your great posts! A question for you. When passing data in from the visualforce page (lines 3-6) if the record does not contain a value in a particular field and we try to access the value in that field we receive an error “The flow failed to access the value for because it hasn’t been set or assigned.” However sometimes a blank value is an appropriate thing for a field to contain. I’ve tried error capturing with a decision element but even the decision element fails with the same error. So generally i have to fall back to the other option you describe in your Implementation Note: “If you want to avoid bothering with changes between lines 3-6, simply re-query the records in the Flow using the Fast Lookup element. Though it’s less efficient this way since you’re not leveraging the query made by Visualforce.”

    So two questions:
    1. Is there a better way to pass data in from a Visualforce page when the field may not contain a value so that flow can handle it?

    2. If we need to requery the records in the flow, do you have a faster way to do the “simply re-query the records” step than what I am currently doing?

    Current process:
    1. Add a text field to the object for the records being queried.
    2. Use a Fast Update – update all selected records and put some unique value (typically using the current date/time) into the new text field just created.
    3. Use a Fast Lookup to then query those same records using the temporary ID field as the criteria to lookup the same set of records.

    For some reason the flow treats records queried in a fast lookup differently than those passed in from a visualforce page and I can evaluate blank fields from a fast lookup. Any thoughts or suggestions would be appreciated. Thanks!

    • I have the same issue and question as Neil regarding empty fields causing my Flow to fail with the error “The flow failed to access the value for because it hasn’t been set or assigned.” Thanks!

      • You probably solved this already, but what I did was add a Decision Element to split out records with a NULL value. This was happening for me with NULL Annual Revenue, so I simply used the decision to take it out of the Flow Screen.

      • Thanks for sharing! 👍🏻

      • You probably found a way around this, but you can add a decision element to the Flow. I was getting this error with the AnnualRevenue so I added a decision and 2 different screens, one which would display the AnnualRevenue and one without it. This avoided the error.

      • You probably found a way around this, but you can add a decision element to the Flow. I was getting this error with the AnnualRevenue so I added a decision and 2 different screens, one which would display the AnnualRevenue and one without it. This avoided the error.

    • Hi, how are you setting new text field before Fast update. Are you Looping to set New text field?

  11. Hi I am getting the below error when i am saving the above code
    Error: Flow “SelectedAccounts” is not found or doesn’t have an active version. Can you please provide the solution.

  12. Hi again. Just wanted to leave this additional tidbit of information about setting the finish location. I’ve only just figured this out and it seems to work for me although I haven’t tested it thoroughly. With the example in the post setting the finish location to this

    finishLocation=”{!URLFOR($Action.Account.Tab, $ObjectType.Account)}”>

    takes the user back to the tab but NOT into the list view which is a bit confusing of an experience. However if I do this instead it takes me to the list view:

    finishLocation=”/{!$ObjectType.Account}”>

    Perhaps someone else will have some additional insight or thoughts on this?

    • Thanks Neil, good insight

      • Andrew. Thank you! This helped me deliver a huge requirement in a single day when I thought it would take weeks (as I have no programming skills yet). Neil, your insight helped big time too. Now the users can pin their list and see their records update without having to click several times just to get back to where they started.

      • Fantastic!

    • HI,

      Here’s what I did. I wanted to land back on the parent case record that has the related list view.

      {!row.id}
      {!row.action_outcome__c}
      {!row.Proposed_Resolution__c}
      {!row.Department_Response__c}
      {!row.Warehouse_Picker_Checker_Name__c}
      {!row.Transport_Driver_Drivers_Mate_name__c}
      {!row.ParentId}

  13. Hi Andrew, I have two quick questions:

    Does below code work in the Service Cloud Console?
    finishLocation=”{!URLFOR($Action.Account.Tab, $ObjectType.Account)}”>

    Does below code work in the Service Cloud Console?
    finishLocation=”{!$CurrentPage.parameters.retURL}”>

  14. Pingback: Flow in Winter’17 Lightning Experience | Andy in the Cloud

  15. Hi Andy,

    Thanks for this post – we’ve built a whole new operational process around it, and everyone loves it! The one tweak I’d like to make is delivering an error screen when the no records have been selected from the list view (“Please return to the list view and make a selection”). Evaluating the “SelectedRows” collection variable according to the criteria “is null {!$GlobalConstant.True}” doesn’t work (http://salesforce.stackexchange.com/questions/51797/visual-workflow-how-to-evaluate-whether-an-sobject-collection-variable-isnull), presumably because when the collection is “empty” it’s not “null.” You can set the variable to null when using a Fast Lookup element to pull the collection – could you potentially edit the Visualforce page to do the same, or do you have another suggestion on how to incorporate this check within the flow?

    • Yeah best bet is to use conditional display of a apex:pageMessage element to show the message vs showing the interview flow element using the rendered attributes of each with an appropriate expression

      • Since I’m not a pro with Apex I continued experimenting with the flow yesterday and ended up adding a loop before the action to count the records selected (using this post as a starting point: https://developer.salesforce.com/forums/?id=906F0000000BNOnIAO) and conditionally display the error if total # = 0, or a confirmation screen (Do you want to [perform actions] on the [total #] records selected?) if a selection has been made. Might not be the cleanest route, but it works great and having the count on the confirmation screen is a plus!

      • Excellent! Thanks for sharing

  16. HI Andrew
    Can you kindly please package both of these? It would really help !!
    Thank you so much.

    • You mean so there is no need to edit the visual force manually? Also support different objects. Would that help?

      • HI Andrew
        Yes that would be awesome.
        I wasnt able to replicate what you achieved with the VF page. Could you kindly package them pls.

  17. Its a great posting. I am using your same approach. I am kind of Fast updating in flow. The loop only working for 20 records .. There is no update done on 21 records. I am using same logic in two different logic, both ends at 20th record without any error. Please help

  18. I’m working on a similar use case, but for some reason the {!selected} expression doesn’t seem to be limiting my records. The flow just loops over the entire set of records in the list. Any ideas where I might be going wrong?

    {!row.id}
    {!row.Answer_Status__c}

  19. Andy, thanks for posting this! It helped me a lot!!

    I wonder if you can help me with this question: when I populate the SObject Collection Variable from Visualforce, do I have to specify somewhere the field values that I want to store on the variable?

    My flow loops through the SObject Collection variable and sends an SObject (which is my Loop Variable) to a sub-flow. I’m getting an error because the flow failed to access the value for a field because it hasn’t been set or assigned.

    I temporarily solved this by including a Fast Lookup element inside the loop that populates my SObject variable with the current record on the loop, and then send it to the subflow. I don’t love this solution because lookups within a loop are not a good practice.

    Any ideas or comments on how to solve this?

    Thanks again!!

  20. Hi, Thanks for the code, it’s working great for me. My issue is some of the fields that I pass to the flow could be Null/Blank text fields. If this is the case, I encounter an error that the field hasn’t been set or assigned. I’ve tried checking for the null/blank value on the VF page, but I’m still getting the same error. I tried creating a formula field within the flow what checks if the field is blank, but again I still get the same error. Any suggestions on how I get around this?
    This is my VF page

    {!wo.WorkOrderNumber}
    {!wo.Account_Name__c}
    {!wo.Account_City_County__c}
    {!wo.Account_Postcode__c}
    {!wo.Status}
    {!wo.Subject}
    {!wo.Scheduled_Date__c}
    {!wo.Priority}
    {!wo.Priority_Order__c}
    {!IF(ISBLANK(wo.Technical_Support_Notes__c), ‘Not Set’,wo.Technical_Support_Notes__c) }

    • Yes this has been raised elsewhere in the comments I think. It is a strange challenge that it seems has no solution other than to requery within the flow itself.

  21. Andrew – I’ve implemented this and it works great, but since the flow is launched from a VF page I am not currently able to have the flow show up in Lightning Experience (it uses the Classic UI). Any workarounds to get it to look better?

    • Use the Lightning Flow Component for this instead of your VF page or tick the checkbox on the page to allow it to display in Lightning.

  22. Hi, great post, thank you. I was wondering if it’s possible to order the WorkOrders collection before it’s passed to the flow. I need it to order on a custom field. I know I could do it within the flow, but I’d have to do a FastLookUp which wouldn’t be as efficient as utilising the query already done by the VF page. This is my code

    {!wo.WorkOrderNumber}
    {!wo.Account_Name__c}
    {!wo.Account_City_County__c}
    {!wo.Account_Postcode__c}
    {!wo.Status}
    {!wo.Subject}
    {!wo.Scheduled_Date__c}
    {!wo.Priority}
    {!wo.Priority_Order__c}
    {!IF(ISBLANK(wo.Technical_Support_Notes__c), ‘Not Set’,wo.Technical_Support_Notes__c) }
    {!wo.LineItemCount}

    Many thanks

    • Sorry not as far as I know, the order maybe what is shown in the list view priority, but I don’t think it’s safe to depend on that. Ordering in your flow is best for robustness.

  23. Hi,
    What’s the most efficient way to perform a fast look up on the collection that I’m passing from the VF page, so I can control the order.
    The FastLookUp element has no ‘In’ operand like I would use in a SOQL statement. I’m hoping I wouldn’t have to loop through the collection, perform a look up on each record and then add that to a collection.
    Many thanks

  24. List controllers are not supported for Event

  25. Not sure how long this solution has existed but it fixes (tho it may be too clunky to bother, depending on your use case) the issue of fields without values throwing unhandled errors if you try to set them from the visualforce page (instead of querying within the flow itself). In the decision element, if you use “isnull” it’ll throw the error, but if you use “was set” as the operator it will not throw the error. Then you can assign it to an empty string or null value or whatever for the outcome from the decision element where “was set” = false.

  26. Thanks for the post! Unfortunately I am not a Flow expert and I tried to play along. Mostly it’s working expect it doesn’t respect which records I selected in the List View, it just grabs all the records in the List View and performs the action on all of them. Any idea what I might be doing wrong?

  27. Hi Andew – I am having difficulty with the option of passing just the records in the list view (without selecting records). In your post you say “you have two choices, do you want the user to be able to select records or not? If not, then your button will pass all the records in the List View (currently limited to 2000).” I make the changes you specify, but it passes ALL of the records for that object to the flow, not just the ones filtered in the current list view. Any explanation?

    • Nevermind – found the issue. I was having the same “passing blank values” issue as others have described in the comments. I tried to query around it via fast lookup, but it was querying all records. I ended up doing as a commentor suggested, adding in a decision element to take out the blanks. It is important to state that the decision logic for that was “some field”, operator as “was set”, and global value “false” as the value. At least for me, “some field” with operater “is null” didn’t work at all…

  28. Hi Andy

    As always, thank you for sharing your expertise. Since the article was written in 2015, is record selection still not possible with Lightning?

  29. Update to to my previous comment (some words were omitted): Out of curiosity, why is the apex:repeat element necessary on the Visualforce page to pass in record data to the flow? Can’t see the connection between that and the {!Selected} variable you are actually passing. Thanks.

  30. Thanks for the post.

    I would like to update multiple records from list view and display messages . could you suggest me how to implement using flow in lightning.

    Thanks in advance !!!

  31. Hi Andrew
    Thank you for the great post, it works like a charm.

    I have been wondering if you know how to launch the flow in a popup/modal, instead of opening a new page?

    Thanks in advance

  32. Hi Andy
    How does this solution change given the new Flow Builder? The terminology is different in the new interface (e.g. SObjectCollection variables now appear to be Record Collection) so wondering if you have any suggestions given these latest enhancements?
    For the record, what I’m trying to do with my example is update selected records but only if the status of those records is a particular value.
    Thanks!

  33. Hey Andy,

    I’d like to get your thoughts on the purely declarative list view flow solution presented in this article -> https://bigassforce.com/flow-list-buttons

    I’ve tested it myself and it works like a charm. The “ids” parameter (being implicitly passed to the flow) is not really documented in the Salesforce docs. What are your thoughts on best practice and sustainability of this solution? Have you seen any documentation that backs this up?

    Thanks!
    Justin

    • Hey – i have to agree with the comments on the post tbh – feels risky – especially things at the browser end do tend to change implementation wise more in my experience. I would stick with the VF approach personally. Andy.

  34. Getting Error: Parameter “SelectedRows” has wrong value type.
    Can you please provide solution?

Leave a comment