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
pjaenickepjaenicke 

Trigger syntax - get the id from a map

Feels like I'm really close... 

 

I'm still struggling with trying to populate a lookup field to another table based on the value in a text field.

 

I have...

 a map of accounts with their associated scrubbed zip-code ("accountmap")

 a set of unique scrubbed zip-codes ("accountzips")

 a map of zip codes ("zipcodes")

 

The code compiles, but fails on execution:

        a.ZipId__c = zipcodes.get(accountmap.get(a.id)).id; 

 

Error:  "Apex trigger PopZipId caused an unexpected exception, contact your administrator: PopZipId: execution of BeforeUpdate caused by: System.StringException: Invalid id: 10041"

 

Full trigger is shown below.  Thanks for any/all guidance.  I'm pulling my hair out.

 

//  Set<string> accountzips = new Set<string>();

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

    String billzip;
    integer dashpos;

    Map<id, string> accountmap = new Map<id, string>();
    Set<string> accountzips = new Set<string>();

    for (Account a : Trigger.new) {
        // only include accounts being inserted or where the BillingPostalCode is changing
        if (
                System.Trigger.isInsert
            || (System.Trigger.isUpdate && a.BillingPostalCode != System.Trigger.oldMap.get(a.Id).BillingPostalCode)
           )
        {
            // remove leading zeros, remove zip+4
            if (a.BillingPostalCode != Null) {
                dashpos = (a.BillingPostalCode + '-').indexof('-');
                billzip = (a.BillingPostalCode.substring(0,Dashpos)).replaceAll('^0+(?!$)','');
                //if we accidentally nulled out the zip code, use the '0' zip code:
                if (billzip == Null) {
                    billzip = '0';
                }
            } else {
                billzip = '0';
            }
        accountmap.put(a.id, billzip);
        accountzips.add(billzip);
        }
    } 
   
    Map<id, zip__c> zipcodes = new Map<id, zip__c>([Select id, name from zip__c where name in :accountzips]);

    for (Account a : Trigger.new) {
        //a.ZipId__c = 'a0kT0000000K7dI';     
        a.ZipId__c = zipcodes.get(accountmap.get(a.id)).id; 
    }
}

 

Pete

Best Answer chosen by Admin (Salesforce Developers) 
Chris BarryChris Barry

Pete, did your bulk test involve *inserting* a bunch of accounts? In a Before Insert Trigger event, the id of the Account has not yet been set by the database, therefore a.Id will return null. You can add null to a map as a key, therefore your map probably has one entry: (null, <last zip put on it>). I suggest using some other key on your acctNewZipMap to uniquely identify your accounts.

All Answers

jhenningjhenning

Looks like the "accountmap.get(a.id)" part of the "a.ZipId__c = zipcodes.get(accountmap.get(a.id)).id;" statement returns a string, then you are using the string to perform a Get on the zipcodes map, but the zipcodes map key is an Id. You should switch the zipcodes map around. Replace "Map<id, zip__c> zipcodes = new Map<id, zip__c>([Select id, name from zip__c where name in :accountzips]);" with the following:

 

 

Map<zip__c, id> zipcodes = new Map<zip__c, id>();
for (zip__c z:[Select id, name from zip__c where name in :accountzips]){
    zipcodes.put(z.name, z.id);
}

 

Let me know if this solves the problem.

 

pjaenickepjaenicke

Thanks John,

 

This creates a compile error :

Error: Compile Error: Incompatible key type String for MAP:SOBJECT:Zip__c,Id at line 36 column 9

  

//    Map<id, zip__c> zipcodes = new Map<id, zip__c>([Select id, name from zip__c where name in :accountzips]);

    Map<zip__c, id> zipcodes = new Map<zip__c, id>();
    for (zip__c z:[Select name, id from zip__c where name in :accountzips]){
        zipcodes.put(z.name, z.id);
    }

 

Appreciate the help,

Pete

jhenningjhenning

oops, change your map declaration to:

 

 

Map<string, id> zipcodes = new Map<string, id>();

 

 

pjaenickepjaenicke

John - most obliged !

 

Works like a charm now.  Thanks again for your help!  The complete trigger is indicated below.  (A minor change was necesary in the final assignment).

 

 

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

    String billzip;
    integer dashpos;

    Map<id, string> accountmap = new Map<id, string>();
    Set<string> accountzips = new Set<string>();

    for (Account a : Trigger.new) {
        // only include accounts being inserted or where the BillingPostalCode is changing
        if (
                System.Trigger.isInsert
            || (System.Trigger.isUpdate && a.BillingPostalCode != System.Trigger.oldMap.get(a.Id).BillingPostalCode)
           )
        {
            // remove leading zeros, remove zip+4
            if (a.BillingPostalCode != Null) {
                dashpos = (a.BillingPostalCode + '-').indexof('-');
                billzip = (a.BillingPostalCode.substring(0,Dashpos)).replaceAll('^0+(?!$)','');
                //if we accidentally nulled out the zip code, use the '0' zip code:
                if (billzip == Null) {
                    billzip = '0';
                }
            } else {
                billzip = '0';
            }
        accountmap.put(a.id, billzip);
        accountzips.add(billzip);
        }
    }  
    
    Map<string, id> zipcodes = new Map<string, id>();
    for (zip__c z:[Select name, id from zip__c where name in :accountzips]){
        zipcodes.put(z.name, z.id);
    }

    for (Account a : Trigger.new) {
        a.ZipId__c = zipcodes.get(accountmap.get(a.id));
    }
}

pjaenickepjaenicke

Ok, I think I celebrated a bit early :)

 

My code works fine on singular inserts, but on bulk, it uploads all records with the same Zip Id,  (oops!):

 

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

  Set<string> uniquezipset = new Set<string>();
  Map<id, string> acctNewZipMap = new Map<id, string>();


  for (Account a : Trigger.New) {
    zip = a.BillingPostalCode;
    // ... code to scrub the zip code further
    uniquezipset.add(zip);
    acctNewZipMap.put(a.id, zip);
  }

  List<Zip__c> zipList = [SELECT Id, Name From Zip__c where Name in :uniquezipset];
    
  Map<string, id> zipcodesmap = new Map<string, id>();
  for (zip__c z:[Select name, id from zip__c where name in :uniquezipset]) {
    zipcodesmap.put(z.name, z.id);
  }
    
  for (Account a : Trigger.new) {
    a.ZipId__c = zipcodesmap.get(acctNewZipMap.get(a.Id));
//  a.zipId__c = zipcodesmap.get(a.BillingPostalCode); // works fine, but
//                                                        uses unscrubbed zip
  }
}

 

Struggling with the double get...  trying to get the scrubbed zip asociated to each account, (stored in acctNewZipMap),

and use that value to pull the id from the zip table, (zipcodesmap).  An explanation as to why it's pulling the same result

for all records would be an added bonus :)

 

Thanks,

Pete

 

Chris BarryChris Barry

Pete, did your bulk test involve *inserting* a bunch of accounts? In a Before Insert Trigger event, the id of the Account has not yet been set by the database, therefore a.Id will return null. You can add null to a map as a key, therefore your map probably has one entry: (null, <last zip put on it>). I suggest using some other key on your acctNewZipMap to uniquely identify your accounts.

This was selected as the best answer
pjaenickepjaenicke

Chris,

 

Wow..  wasn't syntax at all - was a logic gap :)   Thanks so much for the assistance !  As Chris suggested, I substituted the Account Id map with an integer representing the record count - it now works like a charm.

 

Thanks again :)

 

Working trigger is documented below:

 

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

  String zip;
  String c;
  String paddedzip;
  integer charpos;
  integer lastnum;
  integer recordcount = 0;

  Set<string> uniquezipset = new Set<string>();
  Map<integer, string> recordZipMap = new Map<integer, string>();

  for (Account a : Trigger.New) {
    recordcount++;
    zip = ((string.valueof(a.BillingPostalCode+'')).trim()+'XXXXX').substring(0,6);
    charpos=0;
    lastnum=0;        
    while (charpos < zip.length()) {
      c = zip.substring(charpos,charpos+1);
      if ((c>='0') && (c<='9')) {
        charpos++;
        lastnum=charpos;
      }
      else {                                            
        charpos = zip.length();
      }
    }
    // zero (left) pad the zip code, if necessary
    paddedzip = '00000' + zip.substring(0,lastnum);
    zip = paddedzip.substring(paddedzip.length()-5);
    uniquezipset.add(zip);
    recordZipMap.put(recordcount, zip);
  }

  Map<string, id> zipcodesmap = new Map<string, id>();
  
  for (zip__c z:[Select name, id from zip__c where name in :uniquezipset]) {
    zipcodesmap.put(z.name, z.id);
  }

  recordcount = 0;    
  for (Account a : Trigger.new) {
    recordcount++;
    a.ZipId__c = zipcodesmap.get(recordZipMap.get(recordcount)); 
  }
}