Automate data backup of Salesforce org

Salesforce provides a feature called "Data Export Service" through which you can generate backup files of data on a weekly or monthly basis depending on your salesforce edition. You can export all your org’s data into a set of comma-separated values (CSV) files. The sad part over here is that this feature in not supported in Sandbox yet. Developers frequently have the requirement to take the data backup of sandbox org, especially if they are working with a managed package. 

Here is a batch class which will allow you to take a backup of your entire org data and store it under Notes and Attachment under a custom Backup object. In the next blog, I will enhance this code to store the backup in Google Drive instead of storing it in a custom object in org. Here are the steps you need to take to make this work :

1) Create a custom object in your org whose API name should be Backup__c



2) Create below batch class in your org

global class DataExportBatch implements Database.Batchable<String>,Database.Stateful{
    
    global Backup__c backupObj {get;set;}
    
    global Iterable<String> start(Database.BatchableContext BC){
        backupObj = new Backup__c(Name=String.valueOf(System.today()));
        insert backupObj;
        List <String> objList = new list <String> ();
        for ( Schema.SObjectType obj : Schema.getGlobalDescribe().values()){
            Schema.DescribeSObjectResult objResult = obj.getDescribe();
            if(objResult.isUpdateable() && objResult.isQueryable() && objResult.isDeletable() && objResult.isSearchable()){
                if(objResult.getName() != 'IdeaComment'){
                    objList.add(objResult.getName());
                }         
            }
        }
        return objList;
    }
    
    
    global void execute(Database.BatchableContext BC, List<String> scope){
        
        for(String straa : scope) {
            String queryString = 'SELECT ';
            Map <String, Schema.SObjectField> mapf = Schema.getGlobalDescribe().get(straa).getDescribe().fields.getMap();
            String csvContent='Id,';
            for (String fieldName: mapf.keySet()) {
                String ketValue = (String) mapf.get(fieldName).getDescribe().getname();
                csvContent = csvContent + ketValue + ',';
                queryString = queryString + ketValue + ',';
            }
            csvContent = csvContent.subString(0,csvContent.lastIndexOf(','));
            csvContent = csvContent + '\n';
            queryString = queryString.subString(0,queryString.lastIndexOf(','));
            queryString = queryString + ' FROM ' + straa;
            List<sObject> sobjList = Database.query(queryString);
            for(sObject obj : sobjList){
                csvContent = csvContent + obj.get('Id') + ',';
                for (String fieldName: mapf.keySet()) {
                    if (mapf.get(fieldName).getDescribe().isCustom() || mapf.get(fieldName).getDescribe().isNameField()) {
                        String ketValue = (String) mapf.get(fieldName).getDescribe().getname();
                        String escapedCSVContent;
                        if(String.valueOf(obj.get(ketValue))!= null && String.valueOf(obj.get(ketValue)).contains(',')){
                            escapedCSVContent = String.valueOf(obj.get(ketValue)).escapeCsv();
                        }else{
                            escapedCSVContent = String.valueOf(obj.get(ketValue));
                        }
                        csvContent = csvContent + escapedCSVContent  + ',';
                    }
                }
                csvContent = csvContent.subString(0,csvContent.lastIndexOf(','));
                csvContent = csvContent + '\n';
            }
            csvContent = csvContent.replace('null','');
            
            // Create csv
            Blob csvBlob = Blob.valueOf(csvContent);
            Attachment attchmnt = new Attachment();
            attchmnt.Body = csvBlob;
            attchmnt.Name = straa + '-' +system.today() + '.csv' ;
            attchmnt.ParentId = backupObj.Id; 
            insert attchmnt;
        }
    }
    
    global void finish(Database.BatchableContext BC){
        // Can write a logic to send mail upon completion of backup
    }
    
}​

3) Create a schedulable class and call this batch class from execute method with a batch size of 1

global class DataExportScheduler implements Schedulable {
   global void execute(SchedulableContext sc) {
      DataExportBatch b = new DataExportBatch(); 
      Database.executebatch(b,1);
   }
}

Comments

Popular posts from this blog

Salesforce Lightning: Countdown timer

Salesforce Hacks: System.LimitException: Too many queueable jobs added to the queue: 2

Building an Org Role Hierarchy component in LWC