google-sheetsgoogle-apps-script

How to execute a Google Apps Script ONLY on the edited row


I have an auto-mailing script written in the Google Apps Script language. It's linked to an activated installed edit trigger and sends an email to the address in the spreadsheet if the value in col G is changed to "Yes". Here is the spreadsheet: https://docs.google.com/spreadsheets/d/176ld8VOkIksSuSWBErhD5jiZbhCWpZX7wUFwqFJJ-Gs/edit?gid=0#gid=0

and here is the script:

function sendEmails(e) {
  const source = e.source.getActiveSheet(); 
  const dataRange = e.source.getRange("A2:G");
  const data = dataRange.getValues();

console.log(data);
console.log(data.length);
  for (let i = 0; i < data.length; i++) {
    const row = data[i];
    const businessName = row[0];
    const emailAddress = row[1];
    const invoiceNumber = row[2];
    const invoiceAmount = row[3];
    const dueDate = row[4];
    const subject = row[5];
    const edval = row[6];

    console.log(`Row ${i + 2}: ${businessName}, ${emailAddress}, ${invoiceNumber}, ${invoiceAmount}, ${dueDate}, ${subject}`); // Logging the data

    if (edval=="Yes"){

      if (!emailAddress) {
      console.log(`Row ${i + 2}: Email address missing.`);
      continue;
      }
      const message = createEmailMessage(businessName, invoiceNumber, invoiceAmount, dueDate);

      function createEmailMessage(businessName, invoiceNumber, invoiceAmount, dueDate) {
      const message = `Dear ${businessName},

        Your ACME order number ${invoiceNumber} with an amount of $${invoiceAmount} is due on ${dueDate}.

        Send us our money or we'll send a huge boxing glove on a a spring to pop you in the nose!!

        Thank you for your prompt attention to this matter.`;

      return message;
      }

      try {
       GmailApp.sendEmail(emailAddress, subject, message,{replyTo: "roger.rabbit@acme.edu"});
        console.log(`Row ${i + 2}: Email sent to ${emailAddress}`);
      } catch (error) {
    console.log(`Row ${i + 2}: Error sending email to ${emailAddress}. Error message: ${error.message}`);
      }

    }


  }
}

The problem is that emails are sent to every row with "yes" in col G. How can I make this so that it will only send an email to the address in the row where the edit occurred?

Note: sometimes it seems like the edit trigger is working correctly and that only edited rows get an email. Then I test it again and see emails sent to all rows with "Yes" in col G. Is there a time frame where edits are recorded? Am I testing too quickly? Man, I hope that's it but I doubt it.

Citation: https://developers.google.com/


Solution

  • Modification points:

    When these points are reflected in your script, it becomes as follows.

    Modified script:

    When you use this script, please install the OnEdit trigger to the function sendEmails and edit column "G" to "Yes". By this, the script is automatically run.

    In this modification, the sheet name is also checked. In your provided Spreadsheet, "Sheet1" is used. If your actual situation is different from it, please modify the sheet name in the if statement.

    function sendEmails(e) {
      if (!e) {
        console.warn("No event object 'e'. In this case, please edit column 'G' to 'Yes'.");
        return;
      }
      const { range } = e;
      const sheet = range.getSheet();
      const value = range.getValue();
      if (sheet.getName() != "Sheet1" || range.rowStart == 1 || range.columnStart != 7 || value != "Yes") return;
      const row = range.rowStart;
      const [[businessName, emailAddress, invoiceNumber, invoiceAmount, dueDate, subject]] = sheet.getRange(`A${row}:F${row}`).getValues(); // or sheet.getRange(`A${row}:F${row}`).getDisplayValues()
      console.log(`Row ${row}: ${businessName}, ${emailAddress}, ${invoiceNumber}, ${invoiceAmount}, ${dueDate}, ${subject}`);
      if (!emailAddress) {
        console.log(`Row ${row}: Email address missing.`);
        return;
      }
      const message = createEmailMessage(businessName, invoiceNumber, invoiceAmount, dueDate);
      function createEmailMessage(businessName, invoiceNumber, invoiceAmount, dueDate) {
        const message = [
          `Dear ${businessName}`,
          `Your ACME order number ${invoiceNumber} with an amount of $${invoiceAmount} is due on ${dueDate}.`,
          `Send us our money or we'll send a huge boxing glove on a a spring to pop you in the nose!!`,
          `Thank you for your prompt attention to this matter.`,
        ].join("\n\n");
        return message;
      }
      try {
        GmailApp.sendEmail(emailAddress, subject, message, { replyTo: "roger.rabbit@acme.edu" });
        console.log(`Row ${row}: Email sent to ${emailAddress}`);
      } catch (error) {
        console.log(`Row ${row}: Error sending email to ${emailAddress}. Error message: ${error.message}`);
      }
    }
    

    In this script, when the cell value of column "G" is changed to "Yes", an email is sent.

    References: