You need to sign in to do that
Don't have an account?

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
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
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:
Let me know if this solves the problem.
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
oops, change your map declaration to:
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));
}
}
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
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.
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));
}
}