2

Below mentioned is my ss link, it is having 'Sheet1' which is having data in it. Whenever the email address is selected from the dropdown (E2) and checkbox is checked to true(F2), the data present in the column A,B and C (A1:C) need to be sent on the selected email address. Note: There may be 1 entry or multiple entries available, need to send all the data that is available at the time of CHECK.

Thanks in advance. SS Link: https://docs.google.com/spreadsheets/d/1tmnDOMyupjeO8d65qHQsxb5KrrKeq7pMYIE8h2VmEJ4/edit?usp=sharing

enter image description here

  • I have to apologize for my poor English skill. About `the data present in the column A,B and C (A1:C) need to be sent on the selected email address.`, in this case, for example, when you select "A2:C3" cells, can you provide the sample email you expect? – Tanaike Jun 14 '22 at 05:19
  • I simply want to send the table of data present at the time of checking tickbox. In the same table format as it can be seen in the sheet (A1:C). Data can be 1 entry or multiple entries. – Asif Sheikh Jun 14 '22 at 05:24
  • I have added the sample image in the question too, pls check. – Asif Sheikh Jun 14 '22 at 05:24
  • Thank you for replying and adding more information. For example, after you selected the cells of "A2:C3", when you check the checkbox of "F2", the selected cell is "F2", because of the current specification. In this case, how do you want to retrieve the 1st selected cells? – Tanaike Jun 14 '22 at 05:40
  • I don't want to select the cell, I just want to enter the data in A,B and C column, Select the email address and send. Email which is sent should have the data present in A1:C (Complete data available in A1:C range, be it 1 entry or 100 entries) – Asif Sheikh Jun 14 '22 at 05:42
  • Thank you for replying. From your reply, I proposed a sample script as an answer. Could you please confirm it? If I misunderstood your question and that was not useful, I apologize. – Tanaike Jun 14 '22 at 05:56

2 Answers2

4

I believe your goal is as follows.

  • You have the email address and checkbox in the cells "E2" and "F2", respectively.
  • When the checkbox is checked, you want to retrieve the email address and the values from the columns "A" to "C", and want to send the values as an email.
  • You want to convert the values to the HTML table.

In this case, how about the following sample script?

Sample script:

This script is run by the installed OnEdit trigger. So, please install OnEdit trigger to the function installedOnEdit. And, when you want to test this, please check the checkbox of "F2".

function installedOnEdit(e) {
  const range = e.range;
  const sheet = range.getSheet();
  const [email, checkbox] = sheet.getRange("E2:F2").getValues()[0];
  if (sheet.getSheetName() != "Sheet1" || !checkbox) return;
  const values = sheet.getRange("A1:C" + sheet.getLastRow()).getValues();
  const html = '<table border="1" style="border-collapse: collapse">' + values.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
  MailApp.sendEmail({ to: email, subject: "sample subject", htmlBody: html});
  range.uncheck();
}

References:

Added:

About your following 3rd question,

,the given SS link may not work now, but is there any work around that only the occupied cells get sent on mail. With the above code, entire column including the black cells are getting sent on the email.

With the above code, all the data present in the range "A1:C" are being sent on the mail with the borders. But I want the table to be sent on mail only till the last data row available. This script is sending the the entire available rows i.e. A1:C1000 with borders. For e.g. If the data is available till the 3rd row i.e. A1: C3, i want only that data to be sent, instead this code is sending the entire available rows i.e. A1:C1000

For example, how about the following modification?

Modified scirpt:

function installedOnEdit(e) {
  // Ref: https://stackoverflow.com/a/44563639
  Object.prototype.get1stEmptyRowFromTop = function (columnNumber, offsetRow = 1) {
    const range = this.getRange(offsetRow, columnNumber, 2);
    const values = range.getDisplayValues();
    if (values[0][0] && values[1][0]) {
      return range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
    } else if (values[0][0] && !values[1][0]) {
      return offsetRow + 1;
    }
    return offsetRow;
  };

  const range = e.range;
  const sheet = range.getSheet();
  const [email, checkbox] = sheet.getRange("E2:F2").getValues()[0];
  if (sheet.getSheetName() != "Sheet1" || !checkbox) return;
  const values = sheet.getRange("A1:C" + sheet.get1stEmptyRowFromTop(1)).getValues();
  const html = '<table border="1" style="border-collapse: collapse">' + values.reduce((s, r) => s += "<tr>" + r.map(c => `<td>${c}</td>`).join("") + "</tr>", "") + "</table>";
  MailApp.sendEmail({ to: email, subject: "sample subject", htmlBody: html});
  range.uncheck();

  // This is from your 2nd question.
  var dstSheet = e.source.getSheetByName("History");
  dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
}
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • @Asif Sheikh Thank you for replying and testing it. I'm glad your issue was resolved. Thank you, too. – Tanaike Jun 14 '22 at 06:27
  • is there any possibility that range get pasted to another sheet "History". Just to store it as history for what i have shared on email. – Asif Sheikh Jun 14 '22 at 06:49
  • @Asif Sheikh About your new question of `is there any possibility that range get pasted to another sheet "History". Just to store it as history for what i have shared on email`, in this case, how about putting the following script to the end of function? `var dstSheet = e.source.getSheetByName("History"); dstSheet.getRange(dstSheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);` In this case, please add "History" sheet. If I misunderstood your new question, I apologize. – Tanaike Jun 14 '22 at 06:54
  • 1
    again thanks for solving it. I appreciate your efforts, short and powerful codes. – Asif Sheikh Jun 14 '22 at 07:09
  • ,the given SS link may not work now, but is there any work around that only the occupied cells get sent on mail. With the above code, entire column including the black cells are getting sent on the email. – Asif Sheikh Jun 16 '22 at 07:16
  • @Asif Sheikh About your new question of `,the given SS link may not work now, but is there any work around that only the occupied cells get sent on mail. With the above code, entire column including the black cells are getting sent on the email.`, I have to apologize for my poor English skill. Unfortunately, I cannot understand your new question. Can I ask you about the detial of it? – Tanaike Jun 16 '22 at 07:20
  • With the above code, all the data present in the range "A1:C" are being sent on the mail with the borders. But I want the table to be sent on mail only till the last data row available. This script is sending the the entire available rows i.e. A1:C1000 with borders. For e.g. If the data is available till the 3rd row i.e. A1: C3, i want only that data to be sent, instead this code is sending the entire available rows i.e. A1:C1000 – Asif Sheikh Jun 16 '22 at 07:52
  • @Asif Sheikh About your 3rd question, I added one more sample script in my answer. Could you please confirm it? If I misunderstood your 3rd question, I apologize. At that time, can you provide the sample Spreadsheet for testing your issue? By this, I would like to confirm it. I could understand and resolve your 1st and 2nd questions. But, it is difficult for me to understand your 3rd question. This is due to my poor English skill. I deeply apologize for this. I would like to study more. – Tanaike Jun 16 '22 at 09:00
  • Thanks it is working as expected. Just for the information, how 2 constants of the same name "range" & "Values" can be defined in a single function. – Asif Sheikh Jun 16 '22 at 09:27
  • @Asif Sheikh Thank you for replying. I'm glad your 3rd question was resolved. – Tanaike Jun 16 '22 at 09:29
1

SUGGESTION:

I did took the long route with using an HTML Template created on the App Script Files Library, but here's mine:

Notes: Instead of using a checkbox, I'd suggest creating a little image button and assign the script to that button on your Google Sheets (if that works for you.) Like so:

enter image description here

SCRIPT:

function sendEmail() {

  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var sheet = ss.getSheetByName('Sheet1'); 
  var emailadd = sheet.getRange('E2').getValue(); 
  var header = sheet.getRange('A1:C1').getValues().flat();
  var range = sheet.getRange(2,1, sheet.getLastRow() - 1, 3);

  const sr = header[0];
  const pName = header[1]; 
  const price = header[2];

  var values = range.getDisplayValues();
  const html = HtmlService.createTemplateFromFile('email');

  html.sr = sr; 
  html.pName = pName; 
  html.price = price;
  html.values = values;

  const test = html.evaluate().getContent();
  console.log(test);

  MailApp.sendEmail(
  emailadd, 
  "Set Email Subject Here", 
  "HTML", { htmlBody: test}
  );

}

(EDITED) HTML:

    <!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    
    <table style="border: 1px solid;border-collapse: collapse;">

      <thead>
        <tr style="border: 2px solid;border-collapse: collapse;">
          <th ><?= sr ?></th><th><?= pName ?></th><th><?= price ?></th>
        </tr>
      </thead>

      <tbody >
     
          <? values.forEach(x => { ?> 
          <tr style="border: 2px solid;border-collapse: collapse;">
            <td style="border: 1px solid;border-collapse: collapse;"><?= x[0] ?></td><td style="border: 1px solid;border-collapse: collapse;"><?= x[1] ?></td><td style="border: 1px solid;border-collapse: collapse;"><?= x[2] ?></td>
          </tr>
          <? }) ?>
          
        </tr>
      </tbody>

    </table> 
  </body>
</html>
Century Tuna
  • 1,378
  • 1
  • 6
  • 13
  • 1
    That great, but using checkbox sound convenient coz user may mistakenly delete the image or drag which i don't prefer. Your code works fine too but previous one is short and efficient. Thanks – Asif Sheikh Jun 14 '22 at 06:47
  • Alright no worries! Leaving this answer here just in case other users may want a different approach. Thanks for the feedback! – Century Tuna Jun 14 '22 at 06:49
  • Hello, Diego, is there any work around that we can get borders in the table that is being sent on email? – Asif Sheikh Jun 16 '22 at 07:08
  • table borders need to be defined using inline style `style="border: 1px solid;border-collapse: collapse;"`. Edited my answer above which i think looks well. – Century Tuna Jun 16 '22 at 09:41
  • Thanks, your answer is useful for me as it has CSS. Please note, heading is not getting 'All borders', heading is getting only Outer borders. Any workaroud for that? – Asif Sheikh Jun 17 '22 at 11:20