rowsToObjects and objectsToRows

Sheet data is easiest as a 2D array. Business logic is easier as objects keyed by header. These two helpers convert back and forth without dragging a dependency into a bootstrapper file.

What you'll need

  • A 2D array from getValues() (header row first), or
  • An array of plain objects plus an optional header order when writing back

rowsToObjects

Takes [[headers...], [row]...] and returns [{header: value, ...}, ...].

function rowsToObjects(rows) { if (!rows || !rows.length) return []; var headers = rows[0].map(function (h) { return String(h).trim(); }); return rows.slice(1).map(function (row) { var obj = {}; for (var i = 0; i < headers.length; i++) { obj[headers[i]] = row[i]; } return obj; }); }

objectsToRows

Takes objects and an optional header list (column order). Returns a 2D array ready for setValues, header included.

function objectsToRows(objects, headers) { if (!objects || !objects.length) return [headers || []]; headers = headers || Object.keys(objects[0]); var body = objects.map(function (obj) { return headers.map(function (key) { return obj.hasOwnProperty(key) ? obj[key] : ''; }); }); return [headers].concat(body); }

Round-trip example

function filterActiveAndWrite() { var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('People'); var values = sheet.getDataRange().getValues(); var people = rowsToObjects(values); var active = people.filter(function (p) { return p.Status === 'Active'; }); var headers = values[0]; var out = objectsToRows(active, headers); var dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('ActivePeople'); dest.clearContents(); dest.getRange(1, 1, out.length, out[0].length).setValues(out); }

Tips:

  • Trim headers once so "Name " and "Name" don't become two different keys.
  • Pass an explicit headers array into objectsToRows when column order matters (Sheets care; Object.keys order is usually insertion order but don't gamble on it for client deliverables).
  • Blank source rows still become objects — pair with a blank-row filter snippet if you need to drop them first.

Happy Coding!

NitroGAS Chrome Extension

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

Get the Extension