├── 003_IntroToAppsScript_Macros.js ├── 005_IntroToAppsScript_HelloWorld.js ├── 006_IntroToAppsScript_CustomFunctions.js ├── 007_IntroToAppsScript_Variables.js ├── 008_IntroToAppsScript_Operators.js ├── 009_IntroToAppsScript_Functions.js ├── 010_IntroToAppsScript_Arrays.js ├── 011_IntroToAppsScript_Objects.js ├── 012_IntroToAppsScript_Loops.js ├── 013_IntroToAppsScript_SpreadsheetService.js ├── 014_IntroToAppsScript_WorkingWithData.js ├── 015_IntroToAppsScript_PuttingDataBackIntoSheets.js ├── 016_IntroToAppsScript_CustomMenus.js ├── 017_IntroToAppsScript_addingFormulas.js ├── 018_IntroToAppsScript_Formatting.js ├── 019_IntroToAppsScript_Charts.js ├── 020_IntroToAppsScript_Project1.js ├── 021_IntroToAppsScript_Project2.js ├── 022_IntroToAppsScript_Project3.js ├── 023_IntroToAppsScript_Project4.js ├── 024_IntroToAppsScript_Project5.js ├── 025_IntroToAppsScript_Project6.js ├── 026_IntroToAppsScript_Project7.js ├── 027_IntroToAppsScript_Project8.js ├── 028_IntroToAppsScript_Project9.js ├── AppsScript_Intro copy.jpg └── README.md /003_IntroToAppsScript_Macros.js: -------------------------------------------------------------------------------- 1 | function firstmacro() { 2 | 3 | var spreadsheet = SpreadsheetApp.getActive(); 4 | 5 | spreadsheet.getActiveRangeList().setFontWeight('bold') 6 | .setFontStyle('italic') 7 | .setFontColor('#ff0000'); 8 | 9 | }; 10 | 11 | function secondmacro() { 12 | 13 | var spreadsheet = SpreadsheetApp.getActive(); 14 | 15 | spreadsheet.getRange('D1').activate(); 16 | 17 | spreadsheet.getActiveRangeList().setFontWeight('bold') 18 | .setFontStyle('italic') 19 | .setFontColor('#0000ff'); 20 | }; 21 | 22 | function greencolors() { 23 | var spreadsheet = SpreadsheetApp.getActive(); 24 | 25 | spreadsheet.getCurrentCell().offset(0, 0, 11, 5).activate(); 26 | 27 | spreadsheet.getActiveRange().applyRowBanding(SpreadsheetApp.BandingTheme.LIGHT_GREY); 28 | var banding = spreadsheet.getActiveRange().getBandings()[0]; 29 | banding.setHeaderRowColor('#63d297') 30 | .setFirstRowColor('#ffffff') 31 | .setSecondRowColor('#e7f9ef') 32 | .setFooterRowColor(null); 33 | }; 34 | 35 | function orangecolors() { 36 | var spreadsheet = SpreadsheetApp.getActive(); 37 | 38 | spreadsheet.getDataRange().applyRowBanding(SpreadsheetApp.BandingTheme.ORANGE); 39 | 40 | }; 41 | 42 | 43 | function chart() { 44 | var spreadsheet = SpreadsheetApp.getActive(); 45 | spreadsheet.getRange('D1:E11').activate(); 46 | var sheet = spreadsheet.getActiveSheet(); 47 | var chart = sheet.newChart() 48 | .asColumnChart() 49 | .addRange(spreadsheet.getRange('D1:E11')) 50 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 51 | .setTransposeRowsAndColumns(false) 52 | .setNumHeaders(-1) 53 | .setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH) 54 | .setPosition(1, 2, 26, 13) 55 | .build(); 56 | sheet.insertChart(chart); 57 | var charts = sheet.getCharts(); 58 | chart = charts[charts.length - 1]; 59 | sheet.removeChart(chart); 60 | chart = sheet.newChart() 61 | .asPieChart() 62 | .addRange(spreadsheet.getRange('D1:E11')) 63 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 64 | .setTransposeRowsAndColumns(false) 65 | .setNumHeaders(-1) 66 | .setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH) 67 | .setPosition(1, 2, 26, 13) 68 | .build(); 69 | sheet.insertChart(chart); 70 | charts = sheet.getCharts(); 71 | chart = charts[charts.length - 1]; 72 | sheet.removeChart(chart); 73 | chart = sheet.newChart() 74 | .asPieChart() 75 | .addRange(spreadsheet.getRange('D1:E11')) 76 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 77 | .setTransposeRowsAndColumns(false) 78 | .setNumHeaders(1) 79 | .setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH) 80 | .setPosition(1, 2, 26, 13) 81 | .build(); 82 | sheet.insertChart(chart); 83 | charts = sheet.getCharts(); 84 | chart = charts[charts.length - 1]; 85 | sheet.removeChart(chart); 86 | chart = sheet.newChart() 87 | .asPieChart() 88 | .addRange(spreadsheet.getRange('D1:E11')) 89 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 90 | .setTransposeRowsAndColumns(false) 91 | .setNumHeaders(1) 92 | .setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH) 93 | .setOption('applyAggregateData', 0) 94 | .setPosition(1, 2, 26, 13) 95 | .build(); 96 | sheet.insertChart(chart); 97 | charts = sheet.getCharts(); 98 | chart = charts[charts.length - 1]; 99 | sheet.removeChart(chart); 100 | chart = sheet.newChart() 101 | .asPieChart() 102 | .addRange(spreadsheet.getRange('D1:E11')) 103 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 104 | .setTransposeRowsAndColumns(false) 105 | .setNumHeaders(1) 106 | .setHiddenDimensionStrategy(Charts.ChartHiddenDimensionStrategy.IGNORE_BOTH) 107 | .setOption('applyAggregateData', 0) 108 | .setPosition(1, 6, 13, 9) 109 | .build(); 110 | sheet.insertChart(chart); 111 | }; 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /005_IntroToAppsScript_HelloWorld.js: -------------------------------------------------------------------------------- 1 | sufunction helloWorld() { 2 | 3 | Logger.log("Hello, World!"); 4 | 5 | } -------------------------------------------------------------------------------- /006_IntroToAppsScript_CustomFunctions.js: -------------------------------------------------------------------------------- 1 | function addOne(x) { 2 | const answer = x + 1; 3 | return answer; 4 | } 5 | 6 | const addOneArrow = x => x + 1; 7 | 8 | function double(x) { 9 | return x * 2; 10 | } 11 | 12 | function multByX(x,c) { 13 | return x * c; 14 | } 15 | 16 | 17 | 18 | /** 19 | * Function to calculate percentage change 20 | * 21 | * @param {number} oldVal Original value 22 | * @param {number} newVal New value 23 | * @return The percent change from old value to the new value 24 | * @customfunction 25 | */ 26 | function percentChange(oldVal,newVal) { 27 | 28 | return (newVal - oldVal) / oldVal; 29 | 30 | } -------------------------------------------------------------------------------- /007_IntroToAppsScript_Variables.js: -------------------------------------------------------------------------------- 1 | // Global Variables 2 | const SHEET_NAME = 'dataset_2020'; 3 | 4 | // const 5 | function constExample() { 6 | 7 | // const 8 | const x = 30; 9 | //console.log(x); 10 | //Logger.log(x); 11 | 12 | // const cannot be reassigned, but the value can change 13 | // TypeError: Assignment to constant variable. 14 | // cannot do this: 15 | // x = 50; 16 | // console.log(x); 17 | 18 | // const has block scope 19 | { 20 | console.log(x); 21 | const y = 1; 22 | console.log(y); 23 | } 24 | 25 | // ReferenceError: y is not defined 26 | // defined in a child block one level up, not available here 27 | console.log(y); 28 | 29 | } 30 | 31 | // let example 32 | function letExample() { 33 | 34 | let y = 100; 35 | console.log(y); 36 | 37 | // can be reassigned 38 | y = 200; 39 | console.log(y); 40 | 41 | // cannot redeclare it though 42 | // let y = 300; 43 | // console.log(y); 44 | 45 | // block scoped 46 | { 47 | let w = 99; 48 | console.log(w); 49 | } 50 | 51 | // variable w not available outside block 52 | //console.log(w); 53 | } 54 | 55 | // var example 56 | function varExample() { 57 | 58 | var x = 1; 59 | console.log(x); 60 | 61 | // can be reassigned 62 | x = 2; 63 | console.log(x); 64 | 65 | // var has function scope 66 | { 67 | var newVariable = 1000; 68 | } 69 | 70 | console.log(newVariable); 71 | 72 | } 73 | 74 | // other things to note about variables 75 | function otherNotes() { 76 | 77 | // Cannot access 'alpha' before initialization 78 | //console.log(alpha); 79 | //const alpha = 10; 80 | 81 | // bad practice to not declare 82 | //alpha = 10; 83 | //alpha = 20; 84 | //console.log(alpha); 85 | 86 | // access global variables 87 | console.log(SHEET_NAME); 88 | } 89 | -------------------------------------------------------------------------------- /008_IntroToAppsScript_Operators.js: -------------------------------------------------------------------------------- 1 | function mathOperators() { 2 | 3 | const a = 10; 4 | const b = 2; 5 | 6 | // standard operators + - * / 7 | console.log(a + b); 8 | console.log(a - b); 9 | console.log(a * b); 10 | console.log(a / b); 11 | 12 | // Raise to power of 13 | const c = Math.pow(a,b); 14 | console.log(c); 15 | 16 | // need to use let in this next example because of reassignment by the i++ and i-- 17 | let i = 0; 18 | console.log(i); 19 | 20 | // increment by 1 21 | i++; 22 | console.log(i); 23 | 24 | // reduce by 1 25 | i--; 26 | console.log(i); 27 | 28 | } 29 | 30 | 31 | function stringOperators() { 32 | 33 | // can use single or double quotes around strings 34 | // BUT MUST BE CONSISTENT WITHIN LINE 35 | 36 | const string1 = "Sarah"; // ok 37 | const string2 = 'Smith'; // ok 38 | const string3 = 'John'; // not ok 39 | 40 | // concatenate strings with the plus sign + 41 | const fullName = string3 + " & " + string1 + " " + string2; 42 | console.log(fullName); 43 | 44 | // multi-line strings with backtick marker 45 | const multiLineString = `This is a multi-line string 46 | in Apps Script, which is handy for those long paragraphs.`; 47 | 48 | console.log(multiLineString); 49 | 50 | } 51 | 52 | 53 | function comparisonOperators() { 54 | 55 | const a = 10; 56 | const b = '10'; 57 | 58 | console.log(a); 59 | console.log(typeof a); 60 | console.log(b); 61 | console.log(typeof b); 62 | 63 | // double == 64 | console.log(a == b); 65 | 66 | // triple === now checks to see if the type is matching too 67 | console.log(a === b); 68 | 69 | // Not equal != 70 | console.log(a != b); 71 | // false becuase javascript does type conversion and so values are equal 72 | 73 | // Not equal when considering value AND type !== 74 | console.log(a !== b); 75 | // true becuase the type is not equal 76 | 77 | // Greater than, less than operators 78 | const c = 50; 79 | const d = 100; 80 | 81 | console.log(c > d); 82 | console.log(c >= d); 83 | console.log(c < d); 84 | console.log(c <= d); 85 | 86 | 87 | } 88 | 89 | 90 | -------------------------------------------------------------------------------- /009_IntroToAppsScript_Functions.js: -------------------------------------------------------------------------------- 1 | // Why use functions? 2 | // you can encapsulate a chunk of code to reuse, with different arguments 3 | 4 | // traditional function declaration syntax 5 | function functionName(argument1, argument2, argument3) { 6 | 7 | //code to be executed when function is called (or invoked) 8 | 9 | // argument1, arguemnt2, argument3 are available 10 | // to do stuff with inside the function 11 | 12 | // return clause tells function what "answer" to return 13 | return someAnswer; 14 | 15 | } 16 | 17 | 18 | // basic function 19 | function firstFunction() { 20 | console.log('Hello World!'); 21 | } 22 | 23 | // arrow function syntax 24 | const firstFunctionArrow = () => console.log('Hello World!'); 25 | 26 | // pass parameters into functions 27 | function addFunction(num1,num2) { 28 | return num1 + num2; 29 | } 30 | 31 | // arrow 32 | const addFunctionArrow = (num1,num2) => num1 + num2; 33 | 34 | // in global space 35 | //console.log(addFunction(2,3)); 36 | //console.log(addFunctionArrow(2,3)); 37 | 38 | // call another function 39 | function runOtherFunction() { 40 | const answer = addFunction(100,93); 41 | console.log(answer); 42 | } 43 | 44 | // assigning functions to variables 45 | const multFunction = (a,b) => a * b; 46 | 47 | //console.log(multFunction); 48 | //Logger.log(multFunction); 49 | //console.log(multFunction(5,10)); 50 | 51 | // pass functions as arguments to other functions 52 | const superFunction = (fn, a, b) => fn(a,b); 53 | 54 | //console.log(superFunction(multFunction,2,5)); 55 | 56 | // default parameters 57 | function defaultParamFunction(a = 100, b = 10) { 58 | return a / b; 59 | } 60 | 61 | const defaultParamFunctionArrow = (a = 100, b = 10) => a / b; 62 | 63 | console.log(defaultParamFunctionArrow()); 64 | 65 | 66 | -------------------------------------------------------------------------------- /010_IntroToAppsScript_Arrays.js: -------------------------------------------------------------------------------- 1 | function arrayFunction() { 2 | 3 | // create new array like this 4 | const newArray = []; 5 | 6 | // ordering of items is important 7 | const fruitsArray = ['Apple','Banana','Pear','Strawberry']; 8 | 9 | //console.log(fruitsArray); // [Apple, Banana, Pear, Strawberry] 10 | 11 | // array index starts at 0 12 | // access items in array with this notation: 13 | //console.log(fruitsArray[0]); // Apple 14 | //console.log(fruitsArray[1]); // Banana 15 | //console.log(fruitsArray[2]); // Pear 16 | //console.log(fruitsArray[3]); // Strawberry 17 | //console.log(fruitsArray[4]); // undefined, nothing at position 4 18 | 19 | // can also write arrays like this: 20 | const anotherArray = ["first", 21 | "second", 22 | "third", 23 | "fourth"]; 24 | 25 | //console.log(anotherArray); 26 | 27 | /* 28 | Array Methods 29 | */ 30 | 31 | const countingArray = ['two','three','four']; 32 | console.log("Starting array:"); 33 | console.log(countingArray); 34 | 35 | // add item to array 36 | 37 | // add to end 38 | countingArray.push('one hundred'); 39 | console.log(countingArray); 40 | 41 | // add to start 42 | countingArray.unshift('one'); 43 | console.log(countingArray); 44 | 45 | // add to middle 46 | countingArray.splice(2,0,'miss a few'); 47 | console.log(countingArray); 48 | 49 | countingArray.splice(3,0,'ninety nine'); 50 | console.log(countingArray); 51 | 52 | // removing items from array 53 | 54 | // remove from end 55 | //countingArray.pop(); 56 | //console.log(countingArray); 57 | 58 | // remove from beginning 59 | //countingArray.shift(); 60 | //console.log(countingArray); 61 | 62 | // remove from middle 63 | countingArray.splice(4,2); 64 | console.log(countingArray); 65 | 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /011_IntroToAppsScript_Objects.js: -------------------------------------------------------------------------------- 1 | // Objects 2 | function objectFunction() { 3 | 4 | // create with curly brackets 5 | const obj = {}; 6 | 7 | // objects consist of key/value pairs 8 | // ordering is not important 9 | // often have line breaks to make easier to read 10 | const employee = { 11 | name: 'Joe Bloggs', 12 | age: 25, 13 | title: 'Data Analyst' 14 | } 15 | 16 | console.log(employee); 17 | console.log(typeof employee); 18 | 19 | // accessing values inside objects 20 | console.log(employee.name); // dot notation 21 | console.log(employee['age']); // square bracket notation 22 | console.log(employee.title); 23 | console.log(employee.height); // undefined because there is no height property in object 24 | 25 | // add item to object 26 | employee.favoriteFood = 'Fish & Chips'; 27 | employee['department'] = 'Marketing'; 28 | 29 | // or update values 30 | employee.age = 26; 31 | 32 | console.log(employee); 33 | 34 | // delete an item from object 35 | delete employee.favoriteFood; 36 | 37 | console.log(employee); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /012_IntroToAppsScript_Loops.js: -------------------------------------------------------------------------------- 1 | // for loop example 2 | function forLoopExample() { 3 | 4 | const fruitsArray = ['Apple','Banana','Pear','Strawberry']; 5 | console.log(fruitsArray); 6 | console.log(fruitsArray.length); // 4 7 | 8 | console.log(fruitsArray[0]); 9 | 10 | // loop 0, 1, 2, 3 then stop 11 | // keep looping whilst less than 4 12 | for (let i = 0; i < fruitsArray.length; i++) { 13 | console.log(i); 14 | console.log(fruitsArray[i]); 15 | } 16 | } 17 | 18 | // forEach loop example 19 | function forEachLoopExample() { 20 | 21 | const numberArray = ['one', 'two', 'three', 'four']; 22 | 23 | numberArray.forEach(function(item,i) { 24 | console.log(i); 25 | console.log(numberArray[i]); 26 | }); 27 | 28 | numberArray.forEach((item,i) => { 29 | console.log(i); 30 | console.log(numberArray[i]); 31 | }) 32 | } 33 | 34 | // function to convert celcius to farenheit 35 | const convertCtoF = (t) => (t * 9/5) + 32; 36 | 37 | // forEach loop example 2 38 | function forEachLoopExample2() { 39 | 40 | const celciusArray = [0,13,19,11,24,29,34,17,4]; 41 | const farenheitArray = []; 42 | 43 | celciusArray.forEach( (t) => { 44 | const f = convertCtoF(t); 45 | farenheitArray.push(f); 46 | }); 47 | 48 | console.log(farenheitArray); 49 | } 50 | 51 | // map loop example 52 | // map array method 53 | // creates a new array from existing applying a function 54 | function mapLoopExample() { 55 | 56 | const celciusArray = [0,13,19,11,24,29,34,17,4]; 57 | 58 | const farenheitArray = celciusArray.map(t => convertCtoF(t)); 59 | 60 | console.log(farenheitArray); 61 | } 62 | 63 | // looping over objects 64 | function objectLoop() { 65 | 66 | const employee = { 67 | name: "Joe Bloggs", 68 | age: 25, 69 | title: "Data Analyst" 70 | } 71 | 72 | // loop over objects with for in loop 73 | for (const property in employee) { 74 | console.log(property); 75 | console.log(employee[property]); // need to use square bracket notation 76 | } 77 | 78 | // cannot do forEach method on objects 79 | /* 80 | employee.forEach(function(item){ 81 | console.log(item); 82 | }); 83 | */ 84 | 85 | } -------------------------------------------------------------------------------- /013_IntroToAppsScript_SpreadsheetService.js: -------------------------------------------------------------------------------- 1 | // get name of our sheet 2 | function getName() { 3 | const ss = SpreadsheetApp.getActive(); 4 | const name = ss.getName(); 5 | console.log(name); 6 | } 7 | 8 | // get data out of Sheet 9 | function getData1() { 10 | const ss = SpreadsheetApp.getActive(); 11 | const sheet = ss.getActiveSheet(); 12 | const data = sheet.getDataRange(); 13 | const values = data.getValues(); 14 | console.log(values); 15 | } 16 | 17 | /* 18 | 19 | [ 20 | [ 'Fruit', 'Cost', 'Quantity' ], 21 | [ 'Apple', 0.86, 4 ], 22 | [ 'Banana', 0.82, 2 ], 23 | [ 'Pear', 0.52, 7 ], 24 | [ 'Watermelon', 1.74, 2 ], 25 | [ 'Kiwi', 0.99, 3 ], 26 | [ 'Strawberry', 0.4, 25 ] 27 | ] 28 | 29 | */ 30 | 31 | // more direct method 32 | function getData2() { 33 | const sheet = SpreadsheetApp.getActiveSheet(); 34 | console.log(sheet.getDataRange().getValues()); 35 | } 36 | 37 | // get Sheet by name 38 | function getData3() { 39 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 40 | const sheet1 = ss.getSheetByName('Sheet1'); 41 | console.log(sheet1.getDataRange().getValues()); 42 | } 43 | 44 | // active range 45 | function getData4() { 46 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 47 | const sheet1 = ss.getSheetByName('Sheet1'); 48 | console.log(sheet1.getActiveRange().getValues()); 49 | } 50 | 51 | // get data by A1 notation 52 | function getData5() { 53 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 54 | const sheet1 = ss.getSheetByName('Sheet1'); 55 | 56 | let data = sheet1.getRange('A1:C4').getValues(); 57 | console.log(data); 58 | 59 | } 60 | 61 | // get data by range coordinates 62 | function getData6() { 63 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 64 | const sheet1 = ss.getSheetByName('Sheet1'); 65 | 66 | let data1 = sheet1.getRange(1,1).getValue(); 67 | console.log(data1); 68 | 69 | let data2 = sheet1.getRange(1,1,4,3).getValues(); 70 | console.log(data2); 71 | 72 | let data3 = sheet1.getRange(1,1,7,2).getValues(); 73 | console.log(data3); 74 | 75 | } -------------------------------------------------------------------------------- /014_IntroToAppsScript_WorkingWithData.js: -------------------------------------------------------------------------------- 1 | // calculate the row totals 2 | function calculateRowTotals() { 3 | 4 | // get the spreadsheet object and the sheet 5 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 6 | const sheet1 = ss.getSheetByName('Sheet1'); 7 | 8 | // get the data 9 | const data = sheet1.getRange(2,1,6,3).getValues(); 10 | //console.log(data); 11 | 12 | /* 13 | [ 14 | [ 'Apple', 0.86, 4 ], 15 | [ 'Banana', 0.82, 2 ], 16 | [ 'Pear', 0.52, 7 ], 17 | [ 'Watermelon', 1.74, 2 ], 18 | [ 'Kiwi', 0.99, 3 ], 19 | [ 'Strawberry', 0.4, 25 ] 20 | ] 21 | */ 22 | 23 | // loop over the data and do the calculation 24 | // log it 25 | data.forEach(row => { 26 | console.log(row); // [ 'Strawberry', 0.4, 25 ] 27 | //console.log(row[0]); 28 | //console.log(row[1]); 29 | //console.log(row[2]); 30 | const name = row[0]; 31 | const cost = row[1]; 32 | const quantity = row[2]; 33 | 34 | const total = cost * quantity; 35 | 36 | console.log(name + ': $' + total); 37 | 38 | }) 39 | } -------------------------------------------------------------------------------- /015_IntroToAppsScript_PuttingDataBackIntoSheets.js: -------------------------------------------------------------------------------- 1 | // add total for each row into our Sheet 2 | function addRowTotals() { 3 | 4 | const ss = SpreadsheetApp.getActive(); 5 | const sheet1 = ss.getSheetByName("Sheet1"); 6 | const lastRow = sheet1.getLastRow(); 7 | 8 | const data = sheet1.getRange(1,1,lastRow,3).getValues(); 9 | console.log(data); 10 | 11 | // remove header row 12 | data.shift(); 13 | console.log(data); 14 | 15 | const totalsArray = []; 16 | 17 | data.forEach(row => { 18 | 19 | const cost = row[1]; 20 | const quantity = row[2]; 21 | const total = cost * quantity; 22 | 23 | //row.push(total); 24 | //console.log(row); 25 | 26 | totalsArray.push([total]); 27 | 28 | }); 29 | 30 | console.log(totalsArray); 31 | 32 | // paste data back into Sheet 33 | sheet1.getRange(2,4,lastRow - 1,1).setValues(totalsArray); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /016_IntroToAppsScript_CustomMenus.js: -------------------------------------------------------------------------------- 1 | // add total for each row into our Sheet 2 | function addRowTotals() { 3 | 4 | const ss = SpreadsheetApp.getActive(); 5 | const sheet1 = ss.getSheetByName("Sheet1"); 6 | const lastRow = sheet1.getLastRow(); 7 | 8 | const data = sheet1.getRange(1,1,lastRow,3).getValues(); 9 | console.log(data); 10 | 11 | // remove header row 12 | data.shift(); 13 | console.log(data); 14 | 15 | const totalsArray = []; 16 | 17 | data.forEach(row => { 18 | 19 | const cost = row[1]; 20 | const quantity = row[2]; 21 | const total = cost * quantity; 22 | 23 | //row.push(total); 24 | //console.log(row); 25 | 26 | totalsArray.push([total]); 27 | 28 | }); 29 | 30 | console.log(totalsArray); 31 | 32 | // paste data back into Sheet 33 | sheet1.getRange(2,4,lastRow - 1,1).setValues(totalsArray); 34 | 35 | } 36 | 37 | 38 | // add menu 39 | // onOpen is a special function 40 | // runs when your Sheet opens 41 | function onOpen() { 42 | 43 | const ui = SpreadsheetApp.getUi(); 44 | 45 | ui.createMenu("Custom Menu") 46 | .addItem("Add Row Totals","addRowTotals") 47 | .addToUi(); 48 | 49 | } -------------------------------------------------------------------------------- /017_IntroToAppsScript_addingFormulas.js: -------------------------------------------------------------------------------- 1 | // add total for each row into our Sheet 2 | function addRowTotals() { 3 | 4 | const ss = SpreadsheetApp.getActive(); 5 | const sheet1 = ss.getSheetByName('Sheet1'); 6 | const lastRow = sheet1.getLastRow(); 7 | 8 | const data = sheet1.getRange(2,1,lastRow - 1,3).getValues(); 9 | 10 | console.log(data); 11 | 12 | const totalsArray = []; 13 | 14 | data.forEach(function(row) { 15 | 16 | const name = row[0]; 17 | const cost = row[1]; 18 | const quantity = row[2]; 19 | 20 | const total = cost * quantity; 21 | 22 | row.push(total); 23 | 24 | totalsArray.push([total]); 25 | 26 | console.log(row); 27 | 28 | }); 29 | 30 | console.log(totalsArray); 31 | 32 | // paste data back into Sheet 33 | sheet1.getRange(2,4,lastRow - 1,1).setValues(totalsArray); 34 | 35 | } 36 | 37 | 38 | // add menu 39 | // onOpen is a special function 40 | // runs when your Sheet opens 41 | function onOpen() { 42 | 43 | const ui = SpreadsheetApp.getUi(); 44 | 45 | ui.createMenu('Custom Menu') 46 | .addItem('Add Row Totals','addRowTotals') 47 | .addItem('Add Grand Total','grandTotal') 48 | .addToUi(); 49 | 50 | } 51 | 52 | 53 | // add grand total function 54 | function grandTotal() { 55 | 56 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 57 | const sheet1 = ss.getSheetByName('Sheet1'); 58 | const lastRow = sheet1.getLastRow(); 59 | const lastColumn = sheet1.getLastColumn(); 60 | 61 | // add total row 62 | sheet1.getRange(lastRow + 1,1).setValue('TOTAL'); 63 | sheet1.getRange(lastRow + 1, lastColumn).setFormula('=SUM(D2:D' + lastRow + ')'); 64 | 65 | } -------------------------------------------------------------------------------- /018_IntroToAppsScript_Formatting.js: -------------------------------------------------------------------------------- 1 | // add total for each row into our Sheet 2 | function addRowTotals() { 3 | 4 | const ss = SpreadsheetApp.getActive(); 5 | const sheet1 = ss.getSheetByName('Sheet1'); 6 | const lastRow = sheet1.getLastRow(); 7 | 8 | const data = sheet1.getRange(2,1,lastRow - 1,3).getValues(); 9 | 10 | console.log(data); 11 | 12 | const totalsArray = []; 13 | 14 | data.forEach(function(row) { 15 | 16 | const name = row[0]; 17 | const cost = row[1]; 18 | const quantity = row[2]; 19 | 20 | const total = cost * quantity; 21 | 22 | row.push(total); 23 | 24 | totalsArray.push([total]); 25 | 26 | console.log(row); 27 | 28 | }); 29 | 30 | console.log(totalsArray); 31 | 32 | // paste data back into Sheet 33 | sheet1.getRange(2,4,lastRow - 1,1).setValues(totalsArray); 34 | 35 | } 36 | 37 | 38 | // add menu 39 | // onOpen is a special function 40 | // runs when your Sheet opens 41 | function onOpen() { 42 | 43 | const ui = SpreadsheetApp.getUi(); 44 | 45 | ui.createMenu('Custom Menu') 46 | .addItem('Add Row Totals','addRowTotals') 47 | .addItem('Add Grand Total','grandTotal') 48 | .addItem('Format Table','formatTable') 49 | .addToUi(); 50 | 51 | } 52 | 53 | 54 | // add grand total function 55 | function grandTotal() { 56 | 57 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 58 | const sheet1 = ss.getSheetByName('Sheet1'); 59 | const lastRow = sheet1.getLastRow(); 60 | const lastColumn = sheet1.getLastColumn(); 61 | 62 | // add total row 63 | sheet1.getRange(lastRow + 1,1).setValue('TOTAL'); 64 | sheet1.getRange(lastRow + 1, lastColumn).setFormula('=SUM(D2:D' + lastRow + ')'); 65 | 66 | } 67 | 68 | 69 | // format the table 70 | function formatTable() { 71 | 72 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 73 | const sheet1 = ss.getSheetByName('Sheet1'); 74 | const lastRow = sheet1.getLastRow(); 75 | const lastColumn = sheet1.getLastColumn(); 76 | const dataRange = sheet1.getDataRange(); 77 | 78 | // orange row banding 79 | dataRange.applyRowBanding(SpreadsheetApp.BandingTheme.ORANGE,true,true); 80 | 81 | // add dollar signs to totals 82 | sheet1.getRange(2,lastColumn,lastRow - 1,1).setNumberFormat('$#,##0.00'); 83 | 84 | // make the grand total row bold 85 | sheet1.getRange(lastRow,1,1,lastColumn).setFontWeight('bold'); 86 | 87 | } 88 | -------------------------------------------------------------------------------- /019_IntroToAppsScript_Charts.js: -------------------------------------------------------------------------------- 1 | // add total for each row into our Sheet 2 | function addRowTotals() { 3 | 4 | const ss = SpreadsheetApp.getActive(); 5 | const sheet1 = ss.getSheetByName('Sheet1'); 6 | const lastRow = sheet1.getLastRow(); 7 | 8 | const data = sheet1.getRange(2,1,lastRow - 1,3).getValues(); 9 | 10 | console.log(data); 11 | 12 | const totalsArray = []; 13 | 14 | data.forEach(function(row) { 15 | 16 | const name = row[0]; 17 | const cost = row[1]; 18 | const quantity = row[2]; 19 | 20 | const total = cost * quantity; 21 | 22 | row.push(total); 23 | 24 | totalsArray.push([total]); 25 | 26 | console.log(row); 27 | 28 | }); 29 | 30 | console.log(totalsArray); 31 | 32 | // paste data back into Sheet 33 | sheet1.getRange(2,4,lastRow - 1,1).setValues(totalsArray); 34 | 35 | } 36 | 37 | 38 | // add menu 39 | // onOpen is a special function 40 | // runs when your Sheet opens 41 | function onOpen() { 42 | 43 | const ui = SpreadsheetApp.getUi(); 44 | 45 | ui.createMenu('Custom Menu') 46 | .addItem('Add Row Totals','addRowTotals') 47 | .addItem('Add Grand Total','grandTotal') 48 | .addItem('Format Table','formatTable') 49 | .addItem('Add Chart','addChart') 50 | .addToUi(); 51 | 52 | } 53 | 54 | 55 | // add grand total function 56 | function grandTotal() { 57 | 58 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 59 | const sheet1 = ss.getSheetByName('Sheet1'); 60 | const lastRow = sheet1.getLastRow(); 61 | const lastColumn = sheet1.getLastColumn(); 62 | 63 | // add total row 64 | sheet1.getRange(lastRow + 1,1).setValue('TOTAL'); 65 | sheet1.getRange(lastRow + 1, lastColumn).setFormula('=SUM(D2:D' + lastRow + ')'); 66 | 67 | } 68 | 69 | 70 | // format the table 71 | function formatTable() { 72 | 73 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 74 | const sheet1 = ss.getSheetByName('Sheet1'); 75 | const lastRow = sheet1.getLastRow(); 76 | const lastColumn = sheet1.getLastColumn(); 77 | const dataRange = sheet1.getDataRange(); 78 | 79 | // orange row banding 80 | dataRange.applyRowBanding(SpreadsheetApp.BandingTheme.ORANGE,true,true); 81 | 82 | // add dollar signs to totals 83 | sheet1.getRange(2,lastColumn,lastRow - 1,1).setNumberFormat('$#,##0.00'); 84 | 85 | // make the grand total row bold 86 | sheet1.getRange(lastRow,1,1,lastColumn).setFontWeight('bold'); 87 | 88 | } 89 | 90 | 91 | // add a chart 92 | function addChart() { 93 | 94 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 95 | const sheet1 = ss.getSheetByName('Sheet1'); 96 | const lastRow = sheet1.getLastRow(); 97 | const lastColumn = sheet1.getLastColumn(); 98 | 99 | // get data labels and values 100 | const totalChartLabels = sheet1.getRange(1,1,lastRow - 1,1); 101 | const totalChartValues = sheet1.getRange(1,lastColumn,lastRow - 1,1); 102 | 103 | // create the chart 104 | const totalsChart = sheet1.newChart() 105 | .setChartType(Charts.ChartType.BAR) 106 | .addRange(totalChartLabels) 107 | .addRange(totalChartValues) 108 | .setMergeStrategy(Charts.ChartMergeStrategy.MERGE_COLUMNS) 109 | .setPosition(1,5,0,0) 110 | .setNumHeaders(1) 111 | .setOption('title','Fruit Chart') 112 | .build(); 113 | 114 | // insert Chart into Sheet 115 | sheet1.insertChart(totalsChart); 116 | 117 | 118 | /* 119 | const dataRange = sheet1.getRange('A1:B9'); 120 | console.log(dataRange.getValues()); 121 | 122 | const myNewChart = sheet1.newChart(); 123 | 124 | myNewChart.addRange(dataRange) 125 | .setChartType(Charts.ChartType.BAR) 126 | .setPosition(1,5,0,0) 127 | .setNumHeaders(1) 128 | .setOption('title','Fruit Chart'); 129 | 130 | sheet1.insertChart(myNewChart.build()); 131 | */ 132 | 133 | } 134 | -------------------------------------------------------------------------------- /020_IntroToAppsScript_Project1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson -------------------------------------------------------------------------------- /021_IntroToAppsScript_Project2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form 12 | // There is no code for this lesson -------------------------------------------------------------------------------- /022_IntroToAppsScript_Project3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ -------------------------------------------------------------------------------- /023_IntroToAppsScript_Project4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ 35 | 36 | // Project Lesson 4: update the Google Form 37 | function updateForm_v1() { 38 | 39 | // get the language data from the Sheet 40 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 41 | const setupSheet = ss.getSheetByName('setup'); 42 | const langVals = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues(); 43 | console.log(langVals); 44 | // [ [ 'None' ], [ 'Apps Script' ] ] 45 | 46 | const langValsFlat = langVals.map(item => item[0]); // ['None'] => 'None' 47 | console.log(langValsFlat); 48 | // [ 'None', 'Apps Script' ] // flattened array 49 | 50 | // add these languages to the form now 51 | // get the form 52 | const form = FormApp.openById(FORM_ID); 53 | const langsCheckboxQuestion = form.getItemById('1860180947').asCheckboxItem(); 54 | 55 | // populate the Form checkbox question with new language data 56 | langsCheckboxQuestion.setChoiceValues(langValsFlat); 57 | 58 | } -------------------------------------------------------------------------------- /024_IntroToAppsScript_Project5.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ 35 | 36 | // Project Lesson 4: update the Google Form 37 | function updateForm_v1() { 38 | 39 | // get the language data from the Sheet 40 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 41 | const setupSheet = ss.getSheetByName('setup'); 42 | const langVals = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues(); 43 | console.log(langVals); 44 | // [ [ 'None' ], [ 'Apps Script' ] ] 45 | 46 | const langValsFlat = langVals.map(item => item[0]); // ['None'] => 'None' 47 | console.log(langValsFlat); 48 | // [ 'None', 'Apps Script' ] // flattened array 49 | 50 | // add these languages to the form now 51 | // get the form 52 | const form = FormApp.openById(FORM_ID); 53 | const langsCheckboxQuestion = form.getItemById('1860180947').asCheckboxItem(); 54 | 55 | // populate the Form checkbox question with new language data 56 | langsCheckboxQuestion.setChoiceValues(langValsFlat); 57 | 58 | } 59 | 60 | // Project Lesson 5: Sending emails automatically with Apps Script 61 | function sendEmail_v1() { 62 | 63 | // get spreadsheet 64 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 65 | const responseSheet = ss.getSheetByName('Form Responses 1'); 66 | const data = responseSheet.getDataRange().getValues(); 67 | console.log(data); 68 | 69 | // remove the header row 70 | data.shift(); 71 | console.log(data); 72 | 73 | // loop over data 74 | data.forEach((row,i) => { 75 | 76 | // identify rows I haven't replied to yet 77 | if (row[5] === '') { 78 | 79 | // get email address 80 | const email = row[2]; 81 | 82 | // write the email 83 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 84 | let body = ''; 85 | 86 | // change the body for yes and no 87 | // yes answer 88 | if(row[3] === 'Yes') { 89 | body = 'TBC - Yes answer'; 90 | } 91 | // no answer 92 | else { 93 | body = 'TBC - No answer'; 94 | } 95 | 96 | // send email 97 | GmailApp.sendEmail(email,subject,body); 98 | 99 | // mark as sent 100 | const d = new Date(); 101 | responseSheet.getRange(i + 2,6).setValue(d); 102 | 103 | } 104 | else { 105 | console.log('No email sent for this row'); 106 | } 107 | }); 108 | } 109 | 110 | -------------------------------------------------------------------------------- /025_IntroToAppsScript_Project6.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ 35 | 36 | // Project Lesson 4: update the Google Form 37 | function updateForm_v1() { 38 | 39 | // get the language data from the Sheet 40 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 41 | const setupSheet = ss.getSheetByName('setup'); 42 | const langVals = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues(); 43 | console.log(langVals); 44 | // [ [ 'None' ], [ 'Apps Script' ] ] 45 | 46 | const langValsFlat = langVals.map(item => item[0]); // ['None'] => 'None' 47 | console.log(langValsFlat); 48 | // [ 'None', 'Apps Script' ] // flattened array 49 | 50 | // add these languages to the form now 51 | // get the form 52 | const form = FormApp.openById(FORM_ID); 53 | const langsCheckboxQuestion = form.getItemById('1860180947').asCheckboxItem(); 54 | 55 | // populate the Form checkbox question with new language data 56 | langsCheckboxQuestion.setChoiceValues(langValsFlat); 57 | 58 | } 59 | 60 | // Project Lesson 5: Sending emails automatically with Apps Script 61 | // version 1 62 | function sendEmail_v1() { 63 | 64 | // get spreadsheet 65 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 66 | const responseSheet = ss.getSheetByName('Form Responses 1'); 67 | const data = responseSheet.getDataRange().getValues(); 68 | console.log(data); 69 | 70 | // remove the header row 71 | data.shift(); 72 | console.log(data); 73 | 74 | // loop over data 75 | data.forEach((row,i) => { 76 | 77 | // identify rows I haven't replied to yet 78 | if (row[5] === '') { 79 | 80 | // get email address 81 | const email = row[2]; 82 | 83 | // write the email 84 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 85 | let body = ''; 86 | 87 | // change the body for yes and no 88 | // yes answer 89 | if(row[3] === 'Yes') { 90 | body = 'TBC - Yes answer'; 91 | } 92 | // no answer 93 | else { 94 | body = 'TBC - No answer'; 95 | } 96 | 97 | // send email 98 | GmailApp.sendEmail(email,subject,body); 99 | 100 | // mark as sent 101 | const d = new Date(); 102 | responseSheet.getRange(i + 2,6).setValue(d); 103 | 104 | } 105 | else { 106 | console.log('No email sent for this row'); 107 | } 108 | }); 109 | } 110 | 111 | 112 | // Project Lesson 6: Sending enhanced HTML emails automatically with Apps Script 113 | // version 2 114 | function sendEmail_v2() { 115 | 116 | // get the spreadsheet information 117 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 118 | const responseSheet = ss.getSheetByName('Form Responses 1'); 119 | const data = responseSheet.getDataRange().getValues(); 120 | //console.log(data); 121 | 122 | // remove the header 123 | data.shift(); 124 | //console.log(data); 125 | 126 | // loop over the rows 127 | data.forEach((row,i) => { 128 | 129 | // identify ones I haven't replied to 130 | if (row[5] === '') { 131 | 132 | // get the email address 133 | const name = row[1]; 134 | const email = row[2]; 135 | const answer = row[3]; // yes/no 136 | const langs = row[4]; // list of languages 137 | 138 | // write the email 139 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 140 | let body = ''; 141 | 142 | // change the body for yes and no 143 | // yes answer 144 | if (answer === 'Yes') { 145 | body = 'Hi ' + name +`,

