+ Start a Discussion
ismyhcismyhc 

Is there a way to accomplish something similar to reflection?

Ive searched around to find that reflection isnt avaible in Apex. Now Im pretty sure thats what I need to accomplish what I am going ask, but if there is another way to accomplish this, any help would be appreciated!

 

My app creates two custom fields on opportunity.

 

campaign_start_date__c

campaign_end_date__c

 

If in the case that a customer that installs my app already has two custom date fields on opportunity I would like them to be able to specify using thier custom fields.

 

Ive setup a custom setting that allows them to input the name of the custom fields.

 

I would like to pull from that custom setting and use their custom fields. So.... something like this...

 

 // Get customer Campaign start date and end date field names from Custom Setting x_conf__c 
 x_conf__c getConf = x_conf__c.getInstance('settings'); 
            
 // Get start date field name
 string campStartDateFieldName = string.valueOf(getConf.campaign_start_date_field_name__c);
 string csd = campStartDateFieldName;


// Get start date field name
 string campEndDateFieldName = string.valueOf(getConf.campaign_start_date_field_name__c);
 string esd = campEndDateFieldName;

string xCampaignStartDate = o.+csd;
string xCampaignStartDate = o.+esd;

 

Now I realize this doesnt work... But is there a way to accomplish what I am trying to do here?

 

Thanks!

Best Answer chosen by Admin (Salesforce Developers) 
zachelrathzachelrath

Yeah, the SObject.get(fieldName) method returns whatever type of Object that the specified field is defined as. So if Campaign_Start_Date__c is defined as a Date field, then opp.get(fieldName) returns an Apex date object. For your use case, this is super helpful, because you already are assuming that the field the User is specifying will be a Date field. If you're just trying to feed the Date into a web callout as a string, you might still want to retrieve the Date object, and then use Date.format() to convert it into the exact format you want, without having to do a bunch of cumbersome String parsing.

All Answers

zachelrathzachelrath

Absolutely. There are 2 things to understand in order to make this work: Dynamic SOQL, Dynamic DML. If you want to get fancy and actually do some validation that the field API names / field labels that the user is entering in your Custom Setting actually correspond to REAL fields on the Opportunity object (which you should do :), then you'll also need to do some Schema parsing. I'll show how to do what you're looking for with Dynamic SOQL and DML the quick and dirty way.

 

You probably want to have 2 text fields on your Custom Setting, one each to hold the API Names of the fields that your customer would like to use, e.g.

 

Campaign_Start_Date_Field__c (contains the API name of the field to use as Campaign Start Date)

Campaign_End_Date_Field__c (contains the API name of the field to use as Campaign End Date)

 

// The Id of the Opportunity that we care about
Id oppId = '23749273492374';

 // Get customer Campaign start date and end date field names from Custom Setting x_conf__c
 x_conf__c cs = x_conf__c.getInstance('settings'); 

// Retrieve the Start and End Date fields 
// that the User would like to use 
// as Campaign Start Date and Campaign End Date
String startDateFieldName = cs.Campaign_Start_Date_Field__c;
String endDateFieldName = cs.Campaign_End_Date_Field__c;

// We'll just assume that whatever the User enters in these fields
// corresponds to the actual API names / local names
// of fields on the Opportunity object.
          
// Build a SOQL query to retrieve the requested fields 
// from the selected Opportunity record
String soql = 'SELECT Id,Name,AccountId,ContactId,' 
   + String.escapeSingleQuotes(startDateFieldName) + ','
   + String.escapeSingleQuotes(endDateFieldName)
   + ' FROM Opportunity WHERE Id = \'' 
   + String.escapeSingleQuotes(oppId) + '\' LIMIT 1';
  
// Retrieve the specified fields from the database
Opportunity opp;

try {
    opp = Database.query(soql);
} catch (QueryException ex) {
   System.debug('Either the specified fields do not exist, '
      + 'or the specified Id does not exist.');
}

// If we successfully retrieved our Opportunity record,
// let's grab our fields!
if (opp != null) {

   Date campaignStartDate = opp.get(startDateFieldName);
   Date campaignEndDate = opp.get(endDateFieldName);

   // Do something with our dates,
   // e.g. add 10 days to each of them,
   // then update our record!
   opp.put(startDateFieldName,campaignStartDate.addDays(10));
   opp.put(endDateFieldName,campaignEndDate.addDays(10));

   update opp;
}

 

 Hope that helps!

ismyhcismyhc

Thanks for your response. Ive been able to get it to work in the following code. Your method is probably much better, but I wanted to post what I have for input.

 

Im plucking out the date using indexOf, substring and length. My date doesnt need to be a Date type. I am using the string date to feed into a web callout.

 

Is doing it this way really bad? Im still thinking your way is much cleaner, but Im just wondering if I'm for crazy comming up with the solution in the way that I did?

 

Also.

 

From looking at your code. I assume the     opp.get(campstartdatefieldname); returns just the date value ?  If this is the case, this is def better than parsing through the string and getting it that way... I could just get the date value and convert it to a string.

 

Thanks for you input!!, Ill be trying your method in the moring.

 

 

// Get x customer Campaign start date and end date field names from Custom Setting x_conf__c 
x_conf__c getConf = x_conf__c.getInstance('settings'); 
            
// Get start date field name
string campStartDateFieldName = string.valueOf(getConf.campaign_start_date_field_name__c);
            
// Query     
string cSDate = string.valueOf(Database.query('Select opportunity.'+campStartDateFieldName+' from opportunity where Id = :opps'));
						
// Get index of where the date starts
Integer campSDateIndex = cSDate.indexOf('=', 1) + 1; // Pull out the date using the index value string campStartDate = cSDate.substring(campSDateIndex, campSDateIndex + 10); // Get end date field name string campEndDateFieldName = string.valueOf(getConf.campaign_end_date_field_name__c); // Query string cEDate = string.valueOf(Database.query('Select opportunity.'+campEndDateFieldName+' from opportunity where Id = :opps')); // Get index of where the date starts
Integer campEDateIndex = cEDate.indexOf('=', 1) + 1; // Check length to see if there is an enddate Integer campEDateLength = cEDate.length(); // Pull out the date using the index value string campEndDate = cEDate.substring(campEDateIndex, campEDateIndex + 10); String xCampaignEndDate;
If the length is less than 38 there was no input dat if (campEDateLength < 38) { xCampaignEndDate = ''; } else { xCampaignEndDate = campEndDate; }

 

zachelrathzachelrath

Yeah, the SObject.get(fieldName) method returns whatever type of Object that the specified field is defined as. So if Campaign_Start_Date__c is defined as a Date field, then opp.get(fieldName) returns an Apex date object. For your use case, this is super helpful, because you already are assuming that the field the User is specifying will be a Date field. If you're just trying to feed the Date into a web callout as a string, you might still want to retrieve the Date object, and then use Date.format() to convert it into the exact format you want, without having to do a bunch of cumbersome String parsing.

This was selected as the best answer
ismyhcismyhc

Awesome. Thats much better than parsing through the strings like I as before. I really appreciate your help. I was going in the right direction, just needed a bit of guidance! ;)