HTML Table From Objects

Digest emails beat screenshots of a sheet. htmlTableFromObjects(rows, columns) turns an array of objects into a simple escaped <table> you can drop into HtmlBody. Pair it with sendHtmlEmail — it’s a table builder, not a full report engine.

What you'll need

  • An array of row objects ([{ name, email, status }, …])
  • columns: string keys or { key, label } objects
  • Something that sends HTML (GmailApp / sendHtmlEmail)

How to use this snippet

/** * Escape text for HTML table cells. * @param {*} value * @return {string} */ function escapeHtml_(value) { return String(value == null ? '') .replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;'); } /** * Build a simple HTML table from object rows. * @param {Object[]} rows * @param {Array<string|{key:string,label?:string}>} columns * @return {string} HTML <table>…</table> */ function htmlTableFromObjects(rows, columns) { rows = rows || []; columns = (columns || []).map(function (c) { if (typeof c === 'string') return { key: c, label: c }; return { key: c.key, label: c.label != null ? c.label : c.key }; }); var html = '<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;font-family:Arial,sans-serif;font-size:13px;">'; html += '<thead><tr>'; columns.forEach(function (col) { html += '<th align="left">' + escapeHtml_(col.label) + '</th>'; }); html += '</tr></thead><tbody>'; rows.forEach(function (row) { html += '<tr>'; columns.forEach(function (col) { var cell = row && row[col.key]; html += '<td>' + escapeHtml_(cell) + '</td>'; }); html += '</tr>'; }); html += '</tbody></table>'; return html; }

Example

function sendNightlyDigest_() { var sheet = SpreadsheetApp.getActive().getSheetByName('Exceptions'); var values = sheet.getDataRange().getValues(); var headers = values.shift(); var rows = values.map(function (r) { var o = {}; headers.forEach(function (h, i) { o[h] = r[i]; }); return o; }).filter(function (o) { return o.status === 'FAIL'; }); var table = htmlTableFromObjects(rows, [ { key: 'orderId', label: 'Order' }, { key: 'reason', label: 'Reason' }, 'status' ]); var body = '<p>' + rows.length + ' failures overnight.</p>' + table; // pair with your sendHtmlEmail helper GmailApp.sendEmail(Session.getActiveUser().getEmail(), 'Nightly exceptions', '', { htmlBody: body }); }

Tips:

  • Always escape — user-entered sheet cells can contain < and break (or worse, inject) HTML.
  • Keep columns explicit; don’t dump every object key into a digest.
  • Empty rows still returns a header-only table so the email layout stays stable.
  • For big reports, link to the sheet instead of stuffing hundreds of rows into Gmail.

Tip: NitroGAS Co-Pilot can draft the columns list and wire htmlTableFromObjects into your existing sendHtmlEmail digest — you still pick which fields leave the sheet.

Happy Coding!

NitroGAS Chrome Extension

Want this snippet handy inside the Apps Script editor? NitroGAS gives you free themes and snippets — plus optional Co-Pilot when you want a boost (1-week, 1-month, or yearly passes — no subscription). Happy Coding!

Get the Extension