2

I have below trigger. After forming Name field I need to search ' mc' / ' Mc' / ' MC' and make immidiate next letter capital. Also convert the character after space/hyphen/apostrophe to uppercase. Can someone help me here?

trigger:

trigger ACCOUNT_AFTER_INSUPD_NAME on Account (before insert , before update) {

/*List<Account> acc = new List<Account>();
    acc = [SELECT Id,FirstName,LastName,Middle_vod__c FROM Account WHERE Id IN: Trigger.oldMap.keySet() LIMIT 1];*/
for(Account a: trigger.new)
{

  if(a.Ispersonaccount==true)
  {

    String f = a.FirstName;
    List<String> FName= f.split(' ');
   for(Integer i=0;i<FName.size();i++)
   {
    FName[i] = (FName[i].substring(0,1)).toUppercase() +(FName[i].substring(1,FName[i].length()).toLowercase());
    if(i>0)
     {
     a.FirstName=a.FirstName+' '+FName[i];
     }
     else a.FirstName=FName[i];
   }

    String m = a.Middle_vod__c;
    if(m != null){
    List<String> MName= m.split(' ');
    for(Integer i=0;i<MName.size();i++)
    {
        MName[i] = (MName[i].substring(0,1)).toUppercase() +(MName[i].substring(1,MName[i].length()).toLowercase());
       if(i>0)
     {
     a.Middle_vod__c=a.Middle_vod__c+' '+MName[i];
     }
     else a.Middle_vod__c=MName[i];

    }
                 }
  String l = a.LastName;
  List<String> LName= l.split(' ');
  for(Integer i=0;i<LName.size();i++)
  {
    LName[i] = (LName[i].substring(0,1)).toUppercase() +(LName[i].substring(1,LName[i].length()).toLowercase());
    if(i>0)
     {
     a.LastName=a.LastName+' '+LName[i];
     }
     else a.LastName=LName[i];
  }

  a.Name=a.FirstName+a.Middle_vod__c+a.lastname;

  String N = a.Name;
  List<String> FindName= N.split(' Mc');


  //update a;
   }

   // For Business Accounts
   else { String business = a.Name;
     List<String> BName= business.split(' ');
     for(Integer i=0;i<BName.size();i++)
     {
    BName[i] = (BName[i].substring(0,1)).toUppercase() +(BName[i].substring(1,BName[i].length()).toLowercase());
    if(i>0)
     {
     a.Name=a.Name+' '+BName[i];
     }
     else a.Name=BName[i];
     } 
        }    
 }
}
2
  • 1
    The way to do this is using pattern matcher code and regex. If someone doesn't post an answer, I'll try to look up some code and post an example myself. There should be some example code in the Apex Code Dev Guide which I'll admit was confusing to me the first time I learned to use it, but that could have been a learning curve thing.
    – crmprogdev
    Dec 13, 2014 at 14:11
  • Thanks crmprogdev! I am going through some pattern and .match classes but unable to understand. I will wait for your changes to my code. Thanks in advance! Dec 13, 2014 at 14:20

2 Answers 2

3

Not a direct answer, but where you have detailed logic to implement it pays to move that logic to a separate class so you can also easily build test cases for it. (You then call the class from the trigger.) This also follows the idea of writing code at a single level of abstraction.

So here I would create this class:

public class Names {
    public static String account(String first, String middle, String last) {
        ...
    }
}

and a test for it with a couple of basic cases to start with:

@isTest
private class NamesTest {
    @isTest
    static void account() {
        System.assertEquals('James Mc Govern', Names.account('james', null, 'mc govern'));
        ... many, many more cases go here
    }
}

and then keep adding test cases such as null values and various capitalisations and things like "mc" appearing in the middle of a name.

2
1

Here's a snippet of some very old in-process code I was writing for time pattern matching where the time was entered as text and needed to be assembled to create an event's start date time. You'll notice that it has a lot of error capture code in it to trap different conditions and report data that couldn't be processed by the trigger.

Edit 2 You'll want to go to somerplace like http://gskinner.com/RegExr/ to sort out the regular expression that you're going to need to use for your pattern. I'd expect you to need something along the lines of ('((MC)|(mc)|(Mc)|(mC))|((MC)|(mc)|(Mc)|(mC))\s|((MC)|(mc)|(Mc)|(mC))\\-|((MC)|(mc)|(Mc)|(mC))\')') for your pattern. This pattern will capture an "MC" in any combination of cases either by itself or followed by either a space, hyphen or apostrophe. Notice that the hyphen has been escaped, thus the reason for the double backslashes instead of a single one Reference docs show its needed, but unclear from testing at Gskinner. See saved example at http://regexr.com/3a33j. Other corrections have been made since I Initially posted it as well (several missing | inserted between (mc) instances and an extra ') at the end - possible causes of error messages you were receiving.

Note1: you can't use the global flags shown at GSkinner's site with SF's regex pattern matcher class.

Note2: You could also break the above into separate Pattern matcher classes, running them in sequence until one is found, then insert the appropriate substitution.

Once a match is found, you'd then also be able to do your capitalization of the letter that follows. There are numerous ways of approaching this depending on what you're most comfortable working with and your particular situation. Standard string methods toUpper, etc can also be used to do your conversions once you've done your captures. This should suffice to illustrate how this works with regex. See GSkinner's site at the link above for more on regex's look-forward's and look-back capabilities along with the apex docs.

Example code for assembling & formatting a Date-Time from a text entered time string and Date:

string notes;
string strtDt;    
string strtTm;
string strtTmM;
string endTm;
string endDtTm;
string strtTmB;  
string StrtTmDt;
string sClsDay; 
string sClsMnth;
string sClsYear; 
Integer ClsDay; 
Integer ClsMnth;
Integer ClsYear; 
Date ClosDt;
DateTime Strt;
string err;
string err0;

