0

New to Apps scripts...

I'm trying to send a schedule, (a table in sheets), as HTML in an email.

I have managed to piece together a script that does what I want... mostly.

If I use the following range, the script works. (This is the visible table filtered, where results happen to be in the first 26 rows)

var schedRange = sheet.getRange("A1:J26");

The problem is, the full table is "A1:J261", and when I use the full table range (so I can filter other criteria), I get:

Limit Exceeded: Email Body Size.

Can I specify only the filtered table, excluding all hidden content?

My end objective is to be able to:

  1. Loop through available criteria of COL J, with some exceptions
    • (haven't started on this yet)
  2. For each criteria, send table as HTML in email.

I've made a public version available here

Any assistance is much appreciated!!

Thanks in advance.

0

2 Answers 2

2

To get around sending only visible only rows, I have a query setup from my original data table, that is dependant on a cell setup with data validation. (essentially a filter)

Instead of running a filter on the whole table, now my table is made up of only what I wanted filtered. (so no hidden rows)

The query looks like this:

=QUERY(DATA!A1:J,"select A, C, D, E, F, G, H, I where J = '"&E1&"'",+1)

Where E1 is the Company I want to email and the result of the query is the table I want to send them.

The following is the script I have been using for the last few months to send the booking email to each company (as a HTML table) within a Gmail email, from Google Sheets.

I can't locate/recall where the various snippets came from, so apologies for not referencing any authors that contributed to this function.

It works a treat for me, so hopefully, all of this can help you!

function sendEmail_draft() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  var Avals = ss.getRange("A1:A").getValues();
  var Alast = Avals.filter(String).length+1;
  var recipient = sheet.getRange("B1").getValue(); // "TO" email address
  var name = SpreadsheetApp.getActiveSpreadsheet().getName();
  var subject = "DRAFT Booking - "+ sheet.getRange("E1").getValue()+ " ";
  subject +=  Utilities.formatDate(
                  sheet.getRange("D1").getValue(),
                  ss.getSpreadsheetTimeZone(),
                  "EEE, MMM d yyyy"),
                  sheet.getRange("D1").getValue()
  var schedRange = sheet.getRange("A3:H"+Alast); 

  // Put Name & Date into email first.
  // We only want the schedule within borders, so
  // these are handled separately.
  var body = '<div style="text-align:center;display: inline-block;font-family: arial,sans,sans-serif">'
  body += '<H1>'+ "COMPANY NAME "+ sheet.getRange("E1").getValue() +'</H1>';
  body += '<H2>'+ "WORKBOOK NAME:- "+ name +'</H2>';
  body += '<H2>'+ "Date of Booking - "
        + Utilities.formatDate(
            sheet.getRange("D1").getValue(),
            ss.getSpreadsheetTimeZone(),
            "EEEEE, MMMMM d, yyyy")
        + '</H2>';
  body += getHtmlTable(schedRange);
  body += '</div>';
  debugger;

  //recipient = Session.getActiveUser().getEmail();  // For debugging, send only to self
  GmailApp.sendEmail(recipient, subject, "Requires HTML", {htmlBody:body})
}

/////////////

/**
 * Return a string containing an HTML table representation
 * of the given range, preserving style settings.
 */
function getHtmlTable(range){
  var ss = range.getSheet().getParent();
  var sheet = range.getSheet();
  startRow = range.getRow();
  startCol = range.getColumn();
  lastRow = range.getLastRow();
  lastCol = range.getLastColumn();

  // Read table contents
  var data = range.getValues();

  // Get css style attributes from range
  var fontColors = range.getFontColors();
  var backgrounds = range.getBackgrounds();
  var fontFamilies = range.getFontFamilies();
  var fontSizes = range.getFontSizes();
  var fontLines = range.getFontLines();
  var fontWeights = range.getFontWeights();
  var horizontalAlignments = range.getHorizontalAlignments();
  var verticalAlignments = range.getVerticalAlignments();

  // Get column widths in pixels
  var colWidths = [];
  for (var col=startCol; col<=lastCol; col++) { 
    colWidths.push(sheet.getColumnWidth(col));
  }
  // Get Row heights in pixels
  var rowHeights = [];
  for (var row=startRow; row<=lastRow; row++) { 
    rowHeights.push(sheet.getRowHeight(row));
  }

  // Future consideration...
  var numberFormats = range.getNumberFormats();

  // Build HTML Table, with inline styling for each cell
  var tableFormat = 'style="border:1px solid black;border-collapse:collapse;text-align:center" border = 1 cellpadding = 5';
  var html = ['<table '+tableFormat+'>'];
  // Column widths appear outside of table rows
  for (col=0;col<colWidths.length;col++) {
    html.push('<col width="'+colWidths[col]+'">')
  }
  // Populate rows
  for (row=0;row<data.length;row++) {
    html.push('<tr height="'+rowHeights[row]+'">');
    for (col=0;col<data[row].length;col++) {
      // Get formatted data
      var cellText = data[row][col];
      if (cellText instanceof Date) {
        cellText = Utilities.formatDate(
                     cellText,
                     ss.getSpreadsheetTimeZone(),
          'EEE, MMM dd YY'); ///          'EEE, MMM dd - h:mm a');
      }
      var style = 'style="'
                + 'color: ' + fontColors[row][col]+'; '
                + 'font-family: ' + fontFamilies[row][col]+'; '
                + 'font-size: ' + fontSizes[row][col]+'; '
                + 'font-weight: ' + fontWeights[row][col]+'; '
                + 'background-color: ' + backgrounds[row][col]+'; '
                + 'text-align: ' + horizontalAlignments[row][col]+'; '
                + 'vertical-align: ' + verticalAlignments[row][col]+'; '
                +'"';
      html.push('<td ' + style + '>'
                +cellText
                +'</td>');
    }
    html.push('</tr>');
  }
  html.push('</table>');

  return html.join('');
}
Sign up to request clarification or add additional context in comments.

Comments

0

You're hitting the defined limit. This was mentioned in Current limitations:

enter image description here

1 Comment

Yes, so my question - is there a way to only copy the visible cells shown in the auto-filter, instead of the entire array? I can get it to work for 30 rows, which is all I need when filtered, but don't know how to only copy the visible rows.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.