├── 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 | 
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 |
--------------------------------------------------------------------------------