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
Michael ChristieMichael Christie 

Update Custom Field Based on Attachment File Name

Hi, I'm very new to creating triggers so I apologize if this question is somewhat basic. I am trying to create a trigger on an attachment that, when an attachment with a specific file name is uploaded to an account, will update a custom Datetime field on that account. When the attachment with the specific file name is deleted from the account, the value in the Datetime account field should be erased. Using this thread: https://developer.salesforce.com/forums/?id=9060G000000I8UmQAK#!/feedtype=SINGLE_QUESTION_SEARCH_RESULT&id=906F0000000Ayf8IAC  I was able to create a simple trigger, but I am missing the logic portion to limit the trigger to attachments containing the string "Admissions Packet" in the file name. Here is what I have so far: 
trigger AdmissionsPacketUploaded on Attachment (before insert, before delete)
{
if(trigger.isinsert){
List<Account> co = [select id from Account where id =: Trigger.New[0].ParentId];
If(co.size()>0 && Attachment.Name.contains('Admissions Packet'))
{            
    co[0].Date_Admissions_Packet_Uploaded__c = Date.Today();            
update co;        
}
}


if(trigger.isdelete){

List<Account> co = [select id from Account where id =: Trigger.old[0].ParentId];        
If(co.size()>0 && Attachment.Name.contains('Admissions Packet'))        
{            
    co[0].Date_Admissions_Packet_Uploaded__c = NULL;            
update co;        
}
}
}
My two error messages (for both isinsert and isdelete) read "Method does not exist or incorrect signature: void contains(String) from the type Schema.SObjectField." 

Any assistance would be greatly appreciated!
Best Answer chosen by Michael Christie
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
Michael,  

It looks like Raj's answer is correct; but the trigger is not bulkified.  It assumes there is only one Attachment being inserted or deleted at a time.  This is not a best practice for writing triggers.  Here, I offer a bulkified version that has two other advantages.  The query on Account is only done if there is at least one Attachment with "Admissions Packet" in the filename; and the same code runs for both insert and delete - no need to have two nearly duplicate code blocks to maintain.  Another note: You may wonder why the code does not check whether the query returned any records.  In that case, the query will return an empty list; the for-loop will not iterate; and the update will do nothing - and it won't count against your DML limits.  Let me know if you have any questions.

<pre>
trigger AdmissionsPacketUploaded on Attachment (after insert, after delete)
{
    Set<Id> parentIds = new Set<Id>();
    for ( Attachment attachment : Trigger.isInsert ? Trigger.new : Trigger.old )
    {
        if ( attachment.Name.contains( 'Admissions Packet' ) )
        {
            parentIds.add( attachment.ParentId );
        }
    }
    if ( parentIds.isEmpty() ) return;

    List<Account> accounts =
    (   [   SELECT  Id, Date_Admissions_Packet_Uploaded__c
            FROM    Account
            WHERE   Id IN :parentIds
        ]
    );
    for ( Account account : accounts )
    {
        account.Date_Admissions_Packet_Uploaded__c = Trigger.isInsert ? Date.today() : null;
    }
    update accounts;
}
</pre>

All Answers

Raj VakatiRaj Vakati
change it to
 
Trigger.New[0].Name.contains('Admissions Packet')

 
Raj VakatiRaj Vakati
complete code
 
trigger AdmissionsPacketUploaded on Attachment (after insert, after delete)
{
if(trigger.isinsert){
List<Account> co = [select id from Account where id =: Trigger.New[0].ParentId];
If(co.size()>0 && Trigger.New[0].Name.contains('Admissions Packet'))
{            
    co[0].Date_Admissions_Packet_Uploaded__c = Date.Today();            
update co;        
}
}


if(trigger.isdelete){

List<Account> co = [select id from Account where id =: Trigger.old[0].ParentId];        
If(co.size()>0 && Trigger.New[0].Name.contains('Admissions Packet'))        
{            
    co[0].Date_Admissions_Packet_Uploaded__c = NULL;            
update co;        
}
}
}

 
Glyn Anderson (Slalom)Glyn Anderson (Slalom)
Michael,  