146 | Thank you for responding to our 2019 Developer Survey!

147 | Your feedback is greatly appreciated.

148 | You reported experience with the following coding languages:

149 | ` + langs + `

150 | Thanks,
151 | Ben`; 152 | } 153 | // no answer 154 | else { 155 | body = 'Hi ' + name +`,

156 | Thank you for responding to our 2019 Developer Survey!

157 | Your feedback is greatly appreciated.

158 | You reported not having any experience with coding, so here's a resource to get started:

159 | Getting started with Apps Script

160 | Thanks,
161 | Ben`; 162 | } 163 | //console.log(email); 164 | //console.log(subject); 165 | //console.log(body); 166 | 167 | // send the email 168 | GmailApp.sendEmail(email,subject,'',{htmlBody: body}); 169 | 170 | // mark as sent 171 | const d = new Date(); 172 | responseSheet.getRange(i + 2,6).setValue(d); 173 | 174 | } 175 | else { 176 | console.log('No email sent for this row'); 177 | } 178 | }); 179 | } 180 | 181 | // add a cutsom menu to our Sheet 182 | function onOpen() { 183 | 184 | const ui = SpreadsheetApp.getUi(); 185 | 186 | ui.createMenu("Questionnaire Menu") 187 | .addItem("Update Form","updateForm_v1") 188 | .addItem("Send Emails","sendEmail_v2") 189 | .addToUi(); 190 | 191 | } -------------------------------------------------------------------------------- /026_IntroToAppsScript_Project7.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ 35 | 36 | // Project Lesson 4: update the Google Form 37 | function updateForm_v1() { 38 | 39 | // get the language data from the Sheet 40 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 41 | const setupSheet = ss.getSheetByName('setup'); 42 | const langVals = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues(); 43 | console.log(langVals); 44 | // [ [ 'None' ], [ 'Apps Script' ] ] 45 | 46 | const langValsFlat = langVals.map(item => item[0]); // ['None'] => 'None' 47 | console.log(langValsFlat); 48 | // [ 'None', 'Apps Script' ] // flattened array 49 | 50 | // add these languages to the form now 51 | // get the form 52 | const form = FormApp.openById(FORM_ID); 53 | const langsCheckboxQuestion = form.getItemById('1860180947').asCheckboxItem(); 54 | 55 | // populate the Form checkbox question with new language data 56 | langsCheckboxQuestion.setChoiceValues(langValsFlat); 57 | 58 | } 59 | 60 | // Project Lesson 5: Sending emails automatically with Apps Script 61 | // version 1 62 | function sendEmail_v1() { 63 | 64 | // get spreadsheet 65 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 66 | const responseSheet = ss.getSheetByName('Form Responses 1'); 67 | const data = responseSheet.getDataRange().getValues(); 68 | console.log(data); 69 | 70 | // remove the header row 71 | data.shift(); 72 | console.log(data); 73 | 74 | // loop over data 75 | data.forEach((row,i) => { 76 | 77 | // identify rows I haven't replied to yet 78 | if (row[5] === '') { 79 | 80 | // get email address 81 | const email = row[2]; 82 | 83 | // write the email 84 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 85 | let body = ''; 86 | 87 | // change the body for yes and no 88 | // yes answer 89 | if(row[3] === 'Yes') { 90 | body = 'TBC - Yes answer'; 91 | } 92 | // no answer 93 | else { 94 | body = 'TBC - No answer'; 95 | } 96 | 97 | // send email 98 | GmailApp.sendEmail(email,subject,body); 99 | 100 | // mark as sent 101 | const d = new Date(); 102 | responseSheet.getRange(i + 2,6).setValue(d); 103 | 104 | } 105 | else { 106 | console.log('No email sent for this row'); 107 | } 108 | }); 109 | } 110 | 111 | 112 | // Project Lesson 6: Sending enhanced HTML emails automatically with Apps Script 113 | // version 2 114 | function sendEmail_v2() { 115 | 116 | // get the spreadsheet information 117 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 118 | const responseSheet = ss.getSheetByName('Form Responses 1'); 119 | const data = responseSheet.getDataRange().getValues(); 120 | //console.log(data); 121 | 122 | // remove the header 123 | data.shift(); 124 | //console.log(data); 125 | 126 | // loop over the rows 127 | data.forEach((row,i) => { 128 | 129 | // identify ones I haven't replied to 130 | if (row[5] === '') { 131 | 132 | // get the email address 133 | const name = row[1]; 134 | const email = row[2]; 135 | const answer = row[3]; // yes/no 136 | const langs = row[4]; // list of languages 137 | 138 | // write the email 139 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 140 | let body = ''; 141 | 142 | // change the body for yes and no 143 | // yes answer 144 | if (answer === 'Yes') { 145 | body = 'Hi ' + name +`,

