Apex Return Diff fields between records

Sometimes you want to determine what has changed between an existing record in the database and an update to the record. The diffRecord method will return all the fields that changed for a specific record.

Compare the difference between to records and return changed fields

public SObject diffRecord(SObject updatedRecord, SObject currentRecord, String sObjectName){
  SObjectType objToken = Schema.getGlobalDescribe().get(sObjectName);
  DescribeSObjectResult objDef = objToken.getDescribe();
  Map<String, SObjectField> fields = objDef.fields.getMap();
  Type classType = Type.forName(sObjectName);
  SObject diffRecord = (SObject)JSON.deserialize('{}', classType);
  for (String field : fields.keySet()){
    if (!fieldsToExclude.contains(fields.get(field).getDescribe().getName()) && (fields.get(field).getDescribe().isUpdateable() || fields.get(field).getDescribe().isCreateable())){
        if (updatedRecord.get(field)!=currentRecord.get(field))
        	diffRecord.put(field, updatedRecord.get(field));
    }
  }
  return diffRecord;
}

Test that only changed fields are returned

@isTest static void testDiffRecords(){
  String currentRecordJSON = '{"Id":"a0L63000000qc43EAA","Account_Type__c":"Managed","Amount__c":50.00,"Category__c":"Deposit","Description__c":"Deposit","End_Date__c":"2020-03-31T15:06:57.000+0000","Frequency__c":"Monthly"}';
  String updatedRecordJSON = '{"Amount__c":50.0,"Id":"a0L63000000qc43EAA","Frequency__c":"Annually"}';
  Type classType = Type.forName('Account');
  SObject currentRecord = (SObject)JSON.deserialize(currentRecordJSON, classType);
  SObject updatedRecord = (SObject)JSON.deserialize(updatedRecordJSON, classType);
  Test.startTest();
    SObject diffRecord = App_Service.instance.diffRecord(updatedRecord, currentRecord, 'Account');
    System.assertEquals(diffRecord.get('Amount__c'), null);
    System.assertEquals(diffRecord.get('Frequency__c'), 'Annually');
    System.assertEquals(diffRecord.get('Account_Type__c'), null);
    System.assertEquals(diffRecord.get('Category__c'), null);
  Test.stopTest();
}

Salesforce Export Database Records to CSV for Batch Upload

Exporting of Database records to csv can be done using:

1. OpenCSV CSVWriter
2. FileWriter

1. OpenCSV CSVWriter


	@Inject
    private Environment environment;

	@Inject @Named("proddataSource") DataSource dataSource;

	private FileWriter writer;
	
	@Override
	public ResultSet getDWRecords(String queryName) {
		try {
			java.sql.PreparedStatement ps = dataSource.getConnection().prepareStatement(environment.getProperty(queryName));
			ps.setMaxRows(10000);
			ResultSet rs = ps.executeQuery();
			return rs;
		} catch (SQLException e) {
			logger.error("CreateCSVDWDumpFileImpl.getDWRecords(): " + e.getMessage());
		}
      return null;
	}

	@Override
	public void createCSVDumpFromQuery(ResultSet resultSet, String[] salesforceColumnNames, String fileName) {
		if (resultSet!=null){
			try {
				CSVWriter writer = new CSVWriter(new FileWriter(fileName), ',', CSVWriter.NO_QUOTE_CHARACTER);
				writer.writeNext(salesforceColumnNames);
				writer.writeAll(resultSet, false);
	            writer.close();
			} catch (IOException e) {
				logger.error("CreateCSVDWDumpFileImpl.createCSVDumpFromQuery(): " + e.getMessage());
			} catch (SQLException e) {
				logger.error("CreateCSVDWDumpFileImpl.createCSVDumpFromQuery(): " + e.getMessage());
			}
		}
	}

2. FileWriter

private FileWriter writer;
public void writeToCSVFileAccount(Collection<SObject> sObjects, String[] salesforceColumnNames, String fileName) {
	try {
		writer = new FileWriter(fileName);
		for (int firstCol = 0; firstCol < salesforceColumnNames.length; firstCol++){
			 writer.append(salesforceColumnNames[firstCol]);
			 if (firstCol < salesforceColumnNames.length-1)
				 writer.append(',');
		}
		writer.append('\n');
		
		for (SObject sAccount : sObjects){
			for (int k = 0; k < salesforceColumnNames.length; k++){
				writer.append(sAccount.getField(salesforceColumnNames[k])!=null ? salesforceColumnNames[k].contains("Date") || salesforceColumnNames[k].contains("date") ?  String.format("%1$tF", sAccount.getField(salesforceColumnNames[k])) : sAccount.getField(salesforceColumnNames[k]).toString() : "");
				if (k < salesforceColumnNames.length-1)
					writer.append(',');
			}
			writer.append('\n');
		}
		
		writer.flush();
		writer.close();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		}
	}