Objects: keys, values and entries
An object maps keys to values ({name: "Ana", qty: 5}); Object.keys(obj) lists the keys, Object.values(obj) the values and Object.entries(obj) [key, value] pairs. The most useful sheet pattern is turning each row into an object by header: rows.map(r => Object.fromEntries(headers.map((h, i) => [h, r[i]]))), so code reads row.qty instead of row[3].
Syntax
Object.keys(obj) | Object.values(obj) | Object.entries(obj) | Object.fromEntries(pairs)Examples
const sheet = SpreadsheetApp.getActiveSheet();
const [headers, ...rows] = sheet.getDataRange().getValues();
const records = rows.map(r => Object.fromEntries(headers.map((h, i) => [h, r[i]])));
Logger.log(JSON.stringify(records[0]));Result: {"Item":"Pens","Qty":12,"Price":2.5}
const counts = {};
records.forEach(rec => counts[rec.Status] = (counts[rec.Status] || 0) + 1);
Logger.log(JSON.stringify(counts));Result: {"Open":7,"Closed":12}
const out = Object.entries(counts).map(([status, n]) => [status, n]);
sheet.getRange("H1:I" + out.length).setValues(out);Result: H1:I2 holds Open 7 and Closed 12
Common mistakes
- rec.qty is undefined: keys are case-sensitive and come from the header text exactly, including spaces; normalize headers with trim and toLowerCase if needed.
- Writing records with setValues fails: setValues needs arrays, so convert back with records.map(rec => headers.map(h => rec[h])).
- Object.keys order is not what you expected: integer-like keys come first in ascending order, then string keys in insertion order.
- JSON.stringify of a record shows dates as strings: that is normal for logging; the object still holds Date objects.
Practice Objects: keys, values and entries
These drills check your answer on live data, free, no account needed.
- Group by a fieldReturn an object that maps each value of `item[key]` to the array of items with that value, in their original order. Values become object keys, so the number 2 becomes the key `"2"`. Keys are case-sensitive: `"Paid"` and `"paid"` are different groups.
- Count by a fieldReturn an object that maps each value of `item[key]` to how many items have it. Skip items where the field is missing or `undefined`.
- Pivot rows into a lookupTurn flat rows into a two-level lookup: `result[row[rowKey]][row[colKey]]` is the sum of `row[valueKey]` over every row with that pair. Pairs that never appear are absent. A sum of 0 is still kept.
Questions
Object or Map for lookups?
Object works fine for string keys; Map keeps any key type and insertion order and is slightly cleaner for large lookups: new Map(rows.map(r => [r[0], r])).
How do I copy an object without changing the original?
Use the spread operator for a shallow copy: const copy = {...rec, Status: "Closed"} leaves rec unchanged.
Related
- map, filter and reduceUse map, filter and reduce on Google Sheets data in Apps Script: transform rows, keep rows that match a condition, sum a column, chain them, write back.
- JSON.parse and JSON.stringifyUse JSON.parse and JSON.stringify in Google Apps Script: turn an API response into objects, write nested fields to a sheet, store objects as properties.
- getRange and getValuesRead Google Sheets data with Apps Script: getRange by A1 notation or row and column numbers, then getValue for one cell or getValues for a 2D array of rows.
- Deploy as a web appDeploy a Google Apps Script as a web app: write doGet and doPost, return HTML or JSON, read query and POST parameters, set who runs it and who can access it.