Salesforce bulk approval process

Achieving bulk approval of records in Salesforce

Mukul Mahawariya
4 min readOct 18, 2020


In your career either as a Salesforce administrator or Salesforce developer, you will encounter a terminology called Approval Process. In which, a record will be processed according to the steps defined in the Approval Process.

Approval Process -

An approval process automates how records are approved/rejected in Salesforce. An approval process consists of steps required for record approval/rejection, including from whom to request approval and what to do at each point of the process.

Why bulk approval?

Using the approval process you can only submit one record at a time for approval which is good for a less number of records, but what if there are hundreds or thousands of records that need to be submitted to the approval process that will consume a lot of time and human effort.

To save this we need a bulk approval process that can be achieved by custom logic.

So, I am going to explain how you can achieve bulk approval from a list view using the VisualForce page and an Apex Controller.

  1. Create an approval process on whatever object you like and activate it. I am going to use the opportunity object with a custom picklist Approval Status to show status.
  2. Create a Visualforce Page and an Apex Controller with the following details -

a. Visualforce Page

<apex:page standardController="Opportunity" recordSetVar="Opportunity" extensions="BulkApprovalController" lightningStylesheets="true"><apex:slds /><html xmlns=""  xmlns:xlink="">  <div class="slds-scope">    <div class="demo-only slds-hide" id="spinner"   style="height:6rem">      <div class="slds-spinner_container">         <div role="status" class="slds-spinner slds-spinner_medium slds-spinner_brand">            <span class="slds-assistive-text">Loading</span>              <div class="slds-spinner__dot-a"></div>                <div class="slds-spinner__dot-b"></div>         </div>      </div>     </div>    </div>    <apex:form >      <apex:actionFunction action="{!redirectToListView}"   name="redirection">      </apex:actionFunction>    </apex:form></html><script type="text/javascript">let selectedOpportunitiesIdJSON = '{!selectedOpportunitiesIdJSON}';let div = document.getElementById('spinner');BulkProcess();function BulkProcess(){ if (selectedOpportunitiesIdJSON !== '') {   div.classList.remove('slds-hide');   submittingRecords(); }}async function submittingRecords() { try {    let promise = await submitForApproval();   if (!div.classList.contains('slds-hide')) {      div.classList.add('slds-hide');   }redirectToListView();} catch (exception) {   if (!div.classList.contains('slds-hide')) {     div.classList.add('slds-hide');   }   redirectToListView();  }}function redirectToListView() {  redirection();}// submitting records using visualforce remotingfunction submitForApproval() {    return new Promise(function (resolve, reject)  {Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.BulkApprovalController.submitForApproval}', selectedOpportunitiesIdJSON, function (response, event) {    if (response == 'success') {      resolve(response);    }    else {       reject(response);    }   });  });}</script></apex:page>

StandardSetController — StandardSetController objects allow you to create list controllers similar to, or as extensions of, the pre-built Visualforce list controllers provided by Salesforce.

recordSetVar — The recordSetVar attribute indicates that the page is using a listview controller and it indicates the name of record collection to perform an action or show records on the page.

a. Create an Apex Controller like below -

global with sharing class   BulkApprovalController { public List<Id> selectedOpportunitiesId; public String selectedOpportunitiesIdJSON{get;set;} public BulkApprovalController(Apexpages.StandardSetController  standardController){ selectedOpportunitiesId   = new List<Id>(); for(Opportunity oppty:    (List<Opportunity>)standardController.getSelected()){  selectedOpportunitiesId.add(oppty.Id);  // you   will get only Ids from controller. } if(selectedOpportunitiesId.size()>0){   selectedOpportunitiesIdJSON =    JSON.serialize(selectedOpportunitiesId); }}@RemoteActionglobal static String submitForApproval(String   selectedOpportunities){  try{    List<String> selectedOpptys   = (List<String>)JSON.deserialize(selectedOpportunities,  List<String>.class);    List<Approval.ProcessSubmitRequest>   approvalRequests = new   List<Approval.ProcessSubmitRequest>();    //Creating an approval requests for each Opportunity using  ProcessSubmitRequest    Approval.ProcessSubmitRequest approvalRequest;    for(Id opptyId: selectedOpptys){      approvalRequest   = new Approval.ProcessSubmitRequest();      approvalRequest.setComments('Submitting   request for approval');      approvalRequest.setObjectId(opptyId);// which record to approve//change approver id       approvalRequest.setNextApproverIds(new   Id[]      {UserInfo.getUserId()});       approvalRequests.add(approvalRequest);   }// Submit the approval request    Approval.ProcessResult[] result   =    Approval.process(approvalRequests);   return 'success';  }catch(Exception ex){     return 'error '+ex.getMessage();  }}public Pagereference redirectToListView(){    Schema.DescribeSObjectResult destination;    PageReference pageRef;    try{      destination = Opportunity.SObjectType.getDescribe();      pageRef = new PageReference('/' + destination.getKeyPrefix()     );      pageRef.setRedirect(true);      return pageRef;    }catch(Exception ex){      return pageRef;    }  }}

3. Create a detail list button named — Bulk request on Opportunity and add it to the List view by navigating to Search Layout -

Select the record(s) and click on the Bulk request button.

Record(s) will be submitted for approval -

Conclusion -

❖ Submitting a large number of records for approval is a cumbersome task and Salesforce does not have standard functionality to achieve that therefore we need a workaround to achieve it.

❖ Now we have seen how we can submit records in bulk for approval using apex, what you just need is a record id.

❖ Keep in mind about comments.

In the next blog, I have explained how we can approve and reject records in bulk.

Here is the link to the blog — “Achieving bulk approval of records”.



Mukul Mahawariya

4x Salesforce Certified | Trailhead Ranger | Salesforce Enthusiast