+ Start a Discussion
Joe BBJoe BB 

Autopopula​te "New Task" activity field from related Object?

 

Hello,
I would like to be able to create a formula that can bring up (auto populate) a custom Activity field from a field that originates in the the object where the activity is related to.


For example, Account object has custom field that says Account#. The Related Activity (New Task) has the same custom field Account#. I would like to create a link between both fields, such that when Account# in Account record is populated it automatically transfers that field value to the related field in New Task, New Event and Log a Call Activities once an user clicks on these activities.

Could you  please tell me how I can create such trigger?

 

Please help!
Thank you so much!

sfdcfoxsfdcfox
trigger copyparentdata on task (before insert) {
  map<id, account> accounts = new map<id, account>();
  for( task t:trigger.new ) {
    if(t.accountid!=null) {
      accounts.put(t.accountid,null);
    }
    if(t.whatid!=null&&t.whatid.getsobjecttype()==account.sobjecttype) {
      accounts.put(t.whatid,null);
    }
  }
  accounts.putAll([select id,accountnumber__c from account where id in :accounts.keyset()]);
  for( task t:trigger.new ) {
    if( t.accountid != null ) {
      t.accountnumber__c = accounts.get( t.accountid ).accountnumber__c;
    }
    if( accounts.containskey( t.whatid ) ) {
      t.accountnumber__c = accounts.get( t.whatid ).accountnumber__c;
    }
  }
}

This is a typical "aggregate-query-update" pattern. The page itself won't show the custom data being copied when rendered initially, but after saving, the data will be populated.

Joe BBJoe BB

Thank you for the quick response.

1)      Could you please Bold where I have to substitute with Account_#__c in the trigger?

Both Accounts field and Task field have the same name – Account #.

2)      Should I leave rest the same?

3)      Is the whole code for one field? How do I make it work for more than one field?

 

Thank you, sir!  

sfdcfoxsfdcfox

1) Lines 11, 14 and 17, I refer to the field as "accountnumber__c". Change those values to whatever you desire. You can't use "#" in a field name, so I assume your field is probably called "Account__c", "Account_Number__c", or "Account_No__c". I personally use title case syntax in field names, so AccountNumber__c is how I would have labeled them.

2) This code should work flawlessly assuming the field names are correct (you'd get a compilation error elsewise). This code already includes the minimum number of safeguards I would put in place to prevent null pointer exceptions and other unpleasant surprises for the user.

3) All of this code is for one field. For multiple fields, change the logic as follows: (a) place the fields to copy into the query currently located on line 11, (b) duplicate line 14 for each field you'd like to assign, changing the field names as appropriate, and (c) duplicate the current line 17 for each field you would like to assign, changing field names as appropriate. Example follows.

 

trigger copyparentdata on task (before insert) {
  map<id, account> accounts = new map<id, account>();
  for( task t:trigger.new ) {
    if(t.accountid!=null) {
      accounts.put(t.accountid,null);
    }
    if(t.whatid!=null&&t.whatid.getsobjecttype()==account.sobjecttype) {
      accounts.put(t.whatid,null);
    }
  }
  accounts.putAll([select id,field1__c,field2__c,field3__c from account where id in :accounts.keyset()]);
  for( task t:trigger.new ) {
    if( t.accountid != null ) {
      t.fielda__c = accounts.get( t.accountid ).field1__c;
      t.fieldb__c = accounts.get( t.accountid ).field2__c;
      t.fieldc__c = accounts.get( t.accountid ).field3__c;
    }
    if( accounts.containskey( t.whatid ) ) {
      t.fielda__c = accounts.get( t.whatid ).field1__c;
      t.fieldb__c = accounts.get( t.whatid ).field2__c;
      t.fieldc__c = accounts.get( t.whatid ).field3__c;
    }
  }
}

As you can see, this code scales well. You could do 10 or 20 fields with a linear growth in code the number of lines you'd like to add. Of course, this isn't necessarily the most optimal design... I could just as well do this:

 

trigger copyparentdata on task (before insert) {
  map<id, account> accounts = new map<id, account>();
  for( task t:trigger.new ) {
    if(t.accountid!=null) {
      accounts.put(t.accountid,null);
    }
    if(t.whatid!=null&&t.whatid.getsobjecttype()==account.sobjecttype) {
      accounts.put(t.whatid,null);
    }
  }
  accounts.putAll([select id,field1__c,field2__c,field3__c from account where id in :accounts.keyset()]);
  for( task t:trigger.new ) {
	id whatId = t.accountid == null ? t.whatid : t.accountid ;
    if( accounts.containsKey( whatId ) && accounts.get( whatId ) != null ) {
      t.fielda__c = accounts.get( whatId ).field1__c;
      t.fieldb__c = accounts.get( whatId ).field2__c;
      t.fieldc__c = accounts.get( whatId ).field3__c;
    }
  }
}

This shortens the logic by using whichever of two ID values I have access to.

Joe BBJoe BB

 Thank you SFDCFOX!

 

Could you please tell me where I should place this code. It is new to me.

 

Also, is there any danger to the set up and the information of my organization if I deploy this code? Can I easily revert it if it does not work without causing any harm?

 

Thank you do much!!!

 

sfdcfoxsfdcfox

You'll place it in the Force.com IDE or your organization's "sandbox" account ( Setup > Data management > Sandboxes ). Triggers can be turned on and off by visiting Setup > Develop > Apex Triggers, so disabling misbehaving code is just a click away.

Joe BBJoe BB

Hi Fox!

 Our organization has an Enterprise edition and I think that we can run only Developer Sandbox, although when I go and create one it ask me to select between Developer, Full and select?

My understanding is that I have to place the trigger in the Force.com. Is that correct? I do not see it available in the full list of objects. I have something called “Force.com Connect Offline 2.0”, which offers a trial version and says:  "Alternatively, Administrators, click here to download the zipped MSI package to your desktop."

Do we have a procedure anywhere?

 

Thank you!

Joe BBJoe BB

I inserted the following trigger in my org Developer Sandbox:

 

trigger copyparentdata on task (before insert) {
  map<id, account> accounts = new map<id, account>();
  for( task t:trigger.new ) {
    if(t.accountid!=null) {
      accounts.put(t.accountid,null);
    }
    if(t.whatid!=null&&t.whatid.getsobjecttype()==account.sobjecttype) {
      accounts.put(t.whatid,null);
    }
  }
  accounts.putAll([select id,Bill_to_Account_Number__c from account where id in :accounts.keyset()]);
  for( task t:trigger.new ) {
    if( t.accountid != null ) {
      t.fielda__c = accounts.get( t.accountid ).Bill_to_Account_Number__c;
        }
    if( accounts.containskey( t.whatid ) ) {
      t.fielda__c = accounts.get( t.whatid ).Bill_to_Account_Number__c;
    }
  }
}

 I get the following error:

 

ErrorError: Compile Error: Variable does not exist: account.sobjecttype at line 7 column 51

 

Do you have any idea how to fix that error?

Thank you!

 

sfdcfoxsfdcfox

It works in my developer org. Are you sure your developer org is on Winter 13? I would think all orgs should be on Winter 13 by now, but if not, it wouldn't work.

 

Triggers are added in the Developer Sandbox, under Setup > Customize > Activities > Task Triggers.