It looks like Raj's answer is correct; but the trigger is not bulkified.  It assumes there is only one Attachment being inserted or deleted at a time.  This is not a best practice for writing triggers.  Here, I offer a bulkified version that has two other advantages.  The query on Account is only done if there is at least one Attachment with "Admissions Packet" in the filename; and the same code runs for both insert and delete - no need to have two nearly duplicate code blocks to maintain.  Another note: You may wonder why the code does not check whether the query returned any records.  In that case, the query will return an empty list; the for-loop will not iterate; and the update will do nothing - and it won't count against your DML limits.  Let me know if you have any questions.

<pre>
trigger AdmissionsPacketUploaded on Attachment (after insert, after delete)
{
    Set<Id> parentIds = new Set<Id>();
    for ( Attachment attachment : Trigger.isInsert ? Trigger.new : Trigger.old )
    {
        if ( attachment.Name.contains( 'Admissions Packet' ) )
        {
            parentIds.add( attachment.ParentId );
        }
    }
    if ( parentIds.isEmpty() ) return;

    List<Account> accounts =
    (   [   SELECT  Id, Date_Admissions_Packet_Uploaded__c
            FROM    Account
            WHERE   Id IN :parentIds
        ]
    );
    for ( Account account : accounts )
    {
        account.Date_Admissions_Packet_Uploaded__c = Trigger.isInsert ? Date.today() : null;
    }
    update accounts;
}
</pre>
This was selected as the best answer
Akshay_DhimanAkshay_Dhiman
Hi Michael Christie,

 Try this code its working fine.
 
trigger HelpAttachmentTrue on Attachment (before insert,before delete)
{
    Set<Id> attId = new Set<Id>();
    List<Account> toUpdateList = new List<Account>();
    
    if(Trigger.isInsert || Trigger.isUpdate){
        for(Attachment at :Trigger.New){
            attId.add(at.ParentId);
        }
        if(attId.size() > 0){
            map<Id,Account> mapAcc = new map<Id,Account>([select Id, Date_Admissions_Packet_Uploaded__c from Account where Id IN :attId]);
            if(!mapAcc.isEmpty()){
                for(Attachment att:Trigger.New){
                    if(att.Name.contains('Admissions Packet')){
                        Account acc=mapAcc.get(att.ParentId);
                        acc.Date_Admissions_Packet_Uploaded__c=System.today();
                        toUpdateList.add(acc);
                        
                    }
                }
            }
            if(toUpdateList.size()>0)
            {
                update toUpdateList;
            }                                                                   
        }
    }
    if(Trigger.isDelete){
                    System.debug('attId');
        for(Attachment at :Trigger.Old){
            attId.add(at.ParentId);
        }
        if(attId.size() > 0){
            System.debug('attId'+attId);
            map<Id,Account> mapAcc = new map<Id,Account>([select Id, Date_Admissions_Packet_Uploaded__c from Account where Id IN :attId]);
            System.debug('attId'+mapAcc);
            if(!mapAcc.isEmpty()){
                for(Attachment att:Trigger.Old){
                    if(att.Name.contains('Admissions Packet')){
                        Account acc=mapAcc.get(att.ParentId);
                        acc.Date_Admissions_Packet_Uploaded__c=null;
                        toUpdateList.add(acc);
                    }
                }
            }
            if(toUpdateList.size()>0)
            {
                update toUpdateList;
            }                                                                   
        }
    }
}


Thanks,

Akshay

Michael ChristieMichael Christie
Hello Glyn,

Thank you for the modifications and tips with the trigger's code. While the adjusted code provided by Raj worked initially, I did encounter errors when I tried to delete an attachment from an account (Raj, I apologize for not clarifying: multiple attachments may need to be uploaded to a single account). Now I just have to work on developing a test class and it should be ok. Thank you, everyone, for your help. 

Best,
Michael