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
Nitzan MarinovNitzan Marinov 

Apex Process to Split Client Name to First and Last Name

Hi all,

I have these 3 fields:
SELECT Name, First_Name__c, Last_Name__c FROM Clients__c 

I would like to run a periodical apex process to split the values from Name into First Name and Last Name.

All charachters until 1st space is First Name and everything else is Last Name.

Can anyone please help?

Thanks
Best Answer chosen by Nitzan Marinov
srlawr uksrlawr uk
The "periodical apex process" is an interesting concept here to me, is there a reason why you wouldn't want to do this using a workflow rule or such that could just split the name out everytime a Client__c record is created, or whenever the "Name" field is changed?

You could do this using workflow on the object - using a Field Update to set the "First_Name__c" field to
 
LEFT(Name, FIND(' ',Name))

and the Last_Name__c to
 
RIGHT(Name, FIND(' ',Name))

Which is the sections of text left, and right of the first space.


If you really did want to do this using some sort of periodical apex, you would have to think carefully about how many Clients you might load? A scheduled apex job once a day that looked something like:
 
global class NameSplitScheduledClass Implements Schedulable
{
  global void execute(SchedulableContext sc)
  {
     SplitNames();
  }
                        
  public void SplitNames()
  {
     List<Clients__c> yesterdaysClients = [SELECT Id, Name FROM Clients__c WHERE createdDate = YESTERDAY];
     for(Clients__c thisClient: yesterdaysClients)
     {
         thisClient.First_Name__c = thisClient.Name.Substring(0,thisClient.Name.indexOf(' '));
         thisClient.Last_Name__c = thisClient.Name.Substring(thisClient.Name.indexOf(' '),thisClient.Name.length());
     }
     update yesterdaysClients;
  }
}

BE WARNED - there is ZERO error catching and capability in that code though (I'm not your slave!!) but it will pretty much do what you want. You just need to schedule it using "Schedule Apex" - and obviously put in test coverage (and error handling).


I would still ask immediatly why this wasn't done using work flow though, if I saw it in a client org.

All Answers

srlawr uksrlawr uk
The "periodical apex process" is an interesting concept here to me, is there a reason why you wouldn't want to do this using a workflow rule or such that could just split the name out everytime a Client__c record is created, or whenever the "Name" field is changed?

You could do this using workflow on the object - using a Field Update to set the "First_Name__c" field to
 
LEFT(Name, FIND(' ',Name))

and the Last_Name__c to
 
RIGHT(Name, FIND(' ',Name))

Which is the sections of text left, and right of the first space.


If you really did want to do this using some sort of periodical apex, you would have to think carefully about how many Clients you might load? A scheduled apex job once a day that looked something like:
 
global class NameSplitScheduledClass Implements Schedulable
{
  global void execute(SchedulableContext sc)
  {
     SplitNames();
  }
                        
  public void SplitNames()
  {
     List<Clients__c> yesterdaysClients = [SELECT Id, Name FROM Clients__c WHERE createdDate = YESTERDAY];
     for(Clients__c thisClient: yesterdaysClients)
     {
         thisClient.First_Name__c = thisClient.Name.Substring(0,thisClient.Name.indexOf(' '));
         thisClient.Last_Name__c = thisClient.Name.Substring(thisClient.Name.indexOf(' '),thisClient.Name.length());
     }
     update yesterdaysClients;
  }
}

BE WARNED - there is ZERO error catching and capability in that code though (I'm not your slave!!) but it will pretty much do what you want. You just need to schedule it using "Schedule Apex" - and obviously put in test coverage (and error handling).


I would still ask immediatly why this wasn't done using work flow though, if I saw it in a client org.
This was selected as the best answer
Nitzan MarinovNitzan Marinov
Thanks srlawr uk (nice name :-)),

I do have a Process Builder flow that catches all new and modified records. I would probably only need to run this apex process once, actually, as I want to make sure that all existing records are updated too. 

I will modify your process to only look at records where there is no value in First & Last name.

Thanks again
srlawr uksrlawr uk
Ok, cool! Good work on Process Builder, nice and modern! ;)

Should be simple enough to modify the Apex then to your needs, as you say, change the SOQL query to something like
 
SELECT Id, Name FROM Clients__c WHERE First_Name__c  = ''
the key error checking to do will be that "Name" contains a at least something, and a space..
 
If(thisClient.trim().length() > 0 && thisClient.Name.Contains(' ') != -1) {
// do stuff 
}
Otherwise you will throw a bunch of index out of bounds errors on Substring.

(and as always, do a test run in a sandbox, and back your data up before running!)

Good luck.

 
Nitzan MarinovNitzan Marinov
Of course. Thanks for your help.

Much appreciated.
David Roberts 4David Roberts 4
Thanks Guys. This thread helped me. Just a slight correction: 
thisClient.Name.Contains(' ')  is already boolean so doesn't need the "!= -1".
David Roberts 4David Roberts 4
I ended up with the following:
String fullName = thisClient.Name;
fullName = fullName.trim();
String firstName = 'unknown';
String lastName = 'unknown';
boolean hasLength = fullName.trim().length() > 0;
boolean containsSpace = fullName.Contains(' ');
If( hasLength  ) {
    If(  containsSpace ) {
        firstName = fullName.Substring(0,fullName.indexOf(' '));
        lastName = fullName.Substring(fullName.indexOf(' '),fullName.length());
        lastName = lastName.trim();
        if (lastName.length() == 0){
            lastName = 'unknown';
        }//endif
    }
    else{
        firstName = fullName;
    }//endif  
}//endif


system.debug('first='+firstName);
system.debug('last='+lastName);
//and use them...
thisClient.First_Name__c = firstName;
thisClient.Last_Name__c = lastName;