146 | Thank you for responding to our 2019 Developer Survey!

147 | Your feedback is greatly appreciated.

148 | You reported experience with the following coding languages:

149 | ` + langs + `

150 | Thanks,
151 | Ben`; 152 | } 153 | // no answer 154 | else { 155 | body = 'Hi ' + name +`,

156 | Thank you for responding to our 2019 Developer Survey!

157 | Your feedback is greatly appreciated.

158 | You reported not having any experience with coding, so here's a resource to get started:

159 | Getting started with Apps Script

160 | Thanks,
161 | Ben`; 162 | } 163 | //console.log(email); 164 | //console.log(subject); 165 | //console.log(body); 166 | 167 | // send the email 168 | GmailApp.sendEmail(email,subject,'',{htmlBody: body}); 169 | 170 | // mark as sent 171 | const d = new Date(); 172 | responseSheet.getRange(i + 2,6).setValue(d); 173 | 174 | } 175 | else { 176 | console.log('No email sent for this row'); 177 | } 178 | }); 179 | } 180 | 181 | // add a cutsom menu to our Sheet 182 | function onOpen() { 183 | 184 | const ui = SpreadsheetApp.getUi(); 185 | 186 | ui.createMenu("Questionnaire Menu") 187 | .addItem("Update Form","updateForm_v1") 188 | .addItem("Send Emails","sendEmail_v2") 189 | .addToUi(); 190 | 191 | } 192 | 193 | // Project Lesson 7: automatically update the form 194 | // version 2 195 | function updateForm_v2() { 196 | 197 | // get list of langs in form question 198 | const form = FormApp.openById(FORM_ID); 199 | const formCheckboxChoices = form.getItemById('1860180947').asCheckboxItem().getChoices(); 200 | const formCheckboxValues = formCheckboxChoices.map(x => x.getValue()); 201 | //console.log(formCheckboxValues); // [ 'None', 'Apps Script', 'Python', 'VBA', 'R' ] 202 | //console.log(formCheckboxValues[1]); 203 | //console.log(formCheckboxValues[1].length); 204 | 205 | // get list of langs in setup sheet 206 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 207 | const setupSheet = ss.getSheetByName('setup'); 208 | const setupSheetValues = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues().flat(); 209 | 210 | //console.log(setupSheetValues); // [ 'None', 'Apps Script', 'Python', 'VBA' ] 211 | //console.log(setupSheetValues[1]); 212 | //console.log(setupSheetValues[1].length); 213 | 214 | // get list of langs submitted via the form 215 | const responsesSheet = ss.getSheetByName('Form Responses 1'); 216 | const data = responsesSheet.getRange(2,1,responsesSheet.getLastRow()-1,6).getValues(); 217 | const submittedFormValues = data.map(row => row[4]).join().split(','); 218 | //console.log(submittedFormValues); // [ 'None', 'Apps Script, Python, VBA, R', 'Java' ] 219 | //console.log(submittedFormValues[1]); 220 | //console.log(submittedFormValues[1].length); 221 | 222 | // consolidate list of langs 223 | const allLangs = [...formCheckboxValues,...setupSheetValues,...submittedFormValues]; 224 | //const allLangs = (formCheckboxValues.concat(setupSheetValues)).concat(submittedFormValues); 225 | //console.log(allLangs); 226 | // [None, Apps Script, Python, VBA, R, None, Apps Script, Python, VBA, None, Apps Script, Python, VBA, R, Java] 227 | 228 | // remove leading and trailing spaces from langs 229 | const trimAllLangs = allLangs.map(item => item.trim()); 230 | //console.log(trimAllLangs); 231 | 232 | // sort list of langs 233 | trimAllLangs.sort(); 234 | console.log(trimAllLangs); 235 | 236 | // dedup list of langs 237 | // use let because I'm going to reassign it 238 | let finalLangList = trimAllLangs.filter((lang,i) => trimAllLangs.indexOf(lang) === i); 239 | console.log(finalLangList); 240 | console.log(finalLangList.length); 241 | console.log(finalLangList[0]); 242 | console.log(finalLangList[0].length); 243 | //console.log(finalLangList[1].length); 244 | 245 | // remove any blanks 246 | finalLangList = finalLangList.filter(item => item.length !== 0); 247 | console.log(finalLangList); 248 | console.log(finalLangList.length); 249 | 250 | // move 'None' to front of array 251 | finalLangList = finalLangList.filter(item => item !== 'None'); 252 | finalLangList.unshift('None'); 253 | console.log(finalLangList); 254 | //console.log(finalLangList.length); 255 | 256 | // turn into double array notation for Sheets 257 | const finalDoubleArray = finalLangList.map(lang => [lang]); 258 | //console.log(finalDoubleArray); 259 | //console.log(finalDoubleArray.length); 260 | 261 | // paste into sheet in setup tab 262 | setupSheet.getRange("A2:A").clear(); 263 | setupSheet.getRange(2,1,finalLangList.length,1).setValues(finalDoubleArray); 264 | 265 | // copy into the Form 266 | form.getItemById('1860180947').asCheckboxItem().setChoiceValues(finalLangList); // use the array of strings for the Form, NOT the double array like Sheets 267 | 268 | } -------------------------------------------------------------------------------- /027_IntroToAppsScript_Project8.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Introduction To Apps Script 4 | * Project: Coding Questionnaire 5 | * 6 | */ 7 | 8 | // Project Lesson 1: Intro 9 | // There is no code for this lesson 10 | 11 | // Project Lesson 2: Setup Google Form & global variables 12 | // switch for your own Google Form ID 13 | // get from URL (X's in following example) 14 | // https://docs.google.com/forms/d/XXXXXXXXXXXXXXXXXXXXXXXXX/edit 15 | const FORM_ID = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; // <-- put your Form ID in here 16 | 17 | // Project Lesson 3 18 | // function to find the Form IDs 19 | function findFormIDs() { 20 | 21 | const form = FormApp.openById(FORM_ID); 22 | const formItems = form.getItems(); 23 | 24 | formItems.forEach(item => console.log(item.getTitle() + ' ' + item.getId())); 25 | 26 | } 27 | 28 | /* 29 | 1:32:41 PM Notice Execution started 30 | 1:32:42 PM Info Name: 2120132702 31 | 1:32:42 PM Info Do you have prior coding experience? 267233812 32 | 1:32:42 PM Info What programming languages do you use? 1860180947 33 | 1:32:42 PM Notice Execution completed 34 | */ 35 | 36 | // Project Lesson 4: update the Google Form 37 | function updateForm_v1() { 38 | 39 | // get the language data from the Sheet 40 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 41 | const setupSheet = ss.getSheetByName('setup'); 42 | const langVals = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues(); 43 | console.log(langVals); 44 | // [ [ 'None' ], [ 'Apps Script' ] ] 45 | 46 | const langValsFlat = langVals.map(item => item[0]); // ['None'] => 'None' 47 | console.log(langValsFlat); 48 | // [ 'None', 'Apps Script' ] // flattened array 49 | 50 | // add these languages to the form now 51 | // get the form 52 | const form = FormApp.openById(FORM_ID); 53 | const langsCheckboxQuestion = form.getItemById('1860180947').asCheckboxItem(); 54 | 55 | // populate the Form checkbox question with new language data 56 | langsCheckboxQuestion.setChoiceValues(langValsFlat); 57 | 58 | } 59 | 60 | // Project Lesson 5: Sending emails automatically with Apps Script 61 | // version 1 62 | function sendEmail_v1() { 63 | 64 | // get spreadsheet 65 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 66 | const responseSheet = ss.getSheetByName('Form Responses 1'); 67 | const data = responseSheet.getDataRange().getValues(); 68 | console.log(data); 69 | 70 | // remove the header row 71 | data.shift(); 72 | console.log(data); 73 | 74 | // loop over data 75 | data.forEach((row,i) => { 76 | 77 | // identify rows I haven't replied to yet 78 | if (row[5] === '') { 79 | 80 | // get email address 81 | const email = row[2]; 82 | 83 | // write the email 84 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 85 | let body = ''; 86 | 87 | // change the body for yes and no 88 | // yes answer 89 | if(row[3] === 'Yes') { 90 | body = 'TBC - Yes answer'; 91 | } 92 | // no answer 93 | else { 94 | body = 'TBC - No answer'; 95 | } 96 | 97 | // send email 98 | GmailApp.sendEmail(email,subject,body); 99 | 100 | // mark as sent 101 | const d = new Date(); 102 | responseSheet.getRange(i + 2,6).setValue(d); 103 | 104 | } 105 | else { 106 | console.log('No email sent for this row'); 107 | } 108 | }); 109 | } 110 | 111 | 112 | // Project Lesson 6: Sending enhanced HTML emails automatically with Apps Script 113 | // version 2 114 | function sendEmail_v2() { 115 | 116 | // get the spreadsheet information 117 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 118 | const responseSheet = ss.getSheetByName('Form Responses 1'); 119 | const data = responseSheet.getDataRange().getValues(); 120 | //console.log(data); 121 | 122 | // remove the header 123 | data.shift(); 124 | //console.log(data); 125 | 126 | // loop over the rows 127 | data.forEach((row,i) => { 128 | 129 | // identify ones I haven't replied to 130 | if (row[5] === '') { 131 | 132 | // get the email address 133 | const name = row[1]; 134 | const email = row[2]; 135 | const answer = row[3]; // yes/no 136 | const langs = row[4]; // list of languages 137 | 138 | // write the email 139 | const subject = 'Thank you for responding to the Apps Script questionnaire!'; 140 | let body = ''; 141 | 142 | // change the body for yes and no 143 | // yes answer 144 | if (answer === 'Yes') { 145 | body = 'Hi ' + name +`,

