{"id":13433204,"url":"https://github.com/jc324x/google-apps-script-cheat-sheet","last_synced_at":"2025-03-17T10:33:42.165Z","repository":{"id":46045075,"uuid":"68617945","full_name":"jc324x/google-apps-script-cheat-sheet","owner":"jc324x","description":"🚧 Big changes coming! \"auto\" branch is the future of the project","archived":false,"fork":false,"pushed_at":"2018-12-27T02:52:57.000Z","size":1129,"stargazers_count":346,"open_issues_count":0,"forks_count":66,"subscribers_count":22,"default_branch":"master","last_synced_at":"2024-05-21T01:57:05.794Z","etag":null,"topics":["google-apps-script","javascript"],"latest_commit_sha":null,"homepage":"https://goo.gl/Ke5BoF","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jc324x.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-19T15:15:13.000Z","updated_at":"2024-05-21T01:57:05.795Z","dependencies_parsed_at":"2022-07-21T09:19:52.070Z","dependency_job_id":null,"html_url":"https://github.com/jc324x/google-apps-script-cheat-sheet","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jc324x%2Fgoogle-apps-script-cheat-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jc324x%2Fgoogle-apps-script-cheat-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jc324x%2Fgoogle-apps-script-cheat-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jc324x%2Fgoogle-apps-script-cheat-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jc324x","download_url":"https://codeload.github.com/jc324x/google-apps-script-cheat-sheet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221675301,"owners_count":16861860,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-apps-script","javascript"],"created_at":"2024-07-31T02:01:22.425Z","updated_at":"2024-10-27T12:32:25.590Z","avatar_url":"https://github.com/jc324x.png","language":"JavaScript","readme":"# Google Apps Script Cheat Sheet #\n\n[General](#general-1)\n=====\n* [Array](#array)\n  * [Check for a Value](#check-for-a-value)\n  * [Remove Duplicates](#remove-duplicates)\n  * [Remove Empty Elements](#remove-empty-elements)\n  * [Get Count of Values](#get-count-of-values)\n  * [Intersect of Two Arrays](#intersect-of-two-arrays)\n  * [Compare Two Arrays](#compare-two-arrays)\n  * [Array as Delimited String](#array-as-delimited-string)\n  * [Array as Modified Delimited String](#array-as-modified-delimited-string)\n* [Two-Dimensional Array](#two-dimensional-array)\n  * [Flatten Two-Dimensional Array](#flatten-two-dimensional-array)\n* [Array of Objects](#array-of-objects)\n  * [Sort by Property or Properties](#sort-by-property-or-properties)\n  * [Find Object With Unique Property Value](#find-object-with-unique-property-value)\n  * [Find Earliest or Latest Object by Timestamp](#find-earliest-or-lastest-object-by-timestamp)\n  * [Filter by Property Value or Values](#filter-by-property-value-or-values)\n  * [Unify Properties for Array of Objects](#unify-properties-for-array-of-objects)\n* [Object](#object)\n  * [Array of Matching Property Values](#array-of-matching-property-values--return-array)\n  * [Merge Objects](#merge-objects--return-object)\n* [Dates and Times](#dates-and-times)\n  * [Formatted Timestamps](#formatted-timestamps--return-string)\n  * [Date Object from String](#date-object-from-string--return-date)\n  * [Match a Date to a Range](#match-a-date-to-a-range--return-integer)\n\n[Drive](#drive-1)\n=====\n* [Folders](#folders)\n  * [Create or Verify Folder Path](#create-or-verify-folder-path)\n  * [Last Folder in Folder Path](#last-folder-in-folder-path)\n  * [Array of All Folders](#array-of-all-folders)\n    * [All Folders in a Folder](#all-folders-in-a-folder)\n    * [All Folders at Root](#all-folders-at-root)\n    * [All Folders in Drive](#all-folders-in-drive)\n  * [Array of All Folder Names](#array-of-all-folder-names)\n  * [Find a Folder](#find-a-folder)\n    * [Find a Folder in a Folder](#find-a-folder)\n    * [Find a Folder at Root](#find-a-folder-at-root)\n    * [Find a Folder in Drive](#find-a-folder-in-drive)\n    * [Find a File at Path](#find-a-file-at-path)\n  * [Create or Verify Folders](#create-or-verify-folders)\n    * [Create or Verify Folders in a Folder](#create-or-verify-folders-in-a-folder)\n    * [Create or Verify Folders at Root](#create-or-verify-folders-at-root)\n* [Files](#files)\n  * [Array of All Files](#array-of-all-files--return-array-files)\n    * [All Files in a Folder](#all-files-in-a-folder)\n    * [All Files at Root](#all-files-at-root)\n    * [All Files in Drive](#all-files-in-drive)\n  * [Array of All File Names](#array-of-all-file-names--return-array-strings)\n  * [Find a File](#find-a-file--return-file)\n    * [Find a File in a Folder](#find-a-file-in-a-folder)\n    * [Find a File at Root](#find-a-file-at-root)\n    * [Find a File in Drive](#find-a-file-in-drive)\n  * [Copy a File to a Folder](#copy-a-file-to-a-folder--return-file)\n  * [Move a File to a Folder](#move-a-file-to-a-folder--return-file)\n* [Files and Folders](#files-and-folders)\n  * [Rename a File or Folder](#rename-a-file-or-folder--return-file-or-folder)\n  * [Parent Folder of a File or Folder](#parent-folder-of-a-file-or-folder--return-file-or-folder)\n\n[JSON](#json-1)\n=====\n  * [Import JSON](#import-json)\n    * [Object From URL](#object-from-url)\n    * [Object From File](#object-from-file)\n    * [Object From URL or File](#object-from-url-or-file)\n\n[Sheets](#sheets-1)\n=====\n* [Managing Spreadsheet Files](#managing-spreadsheet-files)\n  * [Create or Verify Spreadsheet](#create-or-verify-spreadsheet)\n    * [Create or Verify Spreadsheet in a Folder](#create-or-verify-spreadsheet-in-a-folder)\n    * [Create or Verify Spreadsheet at Root](#create-or-verify-spreadsheet-at-root)\n  * [Id of Active Spreadsheet](#id-of-active-spreadsheet)\n  * [Open File as Spreadsheet](#open-file-as-spreadsheet)\n* [Utility Functions for Sheets](#utility-functions-for-sheets)\n  * [Convert Column Number to a Letter](#convert-column-number-to-a-letter)\n  * [Convert Column Letter to a Number](#convert-column-letter-to-a-number)\n  * [Replicating Import Range](#replicating-import-range)\n  * [Evaluating True and False](#evaluating-true-and-false)\n  * [Array of Sheet Names](#array-of-sheet-names)\n* [Object](#object-1)\n  * [Object From Range](#object-from-range)\n* [Array of Objects](#array-of-objects-1)\n  * [Utility Functions for Array of Objects](#utility-functions-for-array-of-objects)\n    * [Header Values](#header-values)\n    * [Values By Row](#values-by-row)\n    * [Header Range](#header-range)\n    * [Value Range](#value-range)\n  * [Array of Objects from Sheet](#array-of-objects-from-sheet)\n  * [Array of Objects from Range](#array-of-objects-from-range)\n* [Array](#array-1)\n  * [Array of Values for Column](#array-of-values-for-column)\n    * [For Header Value](#for-header-value)\n    * [For Column Number](#for-column-number)\n    * [For Range Object](#for-range-object)\n\n[Docs](#docs-1)\n=====\n* [Managing Document Files](#managing-document-files)\n  * [Create or Verify Document](#create-or-verify-document)\n    * [Create or Verify Document in a Folder](#create-or-verify-document-in-a-folder)\n    * [Create or Verify Document at Root](#create-or-verify-document-at-root)\n  * [Id of Active Document](#id-of-active-document)\n  * [Open File as Document](#open-file-as-document)\n* [Utility Functions for Docs](#utility-functions-for-docs)\n  * [Access Document Body](#access-document-body)\n  * [Clear Document Body](#clear-document-body)\n\n[Merges](#merges-1)\n=====\n* [Sheets and Docs](#sheets-and-docs)\n  * [String from Object Properties](#string-from-object-properties)\n  * [Replace Object Properties](#replace-object-properties)\n    * [Replace Object Properties in Document](#replace-object-properties-in-document)\n    * [Replace Object Properties in Spreadsheet](#replace-object-properties-in-spreadsheet)\n    * [Replace Object Properties in Sheet](#replace-object-properties-in-sheet)\n  * [Copy Template for Item in Array of Objects and Replace Object Properties](#copy-template-for-item-in-array-of-objects-and-replace-object-properties)\n    * [Copy Document Template and Replace Object Properties](#copy-document-template-and-replace-object-properties)\n    * [Copy Spreadsheet Template and Replace Object Properties](#copy-spreadsheet-template-and-replace-object-properties)\n  * [Create Bulleted List from Array of Objects](#create-bulleted-list-in-document-for-array-of-objects)\n    * [Single Division List](#single-division-list)\n    * [Multi Division List](#multi-division-list)\n\n[Gmail](#gmail)\n=====\n* [Mail Merge](#mail-merge)\n  * [Append Subject and Body Properties for Object in Array of Objects ](#append-subject-and-body-properties-for-object-in-array-of-objects)\n  * [Run Mail Merge for Array of Objects](#run-mail-merge-for-array-of-objects)\n\n## General ##\n\n### Array ###\n\n#### Check for a Value ####\n\n```javascript\n/**\n * Returns true if the value is in the array.\n *\n * @param {Array} arr\n * @param {*} val\n * @returns {boolean}\n */\n\nfunction checkValIn(arr, val) { \n  return arr.indexOf(val) \u003e -1; \n}\n\nvar arr_cvi = [1, 2, 3, 4];\nLogger.log(checkValIn(arr_cvi, 5)); // false\n```\n\n#### Remove Duplicates ####\n\n```javascript\n/**\n * Returns an array with no duplicate values.\n *\n * @param {Array} arr \n * @returns {Array}\n */\n\nfunction rmDuplicatesFrom(arr) {\n  var check  = {};\n  var result = [];\n  var j = 0;\n  for(var i = 0; i \u003c arr.length; i++) {\n    var item = arr[i];\n    if(check[item] !== 1) {\n      check[item] = 1;\n      result[j++] = item;\n    }\n  }\n  return result;\n}\n\nvar arr_rdf = [1, 2, 3, 1, 2, 3, 4,];\nLogger.log(rmDuplicatesFrom(arr_rdf)); // [1, 2, 3, 4]\n```\n\n#### Remove Empty Elements ####\n\n```javascript\n/**\n * Returns an array with no empty elements.\n *\n * @param {*} x\n * @returns {Array}\n */\n\nfunction rmEmptyEl(x) {\n  return (x !== (undefined || ''));\n}\n\nvar arr_rev = [\"a\",,\"b\",,,\"c\"];\nLogger.log(arr_rev.filter(rmEmptyEl)); // [\"a\", \"b\", \"c\"]\n```\n\n#### Get Count of Values #### \n\n```javascript\n/**\n * Returns an array of objects. Objects have two properties, count and value.\n *\n * @param {Array} arr\n * @property {value} a value found in the array\n * @property {count} count of the value in the array\n * @returns {Object[]}\n */\n\nfunction countOfValIn(arr) {\n  var result = [];\n  var copy = arr.slice(0);\n  for (var i = 0; i \u003c arr.length; i++) {\n    var myCount = 0;  \n    for (var w = 0; w \u003c copy.length; w++) {\n      if (arr[i] == copy[w]) {\n        myCount++;\n        delete copy[w];\n      }\n    }\n    if (myCount \u003e 0) {\n      var obj   = {};\n      obj.value = arr[i];\n      obj.count = myCount;\n      result.push(obj);\n    }\n  }\n  return result;\n}\n\nvar arr_covi  = [\"a\", \"b\", \"c\", \"a\", \"b\", \"c\", \"a\"];\nLogger.log(countOfValIn(arr_covi)); // [{count=3.0, value=a}, {count=2.0, value=b}, {count=2.0, value=c}]\n```\n\n#### Intersect of Two Arrays #### \n\n```javascript\n/**\n * Returns an array of the elements in both arrays.\n *\n * @param {Array} arrA\n * @param {Array} arrB\n * @returns {Array}\n */\n\nfunction intersectOf(arrA, arrB) {\n  var a = 0;\n  var b = 0;\n  var result = [];\n  while( a \u003c arrA.length \u0026\u0026 b \u003c arrB.length ) {\n    if (arrA[a] \u003c arrB[b] ) { a++; }\n    else if (arrA[a] \u003e arrB[b] ) { b++; }\n    else {\n      result.push(arrA[a]);\n      a++;\n      b++;\n    }\n  }\n  return result;\n}\n\nvar arrA_io = [1, 2, 3];\nvar arrB_io = [3, 4, 5];\nLogger.log(intersectOf(arrA_io, arrB_io)); // [3]\n```\n\n#### Compare Two Arrays #### \n\n```javascript\n/**\n * Returns true if both arrays have the same elements in the same order.\n *\n * @param {Array} arrA\n * @param {Array} arrB\n * @returns {boolean}\n */\n\nfunction compareArr(arrA, arrB) {\n  if(arrA.length !== arrB.length) return false;\n  for(var i = arrA.length; i--;) {\n    if(arrA[i] !== arrB[i]) return false;\n  }\n  return true;\n}\n\nvar arrA_ca = [1, 2, 3, 4, 5];\nvar arrB_ca = [1, 2, 3, 4, 5];\nvar arrC_ca = [\"a\", \"b\", \"c\", \"d\", \"e\"];\nLogger.log(compareArr(arrA_ca, arrB_ca)); // true\nLogger.log(compareArr(arrA_ca, arrC_ca)); // false\n```\n\n#### Array as Delimited String #### \n\n```javascript\n/**\n * Returns a string of array values. \n * Elements are separated by a delimiter and a space.\n *\n * @param {Array} arr\n * @param {string} delim\n * @returns {string}\n */\n\nfunction delimStrFromArr(arr, delim) {\n  var _arr = rmDuplicatesFrom(arr).sort();\n  var result  = \"\";\n  for (var i = 0; i \u003c _arr.length; i++) {\n    result += _arr[i] + delim + \" \";\n  }\n  result = result.slice(0, -2);\n  return result;\n}\n\nvar arr_da = [\"c@example.com\", \"b@example.com\", \"a@example.com\"];\nLogger.log(delimStrFromArr(arr_da, \",\")); // \"a@example.com, b@example.com, c@example.com\"\n```\n\n#### Array as Modified Delimited String #### \n\n```javascript\n/**\n * Returns a string of array values.\n * Elements are separated by a delimiter and a space, each followed by a modification.\n *\n * @param {Array} arr\n * @param {string} delim\n * @param {string} mod Modification to append to each item in the array.\n * @returns {string}\n */\n\nfunction delimStrFromArrMod(arr, delim, mod) {\n  var _arr = rmDuplicatesFrom(arr).sort();\n  var result  = \"\";\n  for (var i = 0; i \u003c _arr.length; i++) {\n    result += _arr[i] + mod + delim + \" \"; \n  }\n  result = result.slice(0, -2);\n  return result;\n}\n\nvar arr_clfd = [\"x\", \"z\", \"y\"];\nLogger.log(delimStrFromArrMod(arr_clfd, \",\", \"@example.com\")); // \"x@example.com, y@example.com, z@example.com\"\n```\n\n### Two-Dimensional Array ###\n\n#### Flatten Two-Dimensional Array #### \n\n```javascript\n/**\n * Returns an array containing all values in a two-dimensional array.\n *\n * @param {Array[]} twoDArr\n * @returns {Array} \n */\n\nfunction flattenTwoDArr(twoDArr) {\n  var result = twoDArr.reduce(function(a, b) {\n    return a.concat(b);\n  });\n  return result;\n}\n\nvar sheet_fma = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet1\");\nvar val_fma   = sheet_fma.getRange(\"G2:H5\").getValues();\nLogger.log(flattenTwoDArr(val_fma).sort()); // [1, 2, 3, 4, 5, 6, 7, 8]\n```\n\n### Array of Objects ###\n\n```javascript\nvar ex_arrObj = [\n{a: 1000, b: 1, c: 5}, \n{a: 10000, b: 2, c: 5000}, \n{a: 10, b: 2, c: 500},\n{a: 1, b: 1, c: 50}\n]\n```\n\n#### Sort by Property or Properties ####\n\n```javascript\n/**\n * Returns an array of objects sorted by a single property value.\n *\n * @param {string} prop\n * @returns {Object[]}\n */\n\nfunction dynSort(prop) {\n  var sortOrder = 1;\n  if(prop[0] === \"-\") {\n    sortOrder = -1;\n    prop = prop.substr(1);\n  }\n  return function (a,b) {\n    var result = (a[prop] \u003c b[prop]) ? -1 : (a[prop] \u003e b[prop]) ? 1 : 0;\n    return result * sortOrder;\n  };\n}\n\nLogger.log(ex_arrObj.sort(dynSort(\"a\"))); \n// [{a=1.0, b=1.0, c=50.0}, {a=10.0, b=2.0, c=500.0}, {a=1000.0, b=1.0, c=5.0}, {a=10000.0, b=2.0, c=5000.0}]\n\n/**\n * Returns an array of objects sorted by multiple property values.\n * @param {...string}\n * @returns {Object[]}\n */\n\nfunction dynSortM() {\n  var props = arguments;\n  return function (obj1, obj2) {\n    var i = 0, result = 0, numberOfProperties = props.length;\n    while(result === 0 \u0026\u0026 i \u003c numberOfProperties) {\n      result = dynSort(props[i])(obj1, obj2);\n      i++;\n    }\n    return result;\n  };\n}\n\nLogger.log(ex_/rrObj.sort(dynSortM(\"b\", \"c\"))); \n// [{a=1000.0, b=1.0, c=5.0}, {a=1.0, b=1.0, c=50.0}, {a=10.0, b=2.0, c=500.0}, {a=10000.0, b=2.0, c=5000.0}]\n```\n\n#### Find Object With Unique Property Value #### \n\n```javascript\n/**\n * Returns the first object in an array of objects with the key value pair.\n *\n * @param {Object[]} arrObj\n * @param {string} pQuery\n * @param {string} val\n * @returns {Object}\n */\n\nfunction findObjIn(arrObj, pQuery, val) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj = arrObj[i];\n    for (var prop in obj) {\n      if (obj.hasOwnProperty(pQuery) \u0026\u0026 prop == pQuery \u0026\u0026 obj[prop] == val) {\n        return obj;\n      }\n    }\n  }\n}\n\nLogger.log(findObjIn(ex_arrObj,\"a\",1000)); // {a=1000.0, b=1.0, c=5.0}\n\n/**\n * Returns a value from the first matching object in the array.\n *\n * @param {Object[]} arrObj\n * @param {string} pQuery\n * @param {string} val\n * @param {string} pReturn\n * @returns {*}\n */\n\nfunction findObjValIn(arrObj, pQuery, val, pReturn) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj = arrObj[i];\n    for (var prop in obj) {\n      if (obj.hasOwnProperty(pQuery) \u0026\u0026 prop == pQuery \u0026\u0026 obj[prop] == val) {\n        return obj[pReturn];\n      }\n    }\n  }\n}\n\nLogger.log(findObjValIn(ex_arrObj, \"c\", 500, \"a\")); // 10\n```\n\n#### Find Earliest or Lastest Object by Timestamp #### \n\n```javascript\n/**\n * Returns the object with the oldest Timestamp value.\n *\n * @param {Object[]} arrObj\n * @returns {Object}\n */\n\nfunction earliestTS(arrObj){\n  if (arrObj.length \u003e= 2) {\n    var sorted = arrObj.sort(function(a,b){\n      return new Date(a.Timestamp) - new Date(b.Timestamp);\n    });\n    return sorted[0];\n  } else {\n    return arrObj[0];\n  }\n}\n\nvar sheet_fe  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet1\");\nvar arrObj_fe = arrObjFromRange(sheet_fe, \"J1:K4\");\nLogger.log(earliestTS(arrObj_fe)); // {Timestamp=Sun Feb 19 19:43:40 GMT-06:00 2017, Multiple Choice=A}\n\n/**\n * Returns the object with the latest Timestamp value.\n *\n * @param {Object[]} arrObj\n * @returns {Object}\n */\n\nfunction latestTS(arrObj) {\n  if (arrObj.length \u003e= 2) {\n    var sorted = arrObj.sort(function(a,b){\n      return new Date(b.Timestamp) - new Date(a.Timestamp);\n    });\n    return sorted[0];\n  } else {\n    return arrObj[0];\n  }\n} \n\nvar sheet_le  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet1\");\nvar arrObj_le = arrObjFromRange(sheet_le, \"J1:K4\");\nLogger.log(latestTS(arrObj_le)); // {Timestamp=Wed Feb 22 19:45:07 GMT-06:00 2017, Multiple Choice=C}\n```\n\n#### Filter by Property Value or Values #### \n\n```javascript\n/**\n * Returns an array of objects containing matching objects.\n *\n * @param {Object} arrObj\n * @param {string} pQuery\n * @param {string[]} arrVal\n * @returns {Object[]}\n */\n\nfunction filterObjIn(arrObj, pQuery, arrVal) {\n  var result = [];\n  for (var i = 0; i \u003c arrVal.length; i++) {\n    var val = arrVal[i]; \n    for (var j = 0; j \u003c arrObj.length; j++) {\n      if (arrObj[j][pQuery] == val) result.push(arrObj[j]);\n    }\n  } \n  return result;\n}\n\nLogger.log(filterObjIn(ex_arrObj, \"a\", [10])); // [{a=10.0, b=2.0, c=500.0}]\nLogger.log(filterObjIn(ex_arrObj, \"c\", [5, 500])); // [{a=1000.0, b=1.0, c=5.0}, {a=10.0, b=2.0, c=500.0}]\n```\n\n#### Unify Properties for Array of Objects ####\n\n```javascript\n/**\n * Returns an array of objects, with an additional property value added to each matching object.\n *\n * @param {Object[]} arrObj\n * @param {string[]} arrProp\n * @param {string} newProp \n * @returns {Object[]}\n */\n\nfunction unifyPropForArrObj(arrObj, arrProp, newProp){\n  for (var i = 0; i \u003c arrObj.length; i++){\n    var obj = arrObj[i];\n    for (var h = 0; h \u003c arrProp.length; h++) {\n      for (var prop in obj) {\n        if (obj.hasOwnProperty(prop) \u0026\u0026 prop == arrProp[h] \u0026\u0026 obj[prop] !== \"\"){\n              obj[newProp] = obj[prop];\n        }\n      }\n    }\n  }\n  return arrObj;\n}\n\nvar arrObj_upfao  = [\n  {x: 123},\n  {y: 234},\n  {z: 345},\n];\n\nLogger.log(unifyPropForArrObj(arrObj_upfao, [\"x\",\"y\",\"z\"], \"new\"));\n// [{new=123.0, x=123.0}, {new=234.0, y=234.0}, {new=345.0, z=345.0}]\n```\n\n### Object ###\n\n#### Array of Matching Property Values #### \n\n```javascript\n/**\n * Returns an array of matching properties. \n *\n * @requires intersectOf() \n * @param {Object} obj\n * @param {string[]} props\n * @returns {Array}\n */\n\nfunction filterValIn(obj, props) {\n  var result = [];\n  var keys   = intersectOf(Object.keys(obj), props);\n  for (var i = 0; i \u003c keys.length; i++) {\n    var key = keys[i];\n    for (var prop in obj) {\n      if (obj.hasOwnProperty(key)) {\n        result.push(obj[key]);\n        break;\n      }\n    }\n  }\n  return result;\n}\n\nvar obj_fvi = { \n a: 1, \n b: 2, \n c: 3\n};\n\nvar arr_fvi = [\"a\", \"b\", \"d\"];\nLogger.log(filterValIn(obj_fvi, arr_fvi)); // [1, 2]\n```\n\n#### Merge Objects #### \n\n```javascript\n/**\n * Returns an object with the values of the argument objects.\n * If multiple objects have the same property value, the last value set is retained. \n * @param {...Object}\n * @returns {Object}\n */\n\nfunction mergeObjs() {\n  var obj = arguments[0];\n  for (i = 1; i \u003c arguments.length; i++) {\n    var src = arguments[i]; \n    for (var key in src) {\n      if (src.hasOwnProperty(key)) obj[key] = src[key];\n    }\n  } \n  return obj;\n} \n\nvar objA_mo = {\n a: 1, \n b: 2, \n c: 3\n}; \n\nvar objB_mo = {\n c: 4,\n d: 5, \n e: 6, \n f: 7\n}; \n\nLogger.log(mergeObjs(objA_mo, objB_mo)); // {a=1.0, b=2.0, c=4.0, d=5.0, e=6.0, f=7.0}\n```\n\n### Dates and Times ###\n\n#### Formatted Timestamps ####\n\n```javascript\n/**\n * Returns a string of today's date formatted \"month-day-year\".\n *\n * @returns {string}\n */\n\nfunction fmatD() {\n  var n = new Date();\n  var d = [ n.getMonth() + 1, n.getDate(), n.getYear() ];\n    return d.join(\"-\");\n}\n\nLogger.log(fmatD()); // \"4-24-2017\"\n\n/**\n * Returns a string of the current time formatted \"hour:minute:second\".\n *\n * @returns {string}\n */\n\nfunction fmat24T(){\n  var n  = new Date();\n  var t = [ n.getHours(), n.getMinutes(), n.getSeconds() ];\n    for ( var i = 1; i \u003c 3; i++ ) {\n      if ( t[i] \u003c 10 ) {\n        t[i] = \"0\" + t[i];\n      }\n      return t.join(\":\");\n    }\n}\n\nLogger.log(fmat24T()); // \"20:43:40\"\n\n/**\n * Returns a string of today's date and the current time formatted \"month-day-year hour:minute:second AM/PM\"\n *\n * @returns {string}\n */\n\nfunction fmat12DT() {\n  var n = new Date();\n  var d = [ n.getMonth() + 1, n.getDate(), n.getYear() ];\n    var t = [ n.getHours(), n.getMinutes(), n.getSeconds() ];\n    var s = ( t[0] \u003c 12 ) ? \"AM\" : \"PM\";\n  t[0]  = ( t[0] \u003c= 12 ) ? t[0] : t[0] - 12;\n  for ( var i = 1; i \u003c 3; i++ ) {\n    if ( t[i] \u003c 10 ) {\n      t[i] = \"0\" + t[i];\n    }\n  }\n  return d.join(\"/\") + \" \" + t.join(\":\") + \" \" + s;\n}\n\nLogger.log(fmat12DT()); // \"4-24-2017 8:43:40 PM\"\n```\n\n#### Date Object from String ####\n\n```javascript\n/**\n * Returns a new date object from a string formatted year-month-date. \n *\n * @param {string} str\n * @returns {Date}\n */\n\nfunction dateObjectFromString(str) {\n  var split  = str.split(\"-\");\n  var months = [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\",\n    \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"\n    ];\n  return new Date (months[(split[1] - 1)] + \" \" + split[2] + \", \" + split[0]);\n}\n\nLogger.log(dateObjectFromString(\"2017-04-24\")); // Mon Apr 24 00:00:00 GMT-05:00 2017\n```\n\n#### Match a Date to a Range ####\n\n```javascript\n/**\n * Returns a value associated with a date range.\n *\n * @param {Object[]} arrObj\n * @param {string=new Date()} optDate - Date to match.\n * @namespace\n * @property {string} start           - Starting date.\n * @property {string} end             - Ending date.\n * @property {*} value                - The value to return for a matching date.\n * @returns {*}\n */\n\nfunction matchDateRange(arrObj, optDate) {\n  var date = new Date();\n  if (optDate !== undefined) {\n    date = new Date(optDate);\n  }\n  for (i = 0; i \u003c arrObj.length; i++) {\n    var start = new Date(arrObj[i].start);\n    var end   = new Date(arrObj[i].end);\n    if (date \u003e= start \u0026\u0026 date \u003c= end ) {\n      return arrObj[i].value;\n    }\n  }\n}\n\nvar quarterDates = [\n  {start: \"08/01/2016\", end: \"10/28/2016\", value: 1},\n  {start: \"11/02/2016\", end: \"01/09/2017\", value: 2},\n  {start: \"01/15/2017\", end: \"03/19/2017\", value: 3},\n  {start: \"03/21/2017\", end: \"06/15/2017\", value: 4},\n  {start: \"06/16/2017\", end: \"07/30/2017\", value: \"summer vacation\"}\n];\n\nLogger.log(matchDateRange(quarterDates)); // \"summer vacation\" (06/25/2017)\nLogger.log(matchDateRange(quarterDates, \"08/02/2016\")); // 1 \n```\n\n## Drive ##\n\n### Folders ###\n\n#### Create or Verify Folder Path ####\n\n```javascript\n// -- Create or Verify Folder Path\n\n/**\n * Returns a folder at the end of a folder path.\n * The folder is created if it does not exist already.\n *\n * @param {string} path\n * @returns {Folder}\n */\n\nfunction createVerifyPath(path) {\n  var split = path.split('/');\n  var fldr;\n  for (i = 0; i \u003c split.length; i++) {\n    var fi = DriveApp.getRootFolder().getFoldersByName(split[i]);\n    if (i === 0) {\n      if(!(fi.hasNext())) {\n        DriveApp.createFolder(split[i]);\n        fi = DriveApp.getFoldersByName(split[i]);\n      } \n      fldr = fi.next();\n    } else if (i \u003e= 1) {\n      fi = fldr.getFoldersByName(split[i]);\n      if(!(fi.hasNext())) {\n        fldr.createFolder(split[i]);\n        fi = DriveApp.getFoldersByName(split[i]);\n      } \n      fldr = fi.next();\n    }\n  } \n  return fldr;\n}\n\nLogger.log(createVerifyPath(\"google-apps-script-cheat-sheet-demo/folders/A/B/C\")); // C\n```\n\n#### Last Folder in Folder Path ####\n\n```javascript\n/**\n * Returns the last folder in a folder path.\n *\n * @param path\n * @returns {Folder}\n */\n\nfunction lastFolderIn(path) {\n  var fi;\n  var split = path.split('/');\n  var fldr;\n  for (i = 0; i \u003c split.length; i++) {\n    if (i === 0) {\n      fi = DriveApp.getRootFolder().getFoldersByName(split[i]);\n      if (fi.hasNext()) {\n        fldr = fi.next();\n      } \n    } else if (i \u003e= 1) {\n        fi = fldr.getFoldersByName(split[i]);\n        if (fi.hasNext()) {\n          fldr = fi.next();\n        } \n    }\n  } \n  return fldr;\n}\n\n// Logger.log(lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders/A/B\")); // B\n// Logger.log(lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders/A/B/C/D/E/F/G\")); // C\n```\n\n#### Array of All Folders ####\n\n##### All Folders in a Folder #####\n\n```javascript\n/**\n * Returns an array of all folders in a folder.\n *\n * @param {Folder} fldr\n * @returns {Folder[]}\n */\n\nfunction foldersIn(fldr) {\n  var fi  = fldr.getFolders();\n  var arr = [];\n  while (fi.hasNext()) {\n    var _fldr = fi.next();\n    arr.push(_fldr);\n  } \n  return arr;\n}\n\nLogger.log(foldersIn(lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders/\"))); // [A]\n```\n\n##### All Folders at Root #####\n\n```javascript\n/**\n * Returns an array of all folders in the root of the user's Drive.\n *\n * @returns {Folder[]}\n */\n\nfunction rootFolders() {\n  var rf  = DriveApp.getRootFolder();\n  var fi  = rf.getFolders();\n  var arr = [];\n  while (fi.hasNext()) {\n    var fldr = fi.next();\n    arr.push(fldr);\n  } \n  return arr;\n}\n\nLogger.log(rootFolders());\n```\n\n##### All Folders in Drive #####\n\n```javascript\n/**\n * Returns an array of all folders in the user's Drive.\n *\n * @returns {Folder[]}\n */\n\nfunction allFolders() {\n  var fi  = DriveApp.getFolders();\n  var arr = [];\n  while (fi.hasNext()) {\n    var fldr = fi.next();\n    arr.push(fldr);\n  } \n  return arr;\n}\n\nLogger.log(allFolders());\n```\n\n#### Array of All Folder Names ####\n\n```javascript\n/**\n * Returns an array of folder names.\n *\n * @param {Folders[]}\n * @returns {string[]}\n */\n\nfunction folderNames(fldrs) {\n  var arr = [];\n  for (var i = 0; i \u003c fldrs.length; i++) {\n    var name = fldrs[i].getName();\n    arr.push(name);\n  }\n  return arr;\n}\n\nvar arr_fn  = foldersIn(lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders/A/B\"));\nLogger.log(folderNames(arr_fn)); // [C]\n```\n\n#### Find a Folder ####\n\n##### Find a Folder in a Folder #####\n\n```javascript\n/**\n * Returns a folder.\n *\n * @requires foldersIn() \n * @requires folderNames() \n * @requires checkValIn()\n * @param {Folder} fldr\n * @param {string} name\n * @returns {Folder}\n */\n\nfunction findFolderIn(fldr, name) {\n  var fldrs = foldersIn(fldr);\n  var names = folderNames(fldrs);\n  if (checkValIn(names, name)) {\n    var _fldr = fldr.getFoldersByName(name).next();\n    return _fldr;\n  }\n}\n\nvar fldr_ffi = lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders\");\nLogger.log(findFolderIn(fldr_ffi, \"A\")); // A\n```\n\n##### Find a Folder at Root #####\n\n```javascript\n/**\n * Returns a folder at the root of the user's Drive.\n *\n * @requires rootFolders()\n * @requires folderNames()\n * @requires checkValIn()\n * @param {string} name\n * @returns {Folder}\n */\n\nfunction findFolderAtRoot(name) {\n  var rf    = DriveApp.getRootFolder();\n  var fldrs = rootFolders();\n  var names = folderNames(fldrs);\n  if (checkValIn(names, name)) {\n    var fldr = rf.getFoldersByName(name).next();\n    return fldr;\n  }\n}\n\nLogger.log(findFolderAtRoot(\"google-apps-script-cheat-sheet-demo\")); // google-apps-script-cheat-sheet-demo\n```\n\n##### Find a Folder in Drive #####\n\n```javascript\n/**\n * Returns the first matching folder in Drive.\n *\n * @param {string} name\n * @returns {Folder}\n */\n\nfunction findFolderInDrive(name) {\n  var fi = DriveApp.getFoldersByName(name);\n  while (fi.hasNext()){\n    var fldr = fi.next();\n    return fldr;\n  }\n}\n\nLogger.log(findFolderInDrive(\"folders\")); // folders\n```\n\n#### Create or Verify Folders ####\n\n##### Create or Verify Folders in a Folder #####\n\n```javascript\n/**\n * Returns a folder. \n * Creates folders within a folder if they don't already exist.\n *\n * @requires foldersIn()\n * @requires folderNames()\n * @requires checkValIn()\n * @param {Folder} fldr\n * @param {string[]} names\n * @returns {Folder}\n */\n\nfunction createVerifyFoldersIn(fldr, names) {\n  var fldrs  = foldersIn(fldr);\n  var _names = folderNames(fldrs);\n  for (i = 0; i \u003c names.length; i++) {\n    if (!(checkValIn(_names, names[i]))) {\n      fldr.createFolder(names[i]);\n    }\n  }\n  return fldr;\n}\n\nvar fldr_cvfi = lastFolderIn(\"google-apps-script-cheat-sheet-demo/folders\");\nLogger.log(createVerifyFoldersIn(fldr_cvfi, [\"X\", \"Y\", \"Z\"])); // folders\nLogger.log(foldersIn(fldr_cvfi)); // [A,X,Y,Z]\n```\n\n##### Create or Verify Folders at Root #####\n\n```javascipt\n/**\n * Returns the root folder.\n * Creates folders at root if they don't exist already.\n *\n * @param {string[]} names\n * @returns {Folder}\n */\n\nfunction createVerifyFoldersAtRoot(names) {\n  var rfs    = rootFolders();\n  var _names = folderNames(rfs);\n  for (i=0; i \u003c names.length; i++) {\n    if (!(checkValIn(_names, names[i]))) {\n      DriveApp.createFolder(names[i]);\n    }\n  } \n  return DriveApp.getRootFolder();\n}\n```\n\n### Files ###\n\n#### Array of All Files ####\n\n##### All Files in a Folder ##### \n\n```javascript\n/**\n * Returns an array of files found at the top level of a folder.\n *\n * @param {Folder} fldr\n * @returns {File[]}\n */\n\nfunction filesIn(fldr) {\n  var fi  = fldr.getFiles();\n  var arr = [];\n  while (fi.hasNext()) {\n    var file = fi.next();\n    arr.push(file);\n  } \n  return arr;\n}\n\nvar fldr_fin = lastFolderIn(\"google-apps-script-cheat-sheet-demo/files\");\nLogger.log(filesIn(fldr_fin)); // [example-file]\n```\n\n##### All Files at Root ##### \n\n```javascript\n/**\n * Returns an array of all files at the root of a user's Drive.\n *\n * @returns {File[]}\n */\n\nfunction rootFiles() {\n  var rf = DriveApp.getRootFolder();\n  var fi = rf.getFiles();\n  var arr = [];\n  while (fi.hasNext()) {\n    var file = fi.next();\n    arr.push(file);\n  } \n  return arr;\n}\n\nLogger.log(rootFiles());\n```\n\n##### All Files in Drive ##### \n\n```javascript\n/**\n * Returns an array of all files in the user's Drive.\n *\n * @returns {File[]}\n */\n\nfunction allFiles() {\n  var fi = DriveApp.getFiles();\n  var arr  = [];\n  while (fi.hasNext()) {\n    var file = fi.next();\n    arr.push(file);\n  } \n  return arr;\n}\n\nLogger.log(allFiles());\n```\n\n#### Array of All File Names ####\n\n```javascript\n/**\n *  Returns an array of file names.\n *\n * @param {File[]} files\n * @returns {string[]}\n */\n\nfunction fileNames(files) {\n  var arr = [];\n  for (var i = 0; i \u003c files.length; i++) {\n    var name = files[i].getName();\n    arr.push(name);\n  }\n  return arr;\n}\n\nvar fldr_fnam = lastFolderIn(\"google-apps-script-cheat-sheet-demo/files\");\nvar arr_fnam  = filesIn(fldr_fnam);\nLogger.log(fileNames(arr_fnam)); // [example-file]\n```\n\n#### Find a File ####\n\n##### Find a File in a Folder #####\n\n```javascript\n/**\n * Returns a file found at the top level of a folder. \n *\n * @requires filesIn()\n * @requires fileNames()\n * @requires checkValIn()\n * @param {Folder} fldr\n * @param {string} name\n * @returns {File}\n */\n\nfunction findFileIn(fldr, name) {\n  var files = filesIn(fldr);\n  var names = fileNames(files);\n  if (checkValIn(names, name)) {\n    var file = fldr.getFilesByName(name).next();\n    return file;\n  }\n}\n\nvar fldr_ffi = lastFolderIn(\"google-apps-script-cheat-sheet-demo/files\");\nLogger.log(findFileIn(fldr_ffi, \"example-file\")); // example-file\n```\n\n##### Find a File at Root #####\n\n```javascript\n/**\n * Returns a file found at the root of a user's Drive.\n *\n * @requires rootFiles()\n * @requires fileNames()\n * @requires checkValIn()\n * @param {string} name\n * @returns {File}\n */\n\nfunction findFileAtRoot(name) {\n  var rf    = DriveApp.getRootFolder();\n  var files = rootFiles();\n  var names = fileNames(files);\n  if (checkValIn(names, name)) {\n    var file = rf.getFilesByName(name).next();\n    return file;\n  }\n}\n```\n\n##### Find a File in Drive #####\n\n```javascript\n/**\n * Returns the first matching file found in the user's Drive.\n *\n * @param {string} name\n * @returns {File}\n */\n\nfunction findFileInDrive(name) {\n  var fi = DriveApp.getFilesByName(name);\n  while (fi.hasNext()){\n    var file = fi.next();\n    return file;\n  }\n}\n\nLogger.log(findFileInDrive(\"example-file\")); // example-file\n```\n\n#### Find at File at Path ####\n\n```javascript\n\n/**\n * Returns the file found at the end of a path.\n *\n * @param {string} path\n * @returns {File}\n */\n\nfunction findFileAtPath(path) {\n  var fi;\n  var split = path.split('/');\n  var file  = split[split.length -1];\n  var fldr;\n  for (i = 0; i \u003c split.length - 1; i++) {\n    if (i === 0) {\n      fi = DriveApp.getRootFolder().getFoldersByName(split[i]);\n      if (fi.hasNext()) {\n        fldr = fi.next();\n      } else { \n        return null;\n      }\n    } else if (i \u003e= 1) {\n        fi = fldr.getFoldersByName(split[i]);\n        if (fi.hasNext()) {\n          fldr = fi.next();\n        } else { \n          return null;\n        }\n    }\n  } \n  return findFileIn(fldr, file);\n} \n\nLogger.log(findFileAtPath(\"google-apps-script-cheat-sheet-demo/files/example-file\"));\n```\n\n#### Copy a File to a Folder ####\n\n```javascript\n/**\n * Returns the copied file.\n *\n * @requires findFileIn()\n * @param {File} file\n * @param {Folder} fldr\n * @returns {File}\n */\n\nfunction copyFile(file, fldr) {\n  var name = file.getName();\n  var dest = findFileIn(fldr, name);\n  if (dest === undefined) file.makeCopy(name, fldr);\n  return findFileIn(fldr, name);\n}\n\nvar fldr_cf = createVerifyPath(\"google-apps-script-cheat-sheet-demo/files/copied\");\nvar file_cf = findFileInDrive(\"example-file\");\nLogger.log(copyFile(file_cf, fldr_cf)); // example-file\n```\n\n#### Move a File to a Folder ####\n\n```javascript\n/**\n * Returns the copied file from its new destination.\n *\n * @requires findFileIn()\n * @param {File} file\n * @param {Folder}  fldr\n * @returns {File}\n */\n\nfunction moveFile(file, fldr) {\n  var name = file.getName();\n  var dest = findFileIn(fldr, name);\n  if (dest === undefined) file.makeCopy(name, fldr);\n  var _file = findFileIn(fldr, name);\n  if (_file !== undefined) file.setTrashed(true);\n  return _file;\n}\n\nvar fldr_mf1 = lastFolderIn(\"google-apps-script-cheat-sheet-demo/files/copied\");\nvar file_mf  = findFileIn(fldr_mf1, \"example-file\");\nvar fldr_mf2 = createVerifyPath(\"google-apps-script-cheat-sheet-demo/files/moved\");\nLogger.log(moveFile(file_mf, fldr_mf2)); // example-file\n```\n\n### Files and Folders ###\n\n#### Rename a File or Folder ####\n\n```javascript\n/**\n * Returns a renamed file or a folder.\n *\n * @param {File || Folder} file_fldr\n * @param {string} name\n * @returns {File || Folder}\n */\n\nfunction renameFileFldr(file_fldr, name) {\n  file_fldr.setName(name);\n  return file_fldr;\n} \n\nvar fldr_rf = lastFolderIn(\"google-apps-script-cheat-sheet-demo/files/moved\");\nvar file_rf = findFileIn(fldr_rf, \"example-file\");\nLogger.log(renameFileFldr(file_rf, \"modified-example-file\")); // modified-example-file\n```\n\n#### Parent Folder of a File or Folder ####\n\n```javascript\n/**\n * Returns the parent folder or a file or a folder.\n *\n * @param {File || Folder} file_fldr\n * @returns {Folder}\n */\n\nfunction parentFolderOf(file_fldr) {\n  var fi = file_fldr.getParents();\n  return fi.next();\n}\n\nvar file_pfo = findFileInDrive(\"example-file\");\nLogger.log(parentFolderOf(file_pfo)); // files\n```\n\n## JSON ##  \n\n### Import JSON ###\n\n```javascript\nfunction jsonExFile() {\n  var fldr = createVerifyPath(\"google-apps-script-cheat-sheet-demo/json\");\n  var file = findFileIn(fldr, \"example-json\");\n  var json = jsonFromUrl(\"https://raw.githubusercontent.com/jcodesmn/google-apps-script-cheat-sheet/dev/example.json\");\n  var text = JSON.stringify(json);\n  if (!(file)){fldr.createFile(\"example-json\");}\n  file.setContent(text);\n  return findFileIn(fldr, \"example-json\");\n}\n\njsonExFile();\n```\n\n#### Object From URL #### \n\n```javascript\n/**\n * Returns an object from a URL.\n *\n * @param {string} url\n * @returns {Object}\n */\n\nfunction objFromUrl(url) {\n  var rsp  = UrlFetchApp.fetch(url);\n  var data = rsp.getContentText();\n  return JSON.parse(data);\n} \n\nvar obj_ofu = objFromUrl(\"https://raw.githubusercontent.com/jcodesmn/google-apps-script-cheat-sheet/dev/example.json\");\nLogger.log(JSON.stringify(obj_ofu));\n```\n\n#### Object From File #### \n\n```javascript\n/**\n * Returns an object from a file in Drive.\n *\n * @param {File} file\n * @returns {Object}\n */\n\nfunction objFromFile(file) {\n  var data = file.getBlob().getDataAsString();\n  return JSON.parse(data);\n} \n\nvar file_off = findFileAtPath(\"google-apps-script-cheat-sheet-demo/json/example-json\");\nvar obj_off  = objFromFile(file_off);\nLogger.log(JSON.stringify(obj_off));\n```\n\n#### Object From URL or File ####\n\n```javascript\n/**\n * Returns an object from a URL or from a file in Drive.\n *\n * @param {string || File} input\n * @returns {Object}\n */\n\nfunction objFromUrlOrFile(input) {\n  var regExp = new RegExp(\"^(http|https)://\");\n  var test   = regExp.test(input);\n  if (test) {\n    return objFromUrl(input);\n  } else {\n    var file = findFileAtPath(input); \n    return objFromFile(file);\n  }\n}\n\nLogger.log(JSON.stringify(objFromUrlOrFile(\"https://raw.githubusercontent.com/jcodesmn/google-apps-script-cheat-sheet/dev/example.json\")));\nLogger.log(JSON.stringify(objFromUrlOrFile(\"google-apps-script-cheat-sheet-demo/json/example-json\")));\n```\n\n## Sheets ##\n\n### Managing Spreadsheet Files ###\n\n#### Create or Verify Spreadsheet ####\n\n##### Create or Verify Spreadsheet in a Folder #####\n\n```javascript\n/**\n * Returns a spreadsheet. \n * This creates the spreadsheet if it does not already exist.\n *\n * @requires filesIn()\n * @requires fileNames()\n * @requires checkValIn\n * @requires moveFile()\n * @requires findFileIn()\n * @requires openFileAsSpreadsheet()\n * @param {Folder} fldr\n * @param {string} name\n * @returns {Spreadsheet}\n */\n\nfunction createVerifySSIn(fldr, name) {\n  var files = filesIn(fldr);\n  var names = fileNames(files);\n  if (!(checkValIn(names, name))) {\n    var ss   = SpreadsheetApp.create(name).getId();\n    var file = DriveApp.getFileById(ss);\n    moveFile(file, fldr);\n  }\n  return openFileAsSpreadsheet(findFileIn(fldr, name));\n}\n\nvar fldr_cvssi = createVerifyPath(\"google-apps-script-cheat-sheet-demo/sheets\");\nLogger.log(createVerifySSIn(fldr_cvssi, \"example-sheet\")); // example-sheet\n```\n\n##### Create or Verify Spreadsheet at Root #####\n\n```javascript\n/**\n * Returns a spreadsheet. \n * This creates the spreadsheet if it does not already exist.\n *\n * @requires rootFiles()\n * @requires fileNames()\n * @requires checkValIn() \n * @requires findFileAtRoot() \n * @requires openFileAsSpreadsheet() \n * @param {string} name\n * @returns {Spreadsheet}\n */\n\nfunction createVerifySSAtRoot(name) {\n  var files = rootFiles();\n  var names = fileNames(files);\n  if (!(checkValIn(names, name))) {\n    var ss = SpreadsheetApp.create(name);\n  }\n  return openFileAsSpreadsheet(findFileAtRoot(name));\n}\n```\n\n#### Id of Active Spreadsheet ####\n\n```javascript\n/**\n * Returns the Id of the active spreadsheet.\n *\n * @returns {string}\n */\n\nfunction ssId() {\n  var _id = SpreadsheetApp.getActiveSpreadsheet().getId();\n  return _id;\n}\n\nLogger.log(ssId());\n```\n\n#### Open File as Spreadsheet ####\n\n```javascipt\n/**\n * Returns a spreadsheet. \n *\n * @param {string} \n * @returns {Spreadsheet}\n */\n\nfunction openFileAsSpreadsheet(file) {\n  var _id = file.getId();\n  var _ss = SpreadsheetApp.openById(_id);\n  return _ss;\n} \n\nvar fldr_ofas = lastFolderIn(\"google-apps-script-cheat-sheet-demo/sheets\")\nvar file_ofas = findFileIn(fldr_ofas, \"example-sheet\");\nLogger.log(openFileAsSpreadsheet(file_ofas));\n```\n\n### Utility Functions for Sheets ###\n\n#### Convert Column Number to a Letter #### \n\n```javascript\n/**\n * Returns the column number as a alphabetical column value.\n * Columns are indexed from 1, not from 0.\n * \"CZ\" (104) is the highest supported value.\n *\n * @param {number} number\n * @returns {string}\n */\n\nfunction numCol(number) {\n  var num = number - 1, chr;\n  if (num \u003c= 25) {\n    chr = String.fromCharCode(97 + num).toUpperCase();\n    return chr;\n  } else if (num \u003e= 26 \u0026\u0026 num \u003c= 51) {\n    num -= 26;\n    chr = String.fromCharCode(97 + num).toUpperCase();\n    return \"A\" + chr;\n  } else if (num \u003e= 52 \u0026\u0026 num \u003c= 77) {\n    num -= 52;\n    chr = String.fromCharCode(97 + num).toUpperCase();\n    return \"B\" + chr;\n  } else if (num \u003e= 78 \u0026\u0026 num \u003c= 103) {\n    num -= 78;\n    chr = String.fromCharCode(97 + num).toUpperCase();\n    return \"C\" + chr;\n  }\n}\n\nfunction ex_nc() {\n for (var i = 1; i \u003c= 104; i++) {\n   var j = numCol(i);\n   Logger.log(i + \" - \" + j);\n }\n}\n\nex_nc(); // 1 - A ... CZ - 104\n```\n\n#### Convert Column Letter to a Number #### \n\n```javascript\n/**\n * Returns an alphabetical column value as a number.\n *\n * @param {string} column\n * @returns {number}\n */\n\nfunction colNum(column) {\n  var col = column.toUpperCase(), chr0, chr1;\n  if (col.length === 1)  {\n    chr0 = col.charCodeAt(0) - 64;\n    return chr0;\n  } else if (col.length === 2) {\n    chr0 = (col.charCodeAt(0) - 64) * 26;\n    chr1 = col.charCodeAt(1) - 64;\n    return chr0 + chr1;\n  }\n}\n\nfunction ex_cn() {\n for (var i = 0; i \u003c= 25; i++) {\n   var abc = String.fromCharCode(97 + i).toUpperCase();\n   Logger.log(abc + \" - \" + colNum(abc));\n }\n for (var i = 26; i \u003c= 51; i++) {\n   var abc = \"A\" + String.fromCharCode(97 - 26 + i).toUpperCase();\n   Logger.log(abc + \" - \" + colNum(abc));\n }\n}\n\nex_cn(); // A - 1 ... AZ - 52\n```\n\n#### Replicating Import Range #### \n\n```javascript\n/**\n * Replicating import range in Google Apps Script.\n * Requires a trigger to function.\n * importRange : From spreadsheet : On edit\n *\n */\n\nfunction importRange(){\n  var get = sheet_gs.getRange(\"A2:A5\").getValues();\n  var set = sheet_gs.getRange(\"B2:B5\").setValues(get);\n}\n```\n\n#### Evaluating True and False #### \n\n```javascript\n/**\n * Returns true or false given truthy or falsy values.\n * true: 1, t*, T*, y*, Y*\n * false: 0, !t, || !y\n *\n * @param {string} input\n * @returns {boolean}\n */\n\nfunction checkTF(input) {\n  if (isNaN(input)) {\n    var first_letter = input.charAt(0).toLowerCase();\n    if (first_letter === 't' || first_letter === 'y') {\n      return true;\n    } else {\n      return false;\n    }\n  } else {\n    if (input === 1) {\n      return true;\n    } else { \n      return false;\n    }\n  }\n}\n\nLogger.log(checkTF(\"No\")); // false\nLogger.log(checkTF(\"Yes\")); // true\n```\n\n#### Array of Sheet Names ####\n\n```javascript\n/**\n * Returns an array of the sheet names for a spreadsheet.\n *\n * @param {Spreadsheet} ss\n * @returns {string[]}\n */\n\nfunction arrSheetNames(ss) {\n  var sheets = ss.getSheets();\n  var arr    = [];\n  for (var i = 0; i \u003c sheets.length; i++) {\n    arr.push(sheets[i].getName());\n  } \n  return arr;\n} \n\nvar ss_asn = SpreadsheetApp.getActiveSpreadsheet();\nLogger.log(arrSheetNames(ss_asn)); // [\"Sheet1\", \"Sheet2\", \"Sheet3\"]\n```\n\n### Object ###\n\n#### Object From Range ####\n\n```javascript\n/**\n * Returns an object from a range.\n * The top row of the range is assumed to be the header row.\n * Values in the header row become the object properties.\n *\n * @param {Sheet} sheet\n * @param {string} a1Notation\n * @returns {Object}\n */\n\nfunction objFromRange(sheet, a1Notation) {\n  var range  = sheet.getRange(a1Notation);\n  var height = range.getHeight();\n  var width  = range.getWidth();\n  var values = range.getValues();\n  var obj    = {};\n  for (var i = 0; i \u003c values.length; i++) {\n    obj[values[i][0]] = values[i][1];\n  } \n  return obj;\n}\n\nvar sheet_ofr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet1\");\nLogger.log(objFromRange(sheet_ofr, \"D2:E5\")); // {A=Alpha, B=Bravo, C=Charlie, D=Delta}\n```\n\n### Array of Objects ###\n\n#### Utility Functions for Array of Objects ####\n\n##### Header Values #####\n\n```javascript\n/**\n * Returns an array of values for the top row of a range object.\n *\n * @param {Range} rangeObj\n * @returns {Array}\n */\n\nfunction headerVal(rangeObj){\n  var vals = rangeObj.getValues();\n  var arr  = [];\n  for (var i = 0; i \u003c vals[0].length; i++) {\n    var val = vals[0][i];\n    arr.push(val);\n  } \n  return arr;\n}\n\nvar sheet_hv = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar range_hv = sheet_hv.getRange(\"A2:E19\");\nLogger.log(headerVal(range_hv)); // [\"First\", \"Last\", \"Grade\", \"Homeroom\", \"Email\"]\n```\n\n##### Values By Row #####\n\n```javascript\n/**\n * Returns an array of objects representing a range.\n *\n * @param {Range} rangeObj\n * @param {Array} headers\n * @returns {Object[]}\n */\n\nfunction valByRow(rangeObj, headers){\n  var height = rangeObj.getHeight();\n  var width  = rangeObj.getWidth();\n  var vals   = rangeObj.getValues();\n  var arr  = [];\n  for (var i = 0; i \u003c height; i++) {\n    var row = {};\n    for (var j = 0; j \u003c width; j++) {\n      var prop = headers[j];\n      var val  = vals[i][j];\n      if (val !== \"\") {\n        row[prop] = val;\n      } \n    }\n    arr.push(row);\n  }  \n  return arr;\n}\n\nvar sheet_vbr   = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar range_vbr   = sheet_hv.getRange(\"A2:E19\");\nvar headers_vbr = headerVal(range_vbr);\nLogger.log(valByRow(range_vbr, headers_vbr)); // [{Last=Last, Email=Email, Homeroom=Homeroom, Grade=Grade, First=First}, {Last=Garret, Email=agarret@example.com, Homeroom=Muhsina, Grade=6.0, First=Arienne}...]\n```\n\n##### Header Range #####\n\n```javascript\n/**\n * Returns the header range for a targeted range.\n *\n * @param {Sheet} sheet\n * @param {string} a1Notation\n * @returns {Range}\n */\n\nfunction headerRange(sheet, a1Notation) {\n  var split = a1Notation.split(\":\");\n  var col0  = split[0].match(/\\D/g,'');\n  var col1  = split[1].match(/\\D/g,'');\n  var row   = split[0].match(/\\d+/g);\n  var a1    = col0 + row + \":\" + col1 + row;\n  return sheet.getRange(a1);\n}\n\nvar sheet_hr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nLogger.log(headerRange(sheet_hr, \"A2:E19\").getA1Notation()); // \"A2:E2\"\nLogger.log(headerRange(sheet_hr, \"A2:E19\").getValues()); // [[First, Last, Grade, Homeroom, Email]]\n```\n\n##### Value Range #####\n\n```javascript\n/**\n * Returns the value range for a targeted range. \n *\n * @param {Sheet} sheet\n * @param {string} a1Notation\n * @returns {Range}\n */\n\nfunction valueRange(sheet, a1Notation) {\n  var split = a1Notation.split(\":\");\n  var col0  = split[0].match(/\\D/g,'');\n  var row0  = split[0].match(/\\d+/g);\n  var col1  = split[1].match(/\\D/g,'');\n  var row1  = split[1].match(/\\d+/g);\n  var a1    = col0 + (Number(row0) + 1) + \":\" + col1 + row1;\n  return sheet.getRange(a1);\n}\n\nvar sheet_vr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nLogger.log(valueRange(sheet_vr, \"A2:E19\").getA1Notation()); // \"A3:E19\"\nLogger.log(valueRange(sheet_vr, \"A2:E19\").getValues()); // [[Arienne, Garret, 6.0, Muhsina, agarret@example.com], [Elissa, Jules, 6.0, Lale, ejules@example.com]...]\n```\n\n#### Array of Objects from Sheet ####\n\n```javascript\n/**\n * Returns an array of objects representing the values in a sheet.\n *\n * @requires numCol() \n * @requires headerVal() \n * @requires valByRow() \n * @param sheet\n * @param hRow\n * @returns {undefined}\n */\n\nfunction arrObjFromSheet(sheet, hRow){\n  var lColNum = sheet.getLastColumn();\n  var lColABC = numCol(lColNum);\n  var lRow    = sheet.getLastRow();\n  var hRange  = sheet.getRange(\"A\" + hRow + \":\" + lColABC + hRow);\n  var headers = headerVal(hRange);\n  var vRange  = sheet.getRange(\"A\" + (hRow +1) + \":\" + lColABC + lRow);\n  return valByRow(vRange, headers);\n}\n\nvar sheet_aofs = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nLogger.log(arrObjFromSheet(sheet_aofs, 2)); // [{Last=Garret, Email=agarret@example.com, Homeroom=Muhsina, Grade=6.0, First=Arienne}, {Last=Jules, Email=ejules@example.com, Homeroom=Lale, Grade=6.0, First=Elissa}...]\n```\n\n#### Array of Objects from Range ####\n\n```javascript\n/**\n * Returns an array of values representing the values in a range.\n *\n * @requires headerRange() \n * @requires valueRange() \n * @requires headerVal() \n * @requires valByRow() \n * @param sheet\n * @param a1Notation\n * @returns {undefined}\n */\n\nfunction arrObjFromRange(sheet, a1Notation) {\n  var hRange  = headerRange(sheet, a1Notation);\n  var vRange  = valueRange(sheet, a1Notation);\n  var headers = headerVal(hRange);\n  return valByRow(vRange, headers);\n}\n\nvar sheet_aofr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nLogger.log(arrObjFromRange(sheet_aofr, \"A2:E7\")); // [{Last=Garret, Email=agarret@example.com, Homeroom=Muhsina, Grade=6.0, First=Arienne}, {Last=Jules, Email=ejules@example.com, Homeroom=Lale, Grade=6.0, First=Elissa}...]\n```\n\n### Array ###\n\n#### Array of Values for Column ####\n\n##### For Header Value #####\n\n```javascript\n/**\n * Returns an array containing all values in a column.\n *\n * @param {Sheet} sheet\n * @param {number} hRow\n * @param {string} name\n * @returns {Array}\n */\n\nfunction arrForColName(sheet, hRow, name){\n  var lColNum  = sheet.getLastColumn();\n  var lColABC  = numCol(lColNum);\n  var lRow     = sheet.getLastRow();\n  var hRange   = sheet.getRange(\"A\" + hRow + \":\" + lColABC + hRow);\n  var headers  = headerVal(hRange);\n  var tColABC  = numCol(headers.indexOf(name) + 1);\n  var rangeObj = sheet.getRange(tColABC + (hRow +1) + \":\" + tColABC + lRow);\n  var height   = rangeObj.getHeight();\n  var vals     = rangeObj.getValues();\n  var arr      = [];\n  for (var i = 0; i \u003c height; i++) {\n      var val  = vals[i][0];\n      arr.push(String(val));\n  }  \n  return arr;\n}\n\nvar sheet_afcna = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nLogger.log(arrForColName(sheet_afcna, 2, \"First\")); // [Arienne, Elissa, Nerses, Gülistan, Syed, Isaiah, Stanley, Sára, Kaja, Józef, Radoslava, Sarah, Oluwasegun, Ekundayo, Gina, Sylvia, Cemil]\n```\n\n##### For Column Number #####\n\n```javascript\n/**\n * Returns an array containing all values in a column.\n *\n * @param {Sheet} sheet\n * @param {number} hRow\n * @param {number} colIndex\n * @returns {Array}\n */\n\nfunction arrForColNo(sheet, hRow, colIndex){\n  var lColNum  = sheet.getLastColumn();\n  var lColABC  = numCol(lColNum);\n  var lRow     = sheet.getLastRow();\n  var hRange   = sheet.getRange(\"A\" + hRow + \":\" + lColABC + hRow);\n  var tColABC  = numCol(colIndex);\n  var rangeObj = sheet.getRange(tColABC + (hRow +1) + \":\" + tColABC + lRow);\n  var height   = rangeObj.getHeight();\n  var vals     = rangeObj.getValues();\n  var arr      = [];\n  for (var i = 0; i \u003c height; i++) {\n      var val  = vals[i][0];\n      arr.push(String(val));\n  }  \n  return arr;\n}\n\nvar sheet_afcno = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\"); \nLogger.log(arrForColNo(sheet_afcno, 2, 2)); // [Garret, Jules, Juda, Armen, Yeong-Suk, Coy, Stevie, Emin, Tiriaq, Dilay, Kirabo, Ariadna, Devrim, Adjoa, Suk, Lyle, Edita]\n```\n\n##### For Range Object #####\n\n```javascript\n/**\n * Returns an array containing all values in the first column of a range. \n *\n * @param {Range} rangeObj\n * @returns {Array}\n */\n\nfunction arrForColRange(rangeObj){\n  var height = rangeObj.getHeight();\n  var vals   = rangeObj.getValues();\n  var arr    = [];\n  for (var i = 0; i \u003c height; i++) {\n    arr.push(vals[i][0]);\n  }\n  return arr;\n}\n\nvar sheet_vafro = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet1\");\nvar range_vafro = sheet_vafro.getRange(\"A2:F5\");\nLogger.log(arrForColRange(range_vafro)); // [\"A\", \"B\", \"C\", \"D\"]\n```\n\n## Docs ##\n\n### Managing Document Files ###\n\n#### Create or Verify Document \n\n##### Create or Verify Document in a Folder #####\n\n```javascript\n// --- Create or Verify Document in a Folder\n\n/**\n * Returns a document.\n * This creates the document if it does not already exist.\n *\n * @param {Folder} fldr\n * @param {string} name\n * @returns {Document}\n */\n\nfunction createVerifyDocIn(fldr, name) {\n  var files = filesIn(fldr);\n  var names = fileNames(files);\n  if (!(checkValIn(names, name))) {\n    var doc  = DocumentApp.create(name).getId();\n    var file = DriveApp.getFileById(doc);\n    moveFile(file, fldr);\n  }\n  return openFileAsDocument(findFileIn(fldr, name));\n}\n\nvar fldr_cvdi = createVerifyPath(\"google-apps-script-cheat-sheet-demo/docs\");\nLogger.log(createVerifyDocIn(fldr_cvdi, \"example-doc\")); // example-doc\n```\n\n##### Create or Verify Document at Root #####\n\n```javascript\n/**\n * Returns a document.\n * This creates the document if it does not already exist.\n *\n * @param {string} name\n * @returns {Document}\n */\n\nfunction createVerifyDocAtRoot(name) {\n  var files = rootFiles();\n  var names = fileNames(files);\n  if (!(checkValIn(names, name))) {\n    var ss = DocumentApp.create(name);\n  }\n  return findFileAtRoot(name);\n}\n```\n\n#### Id of Active Document ####\n\n```javascript\n/**\n * Returns the Id of the active document.\n *\n * @returns {string}\n */\n\nfunction docId() {\n  var _id = DocumentApp.getActiveDocument().getId();\n  return _id;\n}\n```\n\n#### Open File as Document ####\n\n```javascript\n/**\n * Returns a file as a document.\n *\n * @param {File} file\n * @returns {Document}\n */\n\nfunction openFileAsDocument(file) {\n  var _id = file.getId();\n  var _doc = DocumentApp.openById(_id);\n  return _doc;\n} \n\nvar fldr_ofad = lastFolderIn(\"google-apps-script-cheat-sheet-demo/docs\");\nvar file_ofad = findFileIn(fldr_ofad, \"example-doc\");\nLogger.log(openFileAsDocument(file_ofad));\n```\n\n### Utility Functions for Docs ### \n\n#### Access Document Body ####\n\n```javascript\nvar fldr_adb = lastFolderIn(\"google-apps-script-cheat-sheet-demo/docs\");\nvar file_adb = findFileIn(fldr_adb, \"example-doc\");\nvar doc_adb  = openFileAsDocument(file_adb);\ndoc_adb.appendParagraph(\"Hello, world!\");\n```\n\n#### Clear Document Body ####\n\n```javascript\nvar fldr_cdb = lastFolderIn(\"google-apps-script-cheat-sheet-demo/docs\");\nvar file_cdb = findFileIn(fldr_cdb, \"example-doc\");\nvar doc_cdb  = openFileAsDocument(file_cdb);\nvar body_cdb = doc_cdb.getBody();\nbody_cdb.clear();\n```\n\n## Merges ##\n\n### Sheets and Docs ###\n\n#### String from Object Properties #### \n\n```javascript\nvar ex_obj = { \n  name:  \"Jon\",\n  state: \"MN\",\n  job:   \"IT Administrator\"\n};\n```\n\n```javascript\n/**\n * Returns a string. \n * Words wrapped by the delimiter are replaced with the matching property value.\n *\n * @param {Object} obj\n * @param {string} str\n * @param {string} delim\n * @returns {string}\n */\n\nfunction strFromProp(obj, str, delim) {\n  var split  = str.split(\" \");\n  var result = [];\n  for (var i = 0; i \u003c split.length; i++) {\n    var _str = split[i]; \n    for (var prop in obj){\n      var first = _str.slice().charAt(0);\n      var last  = _str.slice().substr(-1);\n      var mod   = _str.substr(0, _str.length-1).substr(1);\n      if ((obj.hasOwnProperty(mod)) \u0026\u0026 (first === delim) \u0026\u0026 (last === delim)) {\n        result.push(obj[mod]);\n      } else {\n        result.push(_str);\n      }\n      break;\n    }\n  } \n  return result.join(\" \");\n}\n\nLogger.log(strFromProp(ex_obj, \"name: %name% - state: %state% - job: %job%\", \"%\")); // \"name: Jon - state: MN - job: IT Administrator\"\n```\n\n#### Replace Object Properties #### \n\n##### Replace Object Properties in Document #####\n\n```javascript\n/**\n * Words wrapped by the delimiter are replaced with the matching property value.\n *\n * @param {Object} obj\n * @param {Document} doc\n * @param {string} delim\n */\n\nfunction findReplaceInDoc(obj, doc, delim) {\n  var body = doc.getBody(); \n  for (var prop in obj) {\n    var query = delim + prop + delim;\n    var val   = obj[prop];\n    body.replaceText(query, val);\n  } \n} \n\nvar fldr_frid = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges\");\nvar doc_frid  = createVerifyDocIn(fldr_frid, \"find-replace-doc\");\nvar body_frid = doc_frid.getBody();\nbody_frid.clear();\ndoc_frid.appendParagraph(\"name: %name%\");\ndoc_frid.appendParagraph(\"state: %state%\");\ndoc_frid.appendParagraph(\"job: %job%\");\nfindReplaceInDoc(ex_obj, doc_frid, \"%\");\n```\n\n##### Replace Object Properties in Spreadsheet #####\n\n```javascript\n/**\n * Words wrapped by the delimiter are replaced with the matching property value.\n *\n * @param {Object} obj\n * @param {Spreadsheet} ss\n * @param {string} delim\n */\n\nfunction findReplaceInSpreadsheet(obj, ss, delim) {\n  var numSheets = ss.getNumSheets();\n  var sheets    = ss.getSheets();\n  for (var i = 0; i \u003c numSheets; i++) {\n    var sheet = sheets[i];\n    var values = sheet.getDataRange().getValues();\n    for (var row in values){\n      var update = values[row].map(function(original) {\n        var text = original.toString();\n        for (var prop in obj) {\n          var query = delim + prop+ delim;\n          if (text.indexOf(query) !== -1) {\n            text = text.replace(query, obj[prop]);\n          }\n        } \n        return text;\n      });\n    values[row] = update;\n    }\n    sheet.getDataRange().setValues(values);\n  } \n}\n\nvar fldr_fris  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges\");\nvar ss_frid    = createVerifySSIn(fldr_fris, \"find-replace-sheet\");\nvar sheet_frid = ss_frid.getSheets()[0];\nsheet_frid.clear();\n\nvar val_frid = [\n  [ \"name\", \"state\", \"job\" ],\n  [ \"%name%\", \"%state%\", \"%job%\"]\n];\n\nvar range_frid = sheet_frid.getRange(\"A1:C2\");\nrange_frid.setValues(val_frid);\nfindReplaceInSpreadsheet(ex_obj, ss_frid, \"%\");\n```\n\n##### Replace Object Properties in Sheet #####\n\n```javascript\n/**\n * Words wrapped by the delimiter are replaced with the matching property value.\n *\n * @param {Object} obj\n * @param {Sheet} sheet\n * @param {string} delim\n */\n\nfunction findReplaceinSheet(obj, sheet, delim) {\n  var values = sheet.getDataRange().getValues();\n  for(var row in values){\n    var update = values[row].map(function(original) {\n      var text = original.toString();\n      for (var prop in obj) {\n        var query = delim + prop + delim;\n          if (text.indexOf(query) !== -1) {\n            text = text.replace(query, obj[prop]);\n          }\n      } \n      return text;\n    });\n    values[row] = update;\n  }\n  sheet.getDataRange().setValues(values);\n}\n\nvar fldr_fris  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges\");\nvar ss_fris    = createVerifySSIn(fldr_fris, \"find-replace-sheet\");\nvar sheet_fris = ss_fris.getSheets()[0];\nsheet_fris.clear();\n\nvar val_fris = [\n  [ \"name\", \"state\", \"job\" ],\n  [ \"\u003c\u003cname\u003e\u003e\", \"\u003c\u003cstate\u003e\u003e\", \"\u003c\u003cjob\u003e\u003e\"]\n];\n\nvar range_fris = sheet_fris.getRange(\"A1:C2\");\nrange_fris.setValues(val_fris);\nfindReplaceinSheet(ex_obj, sheet_fris, \"%\");\n```\n\n#### Copy Template for Item in Array of Objects and Replace Object Properties #### \n\n##### Copy Document Template and Replace Object Properties #####\n\n```javascript\n/**\n * For each object, create a new template document and merge in object values.\n *\n * @requires strFromProp() \n * @requires copyFile() \n * @requires findReplaceInDoc() \n * @param {Object[]} arrObj\n * @param {Document} templateDoc\n * @param {string} naming\n * @param {Folder} fldr\n * @param {boolean} ts\n * @param {string} delim\n */\n\nfunction createDocsFromTemplateArrObj(arrObj, templateDoc, naming, fldr, ts, delim) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj  = arrObj[i];\n    var name = strFromProp(obj, naming, delim);\n    if (ts === true) name += \" - \" + fmat12DT();\n    var file  = DriveApp.getFileById(templateDoc.getId());\n    var docId = copyFile(file, fldr).setName(name).getId();\n    var doc   = DocumentApp.openById(docId);\n    findReplaceInDoc(obj, doc, delim);\n    }\n} \n\nvar sheet_cdftao  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar arrObj_cdftao = arrObjFromSheet(sheet_cdftao, 2);\nvar fldr1_cdftao  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges\");\nvar fldr2_cdftao  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges/arrObj-docs\");\nvar doc_cdftao    = createVerifyDocIn(fldr1_cdftao, \"template-doc\");\nvar body_cdftao   = doc_cdftao.getBody();\nbody_cdftao.clear();\ndoc_cdftao.appendParagraph(\"First: %First%\");\ndoc_cdftao.appendParagraph(\"Last: %Last%\");\ndoc_cdftao.appendParagraph(\"Grade: %Grade%\");\ndoc_cdftao.appendParagraph(\"Homeroom: %Homeroom%\");\ndoc_cdftao.appendParagraph(\"Email: %Email%\");\ncreateDocsFromTemplateArrObj(arrObj_cdftao, doc_cdftao, \"Name: %Last% %First%\", fldr2_cdftao, true, \"%\");\n```\n\n##### Copy Spreadsheet Template and Replace Object Properties #####\n\n```javascript\n/**\n * For each object, create a new template spreadsheet and merge in object values.\n *\n * @requires strFromProp() \n * @requires copyFile() \n * @requires findReplaceInSpreadsheet() \n * @param {Object[]} arrObj\n * @param {Spreadsheet} templateDoc\n * @param {string} naming\n * @param {Folder} fldr\n * @param {boolean} ts\n * @param {string} delim\n */\n\nfunction createSpreadsheetsFromTemplateArrObj(arrObj, templateSS, naming, fldr, ts, delim) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj  = arrObj[i];\n    var name = strFromProp(obj, naming, delim);\n    if (ts === true) name += \" - \" + fmat12DT();\n    var file = DriveApp.getFileById(templateSS.getId());\n    var ssId = copyFile(file, fldr).setName(name).getId();\n    var ss   = SpreadsheetApp.openById(ssId);\n    findReplaceInSpreadsheet(obj, ss, delim);\n    }\n} \n\nvar ss1_csftao    = SpreadsheetApp.getActiveSpreadsheet();\nvar sheet1_csftao = ss1_csftao.getSheetByName(\"Sheet2\");\nvar arrObj_csftao = arrObjFromSheet(sheet1_csftao, 2);\nvar fldr1_csftao  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges\");\nvar fldr2_csftao  = createVerifyPath(\"google-apps-script-cheat-sheet-demo/merges/arrObj-sheets\");\nvar file_csftao   = createVerifySSIn(fldr1_csftao, \"template-sheet\");\nvar ss2_csftao    = openFileAsSpreadsheet(file_csftao);\nvar sheet2_csftao = ss2_csftao.getSheets()[0];\n\nvar val_csftao = [\n  [ \"First\", \"Last\", \"Grade\", \"Homeroom\", \"Email\" ],\n  [ \"%First%\", \"%Last%\", \"%Grade%\", \"%Homeroom%\", \"%Email%\"]\n];\n\nvar range_csftao = sheet2_csftao.getRange(\"A1:E2\");\nrange_csftao.setValues(val_csftao);\ncreateSpreadsheetsFromTemplateArrObj(arrObj_csftao, file_csftao, \"Name: %Last% %First%\", fldr2_csftao, true, \"%\");\n```\n\n#### Create Bulleted List in Document for Array of Objects ####\n\n##### Single Division List #####\n\n```javascript\nvar sheet_sdl  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar arrObj_sdl = arrObjFromSheet(sheet_sdl, 2);\nvar fldr_sdl   = createVerifyPath(\"google-apps-script-cheat-sheet-demo/docs\");\nvar file_sdl   = createVerifyDocIn(fldr_sdl, \"example-doc\");\nvar doc_sdl    = openFileAsDocument(file_sdl);\nvar body_sdl   = doc_sdl.getBody();\n\n(function(){\n  arrObj_sdl.sort(dynSortM(\"Last\", \"First\"));\n  var sectionHeader = body_sdl.appendParagraph(\"Students\");\n  sectionHeader.setHeading(DocumentApp.ParagraphHeading.HEADING1);\n  for (var i in arrObj_sdl) {\n    body_sdl.appendListItem(arrObj_sdl[i][\"Last\"] + \", \" + arrObj_sdl[i][\"First\"]);\n  }\n})();\n```\n\n##### Multi Division List #####\n\n```javascript\nvar sheet_mdl  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar arrObj_mdl = arrObjFromSheet(sheet_mdl, 2);\nvar fldr_mdl   = createVerifyPath(\"google-apps-script-cheat-sheet-demo/docs\");\nvar file_mdl   = createVerifyDocIn(fldr_mdl, \"example-doc\");\nvar doc_mdl    = openFileAsDocument(file_mdl);\nvar body_mdl   = doc_mdl.getBody();\n\n(function(){\n  arrObj_mdl.sort(dynSortM(\"Homeroom\", \"Last\", \"First\"));\n  var sectionHeader = body_mdl.appendParagraph(\"Homerooms and Students\");\n  sectionHeader.setHeading(DocumentApp.ParagraphHeading.HEADING1);\n  var homeroom = arrObj_mdl[0][\"Homeroom\"];\n  body_mdl.appendListItem(homeroom);\n  for (var i in arrObj_mdl) {\n    if (arrObj_mdl[i][\"Homeroom\"] === homeroom) {\n      body_mdl.appendListItem(arrObj_mdl[i][\"First\"] + \" \" + arrObj_mdl[i][\"Last\"])\n      .setNestingLevel(1).setIndentStart(10)\n      .setGlyphType(DocumentApp.GlyphType.HOLLOW_BULLET);\n    } else {\n      homeroom = arrObj_mdl[i][\"Homeroom\"];\n      body_mdl.appendListItem(homeroom);\n      body_mdl.appendListItem(arrObj_mdl[i][\"First\"] + \" \" + arrObj_mdl[i][\"Last\"])\n      .setNestingLevel(1).setIndentStart(10)\n      .setGlyphType(DocumentApp.GlyphType.HOLLOW_BULLET);\n    }\n  }\n})();\n```\n\n## Gmail ##\n\n### Mail Merge ###\n\n#### Append Subject and Body Properties for Array of Objects ####\n\n```javascript\n/**\n * Returns an array of objects. Subject and Body properties are appended to each object.\n *\n * @param {Object[]} arrObj\n * @param {string} subj\n * @param {string} body\n * @param {string} delim\n * @returns {Object[]}\n */\n\nfunction appendSubjBodyForArrObj(arrObj, subj, body, delim) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj = arrObj[i];\n    for (var prop in obj) {\n      var search = delim + prop + delim;\n      if (body.indexOf(search) !== -1) {\n        body = body.replace(search, obj[prop]);\n        }\n      if (subj.indexOf(search) !== -1) {\n        subj = subj.replace(search, obj[prop]);\n        }\n      }\n    obj.Subject = subj;\n    obj.Body    = body;\n    }\n  return arrObj;\n} \n\nvar sheet_aasbfao = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar arrObj_asbfao = arrObjFromSheet(sheet_aasbfao, 2);\nvar subj_asbfao   = \"Classroom update for %First% %Last%\";\nvar body_asbfao   = \"\u003cp\u003e%First% %Last% is in %Homeroom%'s this fall!\u003c/p\u003e\";\nLogger.log(appendSubjBodyForArrObj(arrObj_asbfao, subj_asbfao, body_asbfao, \"%\")); // [{Last=Garret, Email=agarret@example.com, Homeroom=Muhsina, Grade=6.0, First=Arienne, Body=\u003cp\u003eArienne Garret is in Muhsina's this fall!\u003c/p\u003e, Subject=Classroom update for Arienne Garret}...]\n```\n\n#### Run Mail Merge for Array of Objects ####\n\n```javascript\n/**\n * Sends and email for each object in an array of objects.\n * Properties Email, Subject and Body are used.\n *\n * @requires appendSubjBodyForArrObj() \n * @param {Object[]} arrObj\n */\n\nfunction runMailMergeForArrObj(arrObj) {\n  for (var i = 0; i \u003c arrObj.length; i++) {\n    var obj = arrObj[i];\n      MailApp.sendEmail({\n        to: obj.Email,\n        subject: obj.Subject,\n        htmlBody: obj.Body\n      });\n  }\n}\n\nvar sheet_rmmfao  = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(\"Sheet2\");\nvar arrObj_rmmfao = arrObjFromSheet(sheet_rmmfao, 2);\nvar subj_rmmfao   = \"Classroom update for %First% %Last%\";\nvar body_rmmfao   = \"\u003cp\u003e%First% %Last% is in %Homeroom%'s this fall!\u003c/p\u003e\";\narrObj_rmmfao     = appendSubjBodyForArrObj(arrObj_rmmfao, subj_rmmfao, body_rmmfao);\nrunMailMergeForArrObj(arrObj_rmmfao);\n```\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjc324x%2Fgoogle-apps-script-cheat-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjc324x%2Fgoogle-apps-script-cheat-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjc324x%2Fgoogle-apps-script-cheat-sheet/lists"}