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
Alex KirbyAlex Kirby 

Clone records, loop through list querying all fields

public class cloneM {
    
    private final Opportunity o;    
    public CloneM (ApexPages.StandardController 
                       stdController) {
                           this.o = (Opportunity)stdController.getrecord();
                       }
    
    Public opportunity newOpp{get; set;}
    
        
    public void cloneOpp(){
        
        list<es__c> esList = [select id from es__c where opportunity_name__c =: o.id];

        
        String soql = cloneUtil.getCreatableFieldsSOQL('opportunity','id=\''+o.id+'\'');
        
        opportunity opp = (opportunity)Database.query(soql);
        opportunity newOpp = opp.clone(false, true);
        newOpp.stageName = 'Not Worked';
        insert newOpp;
        
        if(esList.size() >0){             
                        
            for(es__c es : esList){
                String soql2 = cloneUtil.getCreatableFieldsSOQL('es__c','id=\''+ es.id + '\'');
                es__c oldEs = (es_mpan__c)Database.query(soql2);
                es__c newEs = oldEs.clone(false,false);
                insert newEs;
            }	
        }
    }
}

Here is my class, I am trying to create a custom button to clone a parent record and all child records associated to it. The issue is I hit a govenor limit on the when looping through the esList as I am querying all the fields for each record. I knew this would happen but I am sruggling to solve the issue around looping through a list to retrieve all fields for each record prior to insert?
 
if(esList.size() >0){             
                        
            for(es__c es : esList){
                String soql2 = cloneUtil.getCreatableFieldsSOQL('es__c','id=\''+ es.id + '\'');
                es__c oldEs = (es__c)Database.query(soql2);
                es__c newEs = oldEs.clone(false,false);
                insert newEs;
            }	
        }

This is my issue, I am calling a utility to dynamically pull all field information for each record:

Having this is the loop is the offending line..
es__c oldEs = (es__c)Database.query(soql2);
Does anyone have any ideas on how I can resolve this without having everyfield in the class? 

Thanks in advance.
 
Alex KirbyAlex Kirby
Here is my work so far:
 
public class cloneMpans {
    
    private final Opportunity o;    
    public CloneMpans (ApexPages.StandardController 
                       stdController) {
                           this.o = (Opportunity)stdController.getrecord();
                       }
    
    Public opportunity newOpp{get; set;}
    
    public void cloneOpp(){
        
        String soql = cloneUtil.getCreatableFieldsSOQL('opportunity','id=\''+o.id+'\'');
        
        opportunity opp = (opportunity)Database.query(soql);
        opportunity newOpp = opp.clone(false, true);
        newOpp.stageName = 'Not Worked';
        insert newOpp;
        
        // Get a map of field name and field token
        Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get('es_mpan__c').getDescribe().Fields.getMap();
        list<string> selectFields = new list<string>();
        
        if (fMap != null){
            for (Schema.SObjectField ft : fMap.values()){ // loop through all field tokens (ft)
                
                Schema.DescribeFieldResult fd = ft.getDescribe(); // describe each field (fd)
                if (fd.isCreateable()){ // field is creatable
                    
                    selectFields.add(fd.getName()); 
                }
            }
        }
        
        String selects = '';
        
        if (!selectFields.isEmpty()){
            for (string s:selectFields){
                selects += s + ',';
            }
            
            if (selects.endsWith(',')){selects = selects.substring(0,selects.lastIndexOf(','));}         
            
        }
        
        string queryString = 'select ' + selects + ' from es_mpan__c where opportunity_name__c =\''+ o.id +'\'';
        
        list<es_mpan__c> esList = new list <es_mpan__c>();
        List<es_mpan__c> esMpans = database.query(queryString);
        
        for(es_mpan__c es : esMpans)
        {
            Es_Mpan__c esCopy = es.clone(false,true);
            esCopy.Opportunity_Name__c = newOpp.id;
            esList.add(esCopy);
        }
        insert esList;
    }
}

This now creates new child records on the new parent but it is not populating the field data / cloning the information.. The opportunity name is set as per my code but it is not copying any of the other data.

I thik I am close, if anyone can point me in the right direction it would be appreciated.
Helena Alwyn 1Helena Alwyn 1
Hi Alex,
Do we need include all the fields in the record in SOQL select query to clone a records. We have more than 5 record type in an object and 600 fields per object. 
Alex KirbyAlex Kirby
Hi,

It's been a while, the above is set up to get all the fields from the object that are writeable. I guess you could add only selected fields from the parent to be copied providing that any mandatory fields are included.

string queryString = 'select ' + selects + ' from es_mpan__c where opportunity_name__c =\''+ o.id +'\'';

selects being a string of writeable field names predetermined by the method.

string queryString = 'select field1__c, field2__c, field3__c from es_mpan__c where opportunity_name__c =\''+ o.id +'\'';

If used this resource: http://sfdc.arrowpointe.com/2011/03/28/cloning-records-in-apex/ back in 2016.

The above would just copy the fields required.

Hope this helps.

Alex