146 | Thank you for responding to our 2019 Developer Survey!

147 | Your feedback is greatly appreciated.

148 | You reported experience with the following coding languages:

149 | ` + langs + `

150 | Thanks,
151 | Ben`; 152 | } 153 | // no answer 154 | else { 155 | body = 'Hi ' + name +`,

156 | Thank you for responding to our 2019 Developer Survey!

157 | Your feedback is greatly appreciated.

158 | You reported not having any experience with coding, so here's a resource to get started:

159 | Getting started with Apps Script

160 | Thanks,
161 | Ben`; 162 | } 163 | //console.log(email); 164 | //console.log(subject); 165 | //console.log(body); 166 | 167 | // send the email 168 | GmailApp.sendEmail(email,subject,'',{htmlBody: body}); 169 | 170 | // mark as sent 171 | const d = new Date(); 172 | responseSheet.getRange(i + 2,6).setValue(d); 173 | 174 | } 175 | else { 176 | console.log('No email sent for this row'); 177 | } 178 | }); 179 | } 180 | 181 | // add a cutsom menu to our Sheet 182 | function onOpen() { 183 | 184 | const ui = SpreadsheetApp.getUi(); 185 | 186 | ui.createMenu("Questionnaire Menu") 187 | .addItem("Update Form","updateForm_v1") 188 | .addItem("Send Emails","sendEmail_v2") 189 | .addToUi(); 190 | 191 | } 192 | 193 | // Project Lesson 7: automatically update the form 194 | // version 2 195 | function updateForm_v2() { 196 | 197 | // get Sheet and Form variables 198 | const ss = SpreadsheetApp.getActiveSpreadsheet(); 199 | const form = FormApp.openById(FORM_ID); 200 | 201 | // get list of languages in setup sheet 202 | const setupSheet = ss.getSheetByName('setup'); 203 | const setupSheetValues = setupSheet.getRange(2,1,setupSheet.getLastRow()-1,1).getValues().flat(); 204 | //console.log(setupSheetValues); 205 | // [ 'None', 'Apps Script', 'Python', 'VBA' ] 206 | 207 | // get list of languages submitted via the form 208 | const responsesSheet = ss.getSheetByName('Form Responses 1'); 209 | const data = responsesSheet.getRange(2,5,responsesSheet.getLastRow()-1,1).getValues().flat(); 210 | const submittedFormValues = data.join().split(','); 211 | //console.log(submittedFormValues); 212 | // [ 'None', 'Apps Script, Python, VBA, R', 'Java' ] 213 | 214 | // get list of languages in form question 215 | const formCheckboxChoices = form.getItemById('1860180947').asCheckboxItem().getChoices(); 216 | const formCheckboxValues = formCheckboxChoices.map(x => x.getValue()); 217 | //console.log(formCheckboxValues); 218 | // [ 'None', 'Apps Script', 'Python', 'VBA', 'R' ] 219 | 220 | // consolidate list of languages 221 | const allLangs = [...formCheckboxValues,...setupSheetValues,...submittedFormValues]; 222 | //console.log(allLangs); 223 | // [None, Apps Script, Python, VBA, R, None, Apps Script, Python, VBA, None, Apps Script, Python, VBA, R, Java] 224 | 225 | // remove leading and trailing spaces from languages 226 | const trimAllLangs = allLangs.map(item => item.trim()); 227 | //console.log(trimAllLangs); 228 | 229 | // sort list of languages 230 | trimAllLangs.sort(); 231 | //console.log(trimAllLangs); 232 | 233 | // dedup list of languages 234 | // use let because I'm going to reassign it 235 | let finalLangList = trimAllLangs.filter((lang,i) => trimAllLangs.indexOf(lang) === i); 236 | //console.log(finalLangList); 237 | //console.log(finalLangList.length); 238 | 239 | // remove any blanks 240 | finalLangList = finalLangList.filter(item => item.length !== 0); 241 | //console.log(finalLangList); 242 | //console.log(finalLangList.length); 243 | 244 | // move 'None' to front of array 245 | finalLangList = finalLangList.filter(item => item !== 'None'); 246 | finalLangList.unshift('None'); 247 | //console.log(finalLangList); 248 | 249 | // turn into double array notation for Sheets 250 | const finalDoubleArray = finalLangList.map(lang => [lang]); 251 | //console.log(finalDoubleArray); 252 | 253 | // paste into sheet in setup tab 254 | setupSheet.getRange("A2:A").clear(); 255 | setupSheet.getRange(2,1,finalLangList.length,1).setValues(finalDoubleArray); 256 | 257 | // copy into the Form 258 | form.getItemById('1860180947').asCheckboxItem().setChoiceValues(finalLangList); 259 | 260 | } 261 | 262 | // Project lesson 8: add new triggers to run the update form 2 263 | // No additional code 264 | // set trigger to run updateForm_v2() every time form is submitted -------------------------------------------------------------------------------- /028_IntroToAppsScript_Project9.js: -------------------------------------------------------------------------------- 1 | // Project lesson 9: add new triggers to run the update form 2 2 | 3 | // No additional code 4 | 5 | // delete previous trigger 6 | // set trigger to run updateForm_v2() every time form is submitted 7 | // set 2nd trigger to run updateForm_v2() every time sheet is edited -------------------------------------------------------------------------------- /AppsScript_Intro copy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benlcollins/introductionToAppsScript/1862dd8f0e19d73a6a1cf0293b9bc1c07508a66d/AppsScript_Intro copy.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction To Apps Script 2 | 3 | ![Introduction To Apps Script](https://github.com/benlcollins/introductionToAppsScript/blob/main/AppsScript_Intro%20copy.jpg) 4 | 5 | ## A free, introductory course teaching Google Apps Script from scratch 6 | 7 | This GitHub folder contains code for the online course: [Introduction To Apps Script](https://courses.benlcollins.com/p/apps-script-blastoff) 8 | 9 | Go from zero coding knowledge to automating your work with Google Apps Script. 10 | 11 | This course will set you up to: 12 | 13 | * Understand what Google Apps Script is and why you should use it 14 | * Know the building blocks of Apps Script 15 | * Have the confidence to write your own programs 16 | * Build some cool automated tools you can use right away 17 | * Know your way around the Apps Script developer environment 18 | * ...and much, much more! 19 | 20 | Each lesson is taught through bite-sized, action-oriented 5 - 10 minute-long videos, covering practical techniques you can apply to your own business. 21 | 22 | This course will teach you the basic foundational techniques in Apps Script, even if you’re brand new to coding. 23 | 24 | Sign up here: [Introduction To Apps Script](https://courses.benlcollins.com/p/apps-script-blastoff) 25 | --------------------------------------------------------------------------------