Pattern TimePttrnA = Pattern.compile('((([1])([0-2])|(([0])([1-9])))(\\u003A)(([0-5])([0-9]))(\\s)(([AP])([M])))'); // hh:mm a
Pattern TimePttrnB = Pattern.compile('((([1])([0-2])|(([0])([1-9])))(\\u003A)(([0-5])([0-9])))'); 

boolean hasMatchA;
boolean hasMatchB;
boolean tst;

    for(Opportunity opp : nwEvnt) {

        if (opp.Event_Notes__c == null) notes = 'None';

        notes = opp.Event_Notes__c;

        if(string.isEmpty(opp.Event_Start_Time_Pik__c) == false){ 
            opp.Event_Start_Time_Pik__c.normalizeSpace(); 

//          Do time pattern and match validation

            Matcher mA = TimePttrnA.matcher(opp.Event_Start_Time_Pik__c);

            hasMatchA = mA.matches();


            if(hasMatchA == true){

               strtTm = mA.group(0);

            }else{
//             Do time pattern and match validation again without AM/PM

               Matcher mB = TimePttrnB.matcher(opp.Event_Start_Time_Pik__c);  
               hasMatchB = mB.matches();

               if(hasMatchB == true){
                  strtTmB = mB.group(0);  
                  strtTm = ''+ strtTmB +' PM';
                  err0= 'invalid opp.Event_Start_Time_Pik__c, added PM to time found';
                  err = err0;

               }else{
                  strtTm = '00:00 PM';
                  err0 = 'FATAL ERROR!!! Unable to determine value for opp.Event_Start_Time_Pik__c, set to 00:00 PM';
                  err = err0; 

               } // end if(hasMatchB == true)

            } // end else if(hasMatchA == true) 

        } // end if(string.isEmpty(opp.Event_Start_Time_Pik__c) == false)

//      Assemble StartTimeDate and Calculate Planned Mins

        opp.Event_Notes__c = notes;

        try{
           nulltst = opp.CloseDate.format();
           tst = true;

        }catch (Nullpointerexception e){
           tst = false;
           err0='FatalError!!! Null Pointer Exception Trapped for invalid Close Date';
           err = err +', '+ err0;
        }

        if(tst == true){
           ClosDt = opp.CloseDate;
           ClsDay = ClosDt.day();

           if(ClsDay >= 1 && ClsDay <= 9){ 
           sClsDay = '0' + String.ValueOf(ClsDay); 
           } else {
              sClsDay = String.ValueOf(ClsDay);
           }

           ClsMnth = ClosDt.month();

           if(ClsMnth >=0 && ClsMnth <= 9){ 
              sClsMnth = '0' + String.ValueOf(ClsMnth);

           } else {
              sClsMnth = String.ValueOf(ClsMnth);

           }

           ClsYear = ClosDt.year();
           sClsYear = String.ValueOf(ClsYear);

           strtDt = ''+ sClsMnth + '/' + sClsDay + '/' + sClsYear +'' ;

        }else{    
           strtDt = ''+ sClsMnth + '/' + sClsDay + '/' + sClsYear +' (Possible Data Error: confirm Event Date with Manager) ';

        }            

        if(hasMatchA == false && hasMatchB == false){          
           StrtTmDt = sClsMnth + '/' + sClsDay + '/' + sClsYear + ' 12:00 PM';

        }else{            
           StrtTmDt = sClsMnth + '/' + sClsDay + '/' + sClsYear + ' ' + strtTm;

        }
    }

Edit 1A

In your case, here's some more specific code

String N = a.Name;
String N_MCpart;

// Declare a Pattern using the regex pattern I gave you
Pattern myPattern = Pattern.compile('((MC)|(mc)|(Mc)|(mC))|((MC)|(mc)|(Mc)|(mC))\s|((MC)|(mc)|(Mc)|(mC))\\-|((MC)|(mc)|(Mc)|(mC))\')');

// Declare a boolean for when there's a match   
boolean hasMatch;

// Do the pattern match on the name string  

// Declare a Matcher
Matcher myMatcher = myPattern.match(N);

// Test to see if there's a match
hasMatch = myMatcher.matches();

if(hasMatch == true){
   N_MCpart = myMatcher.group(0);
}

Once you have the above, you can manipulate it however you'd like. You'll want to see which "MC" it returned for you to know what to do with it. I'm confident you can figure out what to do with it from here. If there's more than one match, the rest will be in group(1), etc. See the Apex docs for more.

10
  • I can't understand anything here. Sir can you please do the needful changes in my code? Those stuffs in Pattern.comple(...) , I cant get them. Dec 15, 2014 at 3:58
  • Hi crmprogdev! Can you please help me here? salesforce.stackexchange.com/questions/59993/… Dec 15, 2014 at 4:18
  • You first have to compile your regex pattern into a "matcher" in order to use the Pattern Matcher class. In the answer you posted, you've used a string.split method which is string search method that splits every time it finds a match to the sting literal. It is not a regex pattern matcher method.
    – crmprogdev
    Dec 15, 2014 at 5:03
  • Ok Sir can you please do the change for me please? pattern match is something I am totally confused of. Here are my requirements. 1) If there is ' Mc' then make the letter immidiate after 'c' in capital. 2) If there is a hyphen '-' or apostrophe, make the letter immdiate after that in capital. Can you please guide me meet the requirement. Dec 15, 2014 at 5:17
  • See my edited response for some code that's more specific to your situation.
    – crmprogdev
    Dec 15, 2014 at 5:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .