function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
highgoshhighgosh 

Dynamically copy field values from one custom object to another

We have two custom objects, both of which have the exact same custom fields in them; however, admins will be able to make additional custom fields within these objects, so we won't know the names of the fields themselves in advance.  So, we describe the origination object, grab all the fields, and do a query to find the records we want to create and add them to a List.

 

That works just fine.  Now, however, we want to insert these found records into the destination object.  For now, we can make the assumption that through business rules, the admin knows that both the origination object and the destination object must have the same field names with the same field types...essentially, identical fields.

 

How can I take the results in my origination object query and insert them into the destination object?

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox
trigger DupeData on CO1__c( after insert, after update ) {
  Set<String> fields = CO1__c.getDescribe().fields.getMap().keySet();
  Map<Id,CO2__c> co2 = new Map<Id,CO2__c>();
  for(CO1__c record: Trigger.new) {
    co2.put(record.co2__c,new co2__c(id=record.co2__c));
    for(String field:fields) {
      if(field.indexOf('__c')>-1) { // This is a custom field.
        try {
          co2.get(record.co2__c).put(field,record.get(field));
        } catch(exception e) { /* NOTE: This just means copy failed. */ }
      }
    }
  }
  update co2.values();
}

This is an approximate means of copying the data. You could also provide a blacklist instead of just checking for a custom field. Field names are for example purposes only, but the mechanism is sound. You could also use a query if you may have more than one child per parent; a similar flow would result, but you could simply use a list instead of a map, since the query would return each related record exactly once.

 

Edit: The "copy failed" just applies to the single field that was being attempted. Either the destination field did not exist, had an incompatiable data type, or was read-only (e.g. a formula field). The records themselves would still be copied, minus the fields that failed to copy.

All Answers

sfdcfoxsfdcfox
trigger DupeData on CO1__c( after insert, after update ) {
  Set<String> fields = CO1__c.getDescribe().fields.getMap().keySet();
  Map<Id,CO2__c> co2 = new Map<Id,CO2__c>();
  for(CO1__c record: Trigger.new) {
    co2.put(record.co2__c,new co2__c(id=record.co2__c));
    for(String field:fields) {
      if(field.indexOf('__c')>-1) { // This is a custom field.
        try {
          co2.get(record.co2__c).put(field,record.get(field));
        } catch(exception e) { /* NOTE: This just means copy failed. */ }
      }
    }
  }
  update co2.values();
}

This is an approximate means of copying the data. You could also provide a blacklist instead of just checking for a custom field. Field names are for example purposes only, but the mechanism is sound. You could also use a query if you may have more than one child per parent; a similar flow would result, but you could simply use a list instead of a map, since the query would return each related record exactly once.

 

Edit: The "copy failed" just applies to the single field that was being attempted. Either the destination field did not exist, had an incompatiable data type, or was read-only (e.g. a formula field). The records themselves would still be copied, minus the fields that failed to copy.

This was selected as the best answer
highgoshhighgosh

This looks very interesting, thanks for sharing so quickly!  I'm working my way through this right now, and just received the following error (note, I've replaced "CO1" with my origination object):

"Method does not exist or incorrect signature: CO1__c.getDescribe()"

 

Any thoughts as to why I might be getting this error?

highgoshhighgosh

Alright, I think I noticed the issue.  I needed to change this:

Set<String> fields = CO1__c.getDescribe().fields.getMap().keySet();

 

...to this...

 

Set<String> fields = CO1__c.getSobjectType().getDescribe().fields.getMap().keySet();

 

That got rid of that error.  Now, however, I get the following error on line 5:

 

co2.put(record.co2__c,new co2__c(id=record.co2__c));

 

Error:  "Invalid field co2__c for SObject co1__c"

 

I believe the issue here is that I'm actually running this trigger on the Lead object, not on the CO1__c object.  I'm trying to figure out how I can account for this, since your example trigger depends on this being fired from the CO1__c object.

sfdcfoxsfdcfox

You're right on the first count; I don't normally use it in my code because I use a special cache library I wrote to minimize database calls. As for the second question, you need to replace CO1__c, CO2__c with the appropriate names, where every instance of CO1__c should be replaced with "Lead" (if I read your post right), and replace record.co2__c with the correct lead field for the custom object, and all other instances of CO2__c with the appropriate custom object name.

idanidan

Do you have an idea on how to do it on a reference field  ? 

for example :

co2.get(record.co2__c).put(field,record.get('Owner.My_Field__c'));

TX.

sfdcfoxsfdcfox
co2.get(record.co2__c).put(field,record.getSObject('Owner').get('My_Field__c'));

Using getSObject returns a dynamic SObject. You can follow as many relationships as has been queried.