0

I have setup a task custom object. When the user changes the status of task from pending to completed, an email alert needs to be sent to the person with the attachment that is available in the 'notes and attachment' section on task level. I am calling the following apex class/function from process builder when the task status changes to complete to send an email alert with attachment.However, the code does not detect the file attached in notes and attachments section on tasks and throws error "An Apex error occurred: System.QueryException: List has no rows for assignment to SObject"

 public class sendAnEmailWithCompletedForm
{
     @InvocableMethod(label='Send an email from apex class' 
     description='sends an email')
     public static void sendEmailWithAttachment(List<Id> 
     Requestor_s_Checklist)

{

          Id Taskid= Requestor_s_Checklist[0];
          Attachment a;
          Attachment[] attachments = [select Id, Name, Body, BodyLength from Attachment where ParentId =: Requestor_s_Checklist];
          if (attachments.size() > 0)
              a = attachments[0];


           Messaging.SingleEmailMessage semail= new Messaging.SingleEmailMessage();
           Messaging.EmailFileAttachment attach= new Messaging.EmailFileAttachment();
           attach.setBody(a.Body);
           attach.setFileName(a.Name);
           semail.setSubject('Review the completed form');
           String[] emailIds= new String[]{'[email protected]'};
           semail.setToAddresses(emailIds);
            semail.setPlainTextBody('Please find the attached completed FormName');
           semail.setFileAttachments(new Messaging.EmailFileAttachment[]{attach});
           Messaging.sendEmail(new Messaging.SingleEmailMessage[]{semail});


   }

 }

2 Answers 2

0

First you should correct few things in your apex code:-

  1. It is not suggested to use soql query and dml statement inside a for loop.

A common mistake is that queries or DML statements are placed inside a for loop. There is a governor limit that enforces a maximum number of SOQL queries. There is another that enforces a maximum number of DML statements (insert, update, delete, undelete). When these operations are placed inside a for loop, database operations are invoked once per iteration of the loop making it very easy to reach these governor limits.

Instead, move any database operations outside of for loops. If you need to query, query once, retrieve all the necessary data in a single query, then iterate over the results. If you need to modify the data, batch up data into a list and invoke your DML once on that list of data. Learn more here:- Avoid SOQL Queries or DML statements inside FOR Loops

  1. While a SELECT normally returns an array/list, these statements are using the shorthand syntax that assumes only one row is returned. What’s not obvious is that it also assumes that exactly one row is returned!

    Player__c player = [SELECT Id from Player__c where Name = :username];
    if (player != null)
     p = player.Id;
    

The above code will fail if there is no Player__c record with the matching username. It doesn't actually return a null.

It would be safer to do the following:

Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (players.size() > 0)
p = players[0].Id;

It’s one of those situations for which you would not normally think of creating a test, so it’s safer to just avoid the possibility. Learn more about it here:- List has no rows for assignment to SObject error

  • Now Coming to your question:- You are getting it because the query is not returning any value . It means there is no such attachment available in your org where attachment is related to the current assigned taskId in the loop.
  • Instead of doing a query inside every time inside a loop, better option to use Map.It might be also the case where a task is having more than one attachment attached to it. Again you will face problem.
  • For inserting anything inside a loop, You should use list to store the value and insert the list outside the loop.
1
  • thanks for the help. I have updated the code above. However, I am still gettiing the same null error.
    – Student
    Commented Mar 28, 2019 at 12:52
0

Salesforce files are no longer stored in the old Attachment object but are now in the ContentDocument / ContentVersion / ContentDocumentLink structure. You'll need to query from the ContentVersion and ContentDocumentLink objects to get the info you need.

You must log in to answer this question.

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