A blog about Salesforce CRM Configuration and development

Saturday, 13 October 2018

Upload multiple files through Visualforce page

Upload Multiple files with the progress bar.



While uploading the multiple files at the same time you may have faced the problem like 'View state size limit exceeded', 'Heap size' limit and file size limit. To overcome these limits we can use javascript to handle the file uploading through the Visualforce page.


I have also faced the problem like View state size limit exceeded and Heap size limit, to solve the issue I decided to send/upload the files using HTTP POST Request with the help of Ajax, Jquery, javascript. Below is the code snippet for uploading files in the ContentVersion object.

 <apex:page>  
   <html>  
     <head>  
       <apex:slds />  
       <apex:includeScript value="https://code.jquery.com/jquery-2.2.4.js"/>  
       <script>  
       //function starts  
       $(function(){  
         var fileLenght=0;  
         $('#uploadBtn').click(function() {  
           var v=document.getElementById('addr');  
           console.log(v.files.length);  
           fileLenght = v.files.length;  
           for (var i = 0; i < v.files.length; i++) {  
             uploadSelectedFile(v.files[i], function(err, res){   
               FileUploading += 1;  
               if (FileUploading === FileUploaded){  
                 alert('upload completed');  
                 //blank input file value   
                 document.getElementById("addr").value = "";  
               }  
             })  
           }   
         });  
         var FileUploading = 0;  
         var FileUploaded = 0;  
         var ids = new Array();  
         var uploadSelectedFile = function(file, callback) {  
           filetoBase64(file, function(err, content){  
             var conVer_object = {  
               ContentLocation : 'S',  
               VersionData : content,   
               PathOnClient : file.name,   
               Title : file.name   
             };  
             $.ajax({  
               url: '/services/data/v39.0/sobjects/ContentVersion',  
               data: JSON.stringify(conVer_object ),  
               type: 'POST',  
               processData: false,  
               contentType: false,  
               headers: {'Authorization': 'Bearer {!$Api.Session_ID}', 'Content-Type': 'application/json'},  
               xhr: function(){  
                 var xhr = new window.XMLHttpRequest();  
                 //Upload progress  
                 xhr.upload.addEventListener("progress", function(evt){  
                   if (evt.lengthComputable) {  
                     $('#progress_bar_container').css('display', 'block');  
                     var percentComplete = evt.loaded / evt.total;  
                     console.log('percentComplete '+percentComplete );  
                     var percentCompletex= percentComplete*100;  
                     $('#percentText').html("Uploading. Please wait... "+Math.round(percentCompletex)+"%");  
                     $('.progress').css('width', percentCompletex+ "%");  
                     if(percentCompletex == 100){  
                       $('#progress_bar_container').css('display', 'none');  
                     }  
                   }  
                 }, false);  
                 return xhr;  
               },  
               success: function(response) {  
                 FileUploaded += 1;  
                 console.log(response.id); // the id of the attachment  
                 ids.push(response.id);   
                 console.log('Ids: ' +ids);  
                 $('#records').html('File has been uploeded. Uploaded File ids: ' +ids);  
                 if(fileLenght == FileUploaded ){   
                   //calculateLocation(ids.toString());  
                 }  
                 callback(null, true)  
               },  
             });  
           });  
         }  
         //Read file  
         var filetoBase64 = function(file, callback){  
           var reader = new FileReader();  
           reader.onload = function() {  
             var myFileContents = reader.result;  
             var base64Mark = 'base64,';  
             var dataStart = myFileContents.indexOf(base64Mark) + base64Mark.length;  
             myFileContents = myFileContents.substring(dataStart);  
             callback(null, myFileContents);  
           }  
           reader.readAsDataURL(file);  
         }  
         });  
       </script>  
       <style>  
         .slds-scope .slds-page-header{  
         border-radius: 0px;  
         box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.1);  
         }  
         .bodyPart{  
         padding:10px;  
         }  
       </style>  
     </head>  
     <body>  
       <apex:form >  
         <div class="slds" style="border:1px solid #D9D9D9;">  
           <div class="slds-page-header">  
             <span style=""> Upload Files</span>  
           </div>  
           <div id="progress_bar_container" style="display:none; padding:10px;">  
             <span id="percentText"></span>  
             <div class="slds-progress-bar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="25" role="progressbar">  
               <span class="slds-progress-bar__value progress" style=" width: 0%;">  
                 <span class="slds-assistive-text">Progress: 25%</span>  
               </span>  
             </div>  
           </div><br/>  
           <div class="bodyPart">  
             Select file: <input type="file" name="files[]" multiple="multiple" id="addr"/>  
             <input type="button" id="uploadBtn" name="Address" value="Upload" class="slds-button slds-button--brand"></input>  
         </div>  
         <div id="uploadedrec" style="padding:10px;">  
           <span id="records" style=" color:green; ">  
           </span>  
         </div>  
       </div>  
     </apex:form>  
   </body>  
 </html>  
 </apex:page>  


On 'Upload' button click this method will be called. Here '#uploadBtn' is the id of the button.
  $('#uploadBtn').click(function() { ...}  
If the user selects multiple files, Iterating over files length.
 for (var i = 0; i < v.files.length; i++) { ... }  
In every iteration uploadSelectedFile, JS function will be called.
  uploadSelectedFile(v.files[i], function(err, res){ ...}  
Reading the files and converted into the base64 format.
 filetoBase64(file, function(err, content){ }  
ContentVersion object variable with required fields.
 var conVer_object = {   
         ContentLocation : 'S',   
         VersionData : content,    // File body
         PathOnClient : file.name, // File name   
         Title : file.name    //File title
        };   
This AJAX method used to perform the asynchronous HTTP request to Salesforce.
 $.ajax({ ... }  
URL or Endpoint: HTTP POST method will post the content to the specified location (ContentVersion object).
 url: '/services/data/v39.0/sobjects/ContentVersion',  
Header: Salesforce Session_ID used for authentication.
  headers: {'Authorization': 'Bearer {!$Api.Session_ID}', 'Content-Type': 'application/json'},   
XML HttpRequest object: Send the data from page to server (Salesforce) in the background.
 var xhr = new window.XMLHttpRequest();  
The addEventListener function listen to the progress of uploading.
  xhr.upload.addEventListener("progress", function(evt){ ... }  
These lines of code will display the Progress bar on the page.
 $('#progress_bar_container').css('display', 'block');   
 var percentComplete = evt.loaded / evt.total;   
 console.log('percentComplete '+percentComplete );   
 var percentCompletex= percentComplete*100;   
 $('#percentText').html("Uploading. Please wait... "+Math.round(percentCompletex)+"%");   
 $('.progress').css('width', percentCompletex+ "%");   
 if(percentCompletex == 100){   
    $('#progress_bar_container').css('display', 'none');   
 }  

This success function will return the success message with the ids of the file that just uploaded.
  success: function(response) { ... }  
Output:





References:
XML Http Request
AJAX Method
ContentVersion

Hope this blog post will help many.
Happy coding...
Share:

Saturday, 6 October 2018

How to get Report data in Apex

Sometimes we need to get the report data in Apex to present it on custom report charts. We can get the report data with the help of 'Reports.ReportResults' and 'Reports.ReportManager' class of Apex.
ReportResults: This Apex class contains the results of running a report.
ReportManager: With the help of this Apex class we can run a report synchronously or asynchronously through Apex.
 public class ReportsData{  
   public static String getreport(string reportId){    
     // Get the Report data    
     Reports.ReportResults reportReturned =Reports.ReportManager.runReport(reportId, true);    
     system.debug('Report Data: '+JSON.serialize(reportReturned));    
     //Return Report data in JSON serialize format.    
     return JSON.serialize(reportReturned);    
   }    
 }   
This line of code runs the report of specified report id and return the result.
 Reports.ReportResults reportReturned =Reports.ReportManager.runReport(reportId, true);   
Here the runReport(Id reportId, Boolean includeDetails) method takes two parameter reportId and a boolean value True or false.
 runReport(reportId, true)  
JSON is an Apex class which contains methods for serializing Object into JSON format. JSON.serialize(reportReturned) method serialize the object into JSON format.
 JSON.serialize(reportReturned)  
Calling getreport('id') method. The result (report data) will return in JSON format.
 String result = ReportsData.getreport('reportId');  
Output: Parse the result according to needs.
 {  
  "reportMetadata": {  
   "topRows": null,  
   "standardFilters": null,  
   "standardDateFilter": {  
    "startDate": null,  
    "endDate": null,  
    "durationValue": "CUSTOM",  
    "column": "CUST_CREATED_DATE"  
   },  
   "sortBy": null,  
   "showSubtotals": true,  
   "showGrandTotal": true,  
   "scope": "organization",  
   "reportType": {  
    "type": "CustomEntity$Job_Applications__c@Job_Applications__c.Positions__c",  
    "label": "Job Applications with Positions"  
   },  
   "reportFormat": "SUMMARY",  
   "reportFilters": null,  
   "reportBooleanFilter": null,  
   "name": "Job Applications by Functional Area",  
   "id": "00O28000004naGqEAI",  
   "historicalSnapshotDates": null,  
   "hasRecordCount": true,  
   "hasDetailRows": true,  
   "groupingsDown": [  
    {  
     "sortOrder": "ASCENDING",  
     "sortAggregate": null,  
     "name": "FK_Positions__c.Functional_Area__c",  
     "dateGranularity": "NONE"  
    },  
    {  
     "sortOrder": "ASCENDING",  
     "sortAggregate": null,  
     "name": "FK_NAME",  
     "dateGranularity": "NONE"  
    }  
   ],  
   "groupingsAcross": null,  
   "division": null,  
   "developerName": "Job_Applications_by_Functional_Area",  
   "detailColumns": [  
    "CUST_NAME",  
    "Job_Applications__c.Status__c"  
   ],  
   "description": null,  
   "customSummaryFormula": null,  
   "currencyCode": null,  
   "crossFilters": null,  
   "buckets": null,  
   "aggregates": [  
    "RowCount"  
   ]  
  },  
  "reportExtendedMetadata": {  
   "groupingColumnInfo": {  
    "FK_NAME": {  
     "name": "FK_NAME",  
     "label": "Positions: Position Name",  
     "groupingLevel": 1,  
     "dataType": "STRING_DATA"  
    },  
    "FK_Positions__c.Functional_Area__c": {  
     "name": "FK_Positions__c.Functional_Area__c",  
     "label": "Positions: Functional Area",  
     "groupingLevel": 0,  
     "dataType": "PICKLIST_DATA"  
    }  
   },  
   "detailColumnInfo": {  
    "Job_Applications__c.Status__c": {  
     "name": "Job_Applications__c.Status__c",  
     "label": "Status",  
     "dataType": "PICKLIST_DATA"  
    },  
    "CUST_NAME": {  
     "name": "CUST_NAME",  
     "label": "Job Applications: Job Applications Name",  
     "dataType": "STRING_DATA"  
    }  
   },  
   "aggregateColumnInfo": {  
    "RowCount": {  
     "name": "RowCount",  
     "label": "Record Count",  
     "downGroupingContext": null,  
     "dataType": "INT_DATA",  
     "acrossGroupingContext": null  
    }  
   }  
  },  
  "hasDetailRows": true,  
  "groupingsDown": {  
   "groupings": [  
    {  
     "value": "Human Resources",  
     "label": "Human Resources",  
     "key": "0",  
     "groupings": [  
      {  
       "value": "a0K28000001Bm00EAC",  
       "label": "Sr. Benefits Specialist",  
       "key": "0_0",  
       "groupings": null  
      }  
     ]  
    },  
    {  
     "value": "Information Technology",  
     "label": "Information Technology",  
     "key": "1",  
     "groupings": [  
      {  
       "value": "a0K28000001BjefEAC",  
       "label": "Software Engineer",  
       "key": "1_0",  
       "groupings": null  
      },  
      {  
       "value": "a0K28000001Bm01EAC",  
       "label": "Sr. UI Designer",  
       "key": "1_1",  
       "groupings": null  
      }  
     ]  
    },  
    {  
     "value": "Miscellaneous",  
     "label": "Miscellaneous",  
     "key": "2",  
     "groupings": [  
      {  
       "value": "a0K28000001Bl4MEAS",  
       "label": "Benefits Specialist",  
       "key": "2_0",  
       "groupings": null  
      }  
     ]  
    }  
   ]  
  },  
  "groupingsAcross": {  
   "groupings": null  
  },  
  "factMap": {  
   "1_0!T": {  
    "key": "1_0!T",  
    "aggregates": [  
     {  
      "value": 1,  
      "label": "1"  
     }  
    ],  
    "rows": [  
     {  
      "dataCells": [  
       {  
        "value": "a0O280000003iHPEAY",  
        "label": "JA-00001"  
       },  
       {  
        "value": "New",  
        "label": "New"  
       }  
      ]  
     }  
    ]  
   },  
   "2_0!T": {  
    "key": "2_0!T",  
    "aggregates": [  
     {  
      "value": 1,  
      "label": "1"  
     }  
    ],  
    "rows": [  
     {  
      "dataCells": [  
       {  
        "value": "a0O280000003ib8EAA",  
        "label": "JA-00002"  
       },  
       {  
        "value": "Review Resume",  
        "label": "Review Resume"  
       }  
      ]  
     }  
    ]  
   },  
   "1_1!T": {  
    "key": "1_1!T",  
    "aggregates": [  
     {  
      "value": 1,  
      "label": "1"  
     }  
    ],  
    "rows": [  
     {  
      "dataCells": [  
       {  
        "value": "a0O280000019ULPEA2",  
        "label": "JA-00004"  
       },  
       {  
        "value": "Hired",  
        "label": "Hired"  
       }  
      ]  
     }  
    ]  
   },  
   "T!T": {  
    "key": "T!T",  
    "aggregates": [  
     {  
      "value": 5,  
      "label": "5"  
     }  
    ],  
    "rows": null  
   },  
   "2!T": {  
    "key": "2!T",  
    "aggregates": [  
     {  
      "value": 1,  
      "label": "1"  
     }  
    ],  
    "rows": null  
   },  
   "1!T": {  
    "key": "1!T",  
    "aggregates": [  
     {  
      "value": 2,  
      "label": "2"  
     }  
    ],  
    "rows": null  
   },  
   "0_0!T": {  
    "key": "0_0!T",  
    "aggregates": [  
     {  
      "value": 2,  
      "label": "2"  
     }  
    ],  
    "rows": [  
     {  
      "dataCells": [  
       {  
        "value": "a0O280000019USBEA2",  
        "label": "JA-00005"  
       },  
       {  
        "value": "Review Resume",  
        "label": "Review Resume"  
       }  
      ]  
     },  
     {  
      "dataCells": [  
       {  
        "value": "a0O280000003jMBEAY",  
        "label": "JA-00003"  
       },  
       {  
        "value": "Phone Screen",  
        "label": "Phone Screen"  
       }  
      ]  
     }  
    ]  
   },  
   "0!T": {  
    "key": "0!T",  
    "aggregates": [  
     {  
      "value": 2,  
      "label": "2"  
     }  
    ],  
    "rows": null  
   }  
  },  
  "allData": true  
 }  
References:
ReportManager
ReportResults
Share:

Monday, 1 October 2018

Recent Items Lightning Component

Recent Items Lightning Component:



I believe every Salesforce developer try to access the recently used items in the Salesforce org, In Lightning experience user interface we have to click on 'Setting' icon and then need to click on 'Set Up' after that we get the Set-Up home page, on this page (standard), recently used items displayed. But there is a limit only 10 items displayed on this page and also we can not filter the record based on types like if we want to display recent used Apex classes, Visualforce Pages, Triggers, Custom object, Custom fields, Users, Static resource, etc.  If someone wants to download the log of the recently used items they cannot do using standard page.

I also try to find the recently used items most of the times, I think there should be more than 10 recent items on the recent items page, and also there should be the filter to filter the records. The filter will make the user easy to find the items that they wanted to find.

With these ideas in mind, I have developed a Lightning component which will display up to 100 recently used items on the component, each page will show 10 items, for next items, there are pagination buttons on the component, To filter the record based on types there is a picklist which will have all the possible types to filter the records. There is a button called 'Download As Csv' after clicking on this button the recently used items will be downloaded in the '.CSV' format. 

This component can be used on the Home Page, Detail page, Lightning Tab. etc

To use this component you have to add your salesforce domain URL in remote site setting: e.g:- https://your_domain -dev-ed.my.salesforce.com/

You can install this Lightning component from here.

https://allrecentitem-developer-edition.na59.force.com/

Share:
Trailhead Profile


Follow by Email

Total Pageviews

Followers

Popular Posts

Powered by Blogger.

Contact form

Name

Email *

Message *