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
Rajesh SFDCRajesh SFDC 

how to get last modified field values from case history object

here my requirments i want to get whose last modified fileds values to update to case object
using apex trigger
here my code given below:
trigger TrackigHistory on Case (before update)
{

    set<Id> setId = new set<Id>();
    string strhistory;
   
     for(Case con: trigger.new)
     {
        setId.add(con.Id);
               List<CaseHistory> ch = [Select id,CaseId, Field, NewValue, OldValue from CaseHistory where CaseId = :setId  ];
      
         system.debug('&&&&&&&CaseHistory size&&&&&&&&&&'+ch.size());
       // for(integer i=0;i<ch.size();i++)
       for(CaseHistory c: ch)
        {
          // if(ch[i].Field != NULL && ch[i].OldValue != NULL && ch[i].NewValue != NULL)
           //{
                 system.debug('&&&&&&&CaseHistory&&&&&&&&& '+'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue);
           
                 con.Track_status_history__c = 'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue;
                 how to get fields values last modified field values updat to case object
           //}
        }
     
      }

  
               
 
}
Best Answer chosen by Rajesh SFDC
Rajesh SFDCRajesh SFDC
thanks lot ELI FLORES, NOW ITS WORKING 

All Answers

Eli Flores, SFDC DevEli Flores, SFDC Dev
Can use just use track history on the case and add the related list? I think i'm missing part of the requirement. Why does this have to be a part of the field? Case History would only pick up fields that have already been set to be tracked.

Since this is a before trigger, this code would pick up the 2nd to last change since the latest change hasn't been registered. . And the whole thing breaks down if there are multiple fields update this would just pick randomly one based on how SFDC decides to log the changes. 

If the issue that you want to track all fields, you're in for a bit of a wild ride.

My off-the-cuff approach would be to use a before trigger and use a describe call. Spitballing a bit here

trigger test on Case (before update) {
Map<string, Schema.SobjectField> caseFields = Schema.SObjectType.Case.fields.getMap();

For (Case cs : Trigger.new){
    for (string fieldName : caseFields.keySet()){
        if ( cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName)) {
            cs.Track_status_history__c = 'Field ' + fieldName + ' changed from ' + string.valueOf(Trigger.oldMap.get(cs.id).get(fieldName)) + ' to '  +string.valueOf(cs.get(fieldName));
        }
    }
 
}
}

There's likely to be issue with string.valueOf() but this should get you pointed in the right direction if you are trying to do this outside of the confines of the standard history tracking mechanism.






Eli Flores, SFDC DevEli Flores, SFDC Dev
Hmm perhaps i misunderstood this a little bit. If you just needed the previous lastModifiedDate you could

Date lastMod = trigger.oldMap.get(con.id).lastModifiedDate;
Eli Flores, SFDC DevEli Flores, SFDC Dev
You have to change
if ( cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName) and fieldName != 'track_status_history__c') {

Also you may want to make track_status_history__c larger if possible to give more wiggle room

Also maybe add
string fieldUpdateText  = 'Field ' + fieldName + ' changed from ' + string.valueOf(Trigger.oldMap.get(cs.id).get(fieldName)) + ' to ' string.valueOf(cs.get(fieldName))

if (fieldUpdateText.length() >  caseFields.get('track_status_history__c').getDescribe().getLength()){
   fieldUpdateText=  fieldUpdateText.substring(0,caseFields.get('track_status_history__c').getDescribe().getLength()-1);//you should probably put the getDescribe().getLength() outside the loop since it wont change
}
Anil SavaliyaAnil Savaliya
Hi Rajesh,

Added  'order by createdDate  desc' in SOQL ,So first record will be last modified field.

Please use below code and check ?

trigger TrackigHistory on Case (before update)
{

    set<Id> setId = new set<Id>();
    string strhistory;
  
     for(Case con: trigger.new)
     {
        setId.add(con.Id);
               List<CaseHistory> ch = [Select id,CaseId, Field, NewValue, OldValue from CaseHistory where CaseId = :setId  order by createdDate  desc ];
     
         system.debug('&&&&&&&CaseHistory size&&&&&&&&&&'+ch.size());
       // for(integer i=0;i<ch.size();i++)
       for(CaseHistory c: ch)
        {
          // if(ch[i].Field != NULL && ch[i].OldValue != NULL && ch[i].NewValue != NULL)
           //{
                 system.debug('&&&&&&&CaseHistory&&&&&&&&& '+'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue);
          
                 con.Track_status_history__c = 'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue;
                 how to get fields values last modified field values updat to case object
           //}
        }
    
      }

 
              

}
Rajesh SFDCRajesh SFDC
Eli Flores, SFDC Dev

hi Eli Flores, i am tried ur apex code. its fetch ing the all last modified field values,, i dont want that one,, i want to fetch only last modified field values,, 
eg, 1. status=new  2. case reason = installtion, 3. case origin= phone, whose modified last field values want to display , suppose case origin field ,, previous phone values, suppose i am changed  for phone to web,, display old values nd new values,, but in ur code,, fetching all modified field values .. only i fetch last field values display it,, 
Rajesh SFDCRajesh SFDC
trigger test on Case (before update )
{
Map<string, Schema.SobjectField> caseFields = Schema.SObjectType.Case.fields.getMap();


For (Case cs : Trigger.new)
{
    for (string fieldName : caseFields.keySet())
   
    {
        system.debug('$$$$$$fieldname$$$44'+fieldName);
        if ( cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName))
        {
            datetime cc= system.now();
           if(trigger.oldMap.get(cs.id).lastModifiedDate == cc)
           {
            cs.Track_status_history__c = 'Field ' + fieldName + ' changed from ' + string.valueOf(Trigger.oldMap.get(cs.id).get(fieldName)) + ' to '  +string.valueOf(cs.get(fieldName));
===== here only fetch a last modified field values how to solve,, ===================>
            system.debug('$$$$$$$$$$$$$$$$'+cs.Track_status_history__c); 
            }
        }
    }

}
}
Eli Flores, SFDC DevEli Flores, SFDC Dev
Are you saying you just need any field update but only one? if so just put a break in the loop

if ( cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName))
        {
        ....
        //we've found one changed value, let's exit the loop
        break;


Though as a side note, it's hard for me to see the above code working. It would take a bit of luck to get this check to work
datetime cc= system.now();
           if(trigger.oldMap.get(cs.id).lastModifiedDate == cc)

oldMap has the all the original values of the object (i.e the values prior to the current edit) and new has all updated value (the original field values + any that were updated in the last edit). The only way this would work if is the object was edited twice within a millisecond. I.e. the original (edit before the current edit) lastModified Date is now. So the last time it was edited prior to the current edit would have to be now. 

I think I see where you might be going though. Is it you only want to capture the change to certain fields like origin, status, reason?
if so , it could be done with a couple simple edits:

set<string> trackedFields = new set<string>{'fieldApiName1', 'fieldApiName2', 'fieldApiName3'};//get these from the object page.
...
if ( trackedFields.contains(fieldName) && cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName))//add this condition to the if statement
        {
        ...

Rajesh SFDCRajesh SFDC
thanks lot ELI FLORES, NOW ITS WORKING 
This was selected as the best answer
Rajesh SFDCRajesh SFDC
how to write test class for this trigger ?
trigger test on Case (before update )
{
  Map<string, Schema.SobjectField> caseFields = Schema.SObjectType.Case.fields.getMap();

  case caseold=trigger.old[0];
  For (Case cs : Trigger.new)
  {
    for (string fieldName : caseFields.keySet())
     {
       
        if ( cs.get(fieldName) != Trigger.oldMap.get(cs.id).get(fieldName))
        {
           // cs.Track_status_history__c = 'Field ' + fieldName + ' changed from ' + string.valueOf(Trigger.oldMap.get(cs.id).get(fieldName)) + ' to '  +string.valueOf(cs.get(fieldName));
             string oldvalue = string.valueOf(caseold.get(fieldName));
            
             string newvalue= string.valueOf(cs.get(fieldName));
           
             cs.Track_status_history__c = 'Changed '+fieldName +' From '+oldvalue +' to '+ newvalue;
         
             break;
          }   
       }
  }
}