SlideShare a Scribd company logo
Google Sheets Programming With Google Apps
Script Michael Maguire download
https://ebookbell.com/product/google-sheets-programming-with-
google-apps-script-michael-maguire-5321876
Explore and download more ebooks at ebookbell.com
Here are some recommended products that we believe you will be
interested in. You can click the link to download.
Google Sheets Easy Coding For Beginners Learn Coding Fast Yao
https://ebookbell.com/product/google-sheets-easy-coding-for-beginners-
learn-coding-fast-yao-52856660
Improve Your Skills With Google Sheets Rmy Lentzner
https://ebookbell.com/product/improve-your-skills-with-google-sheets-
rmy-lentzner-23281692
Spreadsheets For Librarians Getting Results With Excel And Google
Sheets Bruce White
https://ebookbell.com/product/spreadsheets-for-librarians-getting-
results-with-excel-and-google-sheets-bruce-white-43398080
A Beginners Guide To Google Drive And Sheets Step By Step Detailed
Guide Tricks Tips And Shortcuts In Google Drive And Sheets William S
Page
https://ebookbell.com/product/a-beginners-guide-to-google-drive-and-
sheets-step-by-step-detailed-guide-tricks-tips-and-shortcuts-in-
google-drive-and-sheets-william-s-page-56901034
A Beginners Guide To Google Drive And Sheets Step By Step Detailed
Guide Tricks Tips Amd Shortcuts In Google Drive And Sheets 1st Edition
William S Page
https://ebookbell.com/product/a-beginners-guide-to-google-drive-and-
sheets-step-by-step-detailed-guide-tricks-tips-amd-shortcuts-in-
google-drive-and-sheets-1st-edition-william-s-page-12073556
Google Drive Docs In 30 Minutes The Unofficial Guide To The New Google
Drive Docs Sheets Slides 2nd Edition Ian Lamont
https://ebookbell.com/product/google-drive-docs-in-30-minutes-the-
unofficial-guide-to-the-new-google-drive-docs-sheets-slides-2nd-
edition-ian-lamont-6770030
Beginning Google Web Toolkit From Novice To Professional Beginning
From Novice To Professional 1st Edition Bram Smeets
https://ebookbell.com/product/beginning-google-web-toolkit-from-
novice-to-professional-beginning-from-novice-to-professional-1st-
edition-bram-smeets-1365342
Rainforest Google
https://ebookbell.com/product/rainforest-google-22521924
Android Developer Fundamentals Unit 1 2nd Edition Google Developer
Training Team
https://ebookbell.com/product/android-developer-fundamentals-
unit-1-2nd-edition-google-developer-training-team-36456436
Google Sheets Programming With Google Apps Script Michael Maguire
Google Sheets Programming With Google Apps Script Michael Maguire
Google Sheets Programming With
Google Apps Script (2015 Revision
In Progress)
Your Guide To Building Spreadsheet
Applications In The Cloud
Michael Maguire
©2016
Tweet This Book!
Please help Michael Maguire by spreading the word about this
book on Twitter!
The suggested hashtag for this book is
#googlespreadsheetprogramming.
Find out what other people are saying about the book by clicking
on this link to search for this hashtag on Twitter:
https://twitter.com/search?q=#googlespreadsheetprogramming
Contents
Chapter 1: Introduction . . . . . . . . . . . . . . . . . . . . 1
1.1 Google Sheets . . . . . . . . . . . . . . . . . . . . . 1
1.2 Google Apps Script (GAS) . . . . . . . . . . . . . . . 2
1.3 JavaScript or Google Apps Script? . . . . . . . . . . 3
1.4 Summary Of Topics Covered . . . . . . . . . . . . . 3
1.5 Software Requirements For This Book . . . . . . . . 5
1.6 Intended Readership . . . . . . . . . . . . . . . . . . 5
1.7 Book Code Available On GitHub . . . . . . . . . . . 6
1.8 My Blog On Google Spreadsheet Programming . . . 7
1.8 Guideline On Using This Book . . . . . . . . . . . . 7
1.9 2015 Update Notes . . . . . . . . . . . . . . . . . . . 8
Chapter 2: Getting Started . . . . . . . . . . . . . . . . . . 9
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Google Apps Script Examples . . . . . . . . . . . . . 9
2.2 Executing Code – One Function At A Time . . . . . 11
2.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . 14
Chapter 3: User-Defined Functions . . . . . . . . . . . . . 15
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 15
3.2 Built-in Versus User-Defined Functions . . . . . . . 16
3.3 Why Write User-Defined Functions . . . . . . . . . 17
3.4 What User-Defined Functions Cannot Do . . . . . . 18
3.5 Introducing JavaScript Functions . . . . . . . . . . . 21
3.6 User-Defined Functions Versus JavaScript Functions 25
3.7 Using JSDoc To Document Functions . . . . . . . . . 26
CONTENTS
3.8 Checking Input And Throwing Errors . . . . . . . . 26
3.9 Encapsulating A Complex Calculation . . . . . . . . 29
3.10 Numeric Calculations . . . . . . . . . . . . . . . . 31
3.11 Date Functions . . . . . . . . . . . . . . . . . . . . 33
3.12 Text Functions . . . . . . . . . . . . . . . . . . . . 39
3.13 Using JavaScript Built-In Object Methods . . . . . . 42
3.14 Using A Function Callback . . . . . . . . . . . . . 43
3.15 Extracting Useful Information About The Spreadsheet 45
3.16 Using Google Services . . . . . . . . . . . . . . . . 49
3.18 Summary . . . . . . . . . . . . . . . . . . . . . . . 50
Chapter 4: Spreadsheets and Sheets . . . . . . . . . . . . . 52
4.1 A Note On Nomenclature . . . . . . . . . . . . . . . 52
4.2 Native And Host Objects . . . . . . . . . . . . . . . 53
4.3 A Note On Method Overloading In Google Apps Script 53
4.5 Object Hierarchies . . . . . . . . . . . . . . . . . . . 54
4.6 SpreadsheetApp . . . . . . . . . . . . . . . . . . . . 57
4.7 The Spreadsheet Object . . . . . . . . . . . . . . . . 58
4.8 The Sheet Object . . . . . . . . . . . . . . . . . . . . 62
4.9 Practical Examples Using Spreadsheet And Sheet
Objects . . . . . . . . . . . . . . . . . . . . . . . 63
4.10 Summary . . . . . . . . . . . . . . . . . . . . . . . 69
Chapter 5: The Range Object . . . . . . . . . . . . . . . . . 71
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 71
5.2 Range Objects Are Complex . . . . . . . . . . . . . 73
5.3 Creating A Range Object . . . . . . . . . . . . . . . 74
5.4 Getting And Setting Range Properties . . . . . . . . 75
5.5 The Range offset() Method . . . . . . . . . . . . . . 78
5.6 The Sheet Data Range . . . . . . . . . . . . . . . . . 80
5.7 Transferring Values Between JavaScript Arrays And
Ranges . . . . . . . . . . . . . . . . . . . . . . . . 82
5.8 Named Ranges . . . . . . . . . . . . . . . . . . . . . 89
5.9 Practical Examples . . . . . . . . . . . . . . . . . . . 91
5.11 Concluding Remarks . . . . . . . . . . . . . . . . . 104
CONTENTS
5.12 Summary . . . . . . . . . . . . . . . . . . . . . . . 105
Chapter 6: MySQL And JDBC . . . . . . . . . . . . . . . . 106
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 106
6.2 What Is JDBC? . . . . . . . . . . . . . . . . . . . . . 107
6.3 MySQL Preliminaries . . . . . . . . . . . . . . . . . 108
6.4 Connecting to a Cloud MySQL Database from the
mysql Client . . . . . . . . . . . . . . . . . . . . . 109
6.5 An Overview of JDBC . . . . . . . . . . . . . . . . . 111
6.6 Note on Code Examples . . . . . . . . . . . . . . . . 112
6.7 Connecting to the Database . . . . . . . . . . . . . . 113
6.8 Create, Load, Query, Update and Delete a Database
Table . . . . . . . . . . . . . . . . . . . . . . . . . 116
6.9 Prepared Statements . . . . . . . . . . . . . . . . . . 126
6.10 Transactions . . . . . . . . . . . . . . . . . . . . . 129
6.11 Database Metadata . . . . . . . . . . . . . . . . . . 131
6.12 A Practical GAS Example . . . . . . . . . . . . . . 133
6.13 Summary . . . . . . . . . . . . . . . . . . . . . . . 143
Chapter 7: User Interfaces - Menus and Forms . . . . . . . 144
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 144
7.2 Adding A Menu . . . . . . . . . . . . . . . . . . . . 145
7.3 Building Forms With HtmlService . . . . . . . . . . 147
7.3.3 Defining Form Layout in CSS . . . . . . . . . . . . 158
7.4 Transferring Data from Google Sheets To an HtmlSer-
vice Web Application . . . . . . . . . . . . . . . . 163
7.5 Create Professional-looking Forms the Easy Way -
Use Bootstrap . . . . . . . . . . . . . . . . . . . . 173
7.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . 177
Chapter 8: Google Drive, Folders, Files, And Permissions 178
8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 178
8.2 List Google Drive File And Folder Names . . . . . . 180
8.3 Creating And Removing Files And Folders . . . . . . 183
8.4 Adding Files To And Removing Files From Folders . 186
CONTENTS
8.5 File And Folder Permissions . . . . . . . . . . . . . 190
8.6 Practical Examples . . . . . . . . . . . . . . . . . . . 197
8.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . 210
Chapter 9: Email and Calendars . . . . . . . . . . . . . . . 211
9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 211
9.2 Sending An Email Using MailApp . . . . . . . . . . 212
9.3 Sending An Email With An Attachment Using MailApp 214
9.4 GmailApp . . . . . . . . . . . . . . . . . . . . . . . 216
9.5 Calendars . . . . . . . . . . . . . . . . . . . . . . . 229
9.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . 236
Appendix A: Excel VBA And Google Apps Script Com-
parison . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Introduction . . . . . . . . . . . . . . . . . . . . . . . . 237
Spreadsheets and Sheets . . . . . . . . . . . . . . . . . 238
Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
Appendix B: Final Notes . . . . . . . . . . . . . . . . . . . 268
Additional Resources . . . . . . . . . . . . . . . . . . . 268
JSLint . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
Getting Source code For This Book From Github . . . . 270
Blog Updates . . . . . . . . . . . . . . . . . . . . . . . . 270
Chapter 1: Introduction
1.1 Google Sheets
Google Sheets is one of the core components of Google cloud
applications. If you have a Gmail account, you can create and
share your spreadsheets with others, even with those who do not
have a Gmail account. Google Sheets offers a comprehensive set
of standard spreadsheet features and functions similar to those
found in other spreadsheet applications such as Microsoft Excel.
In addition, it also supports some novel features such as the very
versatile QUERY function and regular expression functions such
REGEXMATCH.
What really distinguished Google Sheets from desktop spreadsheet
applications like Excel is its cloud nature. The spreadsheet appli-
cation runs in a browser and the spreadsheet files themselves are
stored remotely. The spreadsheet files can be shared with others
in read-only or read-edit modes making them ideal collaborative
tools. Spreadsheets form just one part, albeit an important one,
of the Google suite of products. Others are Google Documents,
Gmail, calendars, forms, and so on and all of these products are
inter-operable at least to some degree resulting in a very productive
environment perfectly suited to collaborative work.
When I began using Google Sheets back in 2010 it was quite limited
in terms of data volume, speed and functionality. It has undergone
significant development since then and got a major upgrade in
March 2014¹. If your experience of Google Sheets was negatively
influenced by experience with earlier versions, I encourage you
to try it again, I think you will notice a big improvement. The
¹https://support.google.com/docs/answer/3544847?hl=en
Chapter 1: Introduction 2
old 400,000 cell limit per spreadsheet is gone and is now at least
2,000,000. It will comfortably deal with tens of thousands of rows
which is, I believe, quite acceptable for any spreadsheet. Other
spreadsheet applications such as Excel can handle a million plus
rows but when data volumes grow to this size, it is advisable to
switch to a database or a dedicated statistical application to handle
such data sizes.
1.2 Google Apps Script (GAS)
The Google Sheets application also hosts a programming language
called Google Apps Script (GAS) that is executed, not in the browser
but remotely on the Google cloud. Google define Google Apps
Script as follows:
“Google Apps Script is a JavaScript cloud scripting language that
provides easy ways to automate tasks across Google products and
third party services.”
If Google Sheets is so feature-rich, you might wonder why it needs
to host a programming language. Here are few reasons why GAS is
needed:
• Write user-defined functions for Google Sheets
• Write simple “macro” type applications
• Develop spreadsheet-based applications
• Integrate other Google products and services
• Develop Graphical User Interfaces (GUIs) that can be run as
web applications
• Interact with cloud-based relational databases via Google
JDBC Services.
GAS plays a similar role in Google Sheets to that played by Visual
Basic for Applications (VBA) in Excel. Both are hosted by their
Chapter 1: Introduction 3
respective applications and both are used to extend functionality
and integrate with other applications and services.
1.3 JavaScript or Google Apps Script?
The emphasis here is on using GAS to enhance and control Google
Sheets. Other Google services are discussed in the context of how
they can be used with Google Sheets. Since GAS is JavaScript
(Google describe it as a sub-set of JavaScript 1.8), there will in-
evitably be discussion of JavaScript as a programming language.
There is, therefore, some discussion of JavaScript topics as they
relate to the code examples given.
Regarding terminology, when discussing a general JavaScript fea-
ture, the code may be referred to as “JavaScript” but when dealing
with a Google App specific example, it may be referred to as
“Google Apps Script” or “GAS”. The meaning of whichever term is
used should be clear from the context. For example, the Spreadsheet
object is central to Google Sheets programming. It is, however, pro-
vided by the hosting environment and is not part of JavaScript itself.
This duality of the programming language and the objects provided
by the hosting environment is similar to JavaScript running on the
web client and the Document Object Model (DOM) entities that it
manipulates.
1.4 Summary Of Topics Covered
This book aims to provide the reader with a solid knowledge of the
GAS language both as it applies to Google Sheets and how it is used
to allow Google Sheets to inter-operate with other Google products
and services as well as with relational databases.
Chapter 2 introduces the GAS language and sets the scene for
the chapters that follow. One of the most important applications
Chapter 1: Introduction 4
of the hosted spreadsheet language, be it VBA or GAS, is to
allow users to write user-defined functions (also known as custom
functions). These are covered in depth in chapter 3 and this chapter
merits careful reading for any readers not familiar with JavaScript.
Functions are central to JavaScript and, by extension, to GAS.
The Spreadsheet, Sheet, and Range objects are crucial for manip-
ulating Google Sheets with GAS and these objects are covered in
depth in chapters 4 and 5. All subsequent chapters assume that the
reader is comfortable with these objects, their methods and their
uses.
Having covered the basics of user-defined functions and the fun-
damental spreadsheet objects, chapter 6 explains how GAS can
be used to work with a back-end relational database (MySQL).
Spreadsheets are great tools but they have their limitations and, as
applications increase both in complexity and in data volume, there
comes a point where a more robust data storage solution is needed
that that offered by spreadsheets.
In order to build spreadsheet applications some sort of Graphical
User Interface (GUI) is usually required. Chapters 7 and 8 cover
menus, alerts, prompts and user forms created using Google Html
Service. Creating forms with Html Service offers the opportunity to
develop web skills such as HTML, CSS and client-side JavaScript.
For those not experienced in frontend development, this material
offers a gentle introduction to a very important skill.
In addition to being an excellent collaborative tool, Google Sheets
is part of a larger set of applications with which it can interact. GAS
written in Google Sheets can be used to manipulate other Google
products such as Google Drive, and Google Calendar and this aspect
of GAS programming is covered in chapters 9 and 10.
For those coming to GAS from Excel VBA, appendix A will be
of especial interest as it gives example code and explanations of
how to perform common spreadsheet programming tasks in both
languages. Appendix B gives an example of a quite complex spread-
Chapter 1: Introduction 5
sheet application written in GAS that brings together much of the
material covered earlier. It describes how to build an application
that takes spreadsheet data as input and uses it to generate SQL for
table creation and row insertion. Appendix C discusses additional
GAS and JavaScript resources that will be of interest to readers.
1.5 Software Requirements For This
Book
Not many! Modern cloud-based applications such as Google Sheets
greatly reduce the technical barriers for new entrants. In the old
days, you might have needed a specific operating system running
some proprietary and often expensive software to get started. Not
anymore! Anyone with a modern browser, an internet connection
and a Gmail account running on Windows, Mac OS X or any
version of Linux will be able to follow along with this book and
run the code examples given. The code examples should run in any
modern browser but I mainly use Chrome and Firefox and never
use Internet Explorer (IE) although I expect that all the code will
run fine in any post IE7 version.
1.6 Intended Readership
This book is written for those who wish to learn how to program-
matically manipulate Google Sheets using GAS. I began learning
GAS for two reasons. Firstly, I was using Google Sheets as a
collaborative tool in my work and, secondly, I had become aware
of the increasing importance of JavaScript generally and was keen
to learn it. Being able to use the JavaScript-based language that
is GAS in spreadsheets appealed to me because I was already
quite experienced in programming Excel using VBA so I felt that
learning GAS to manipulate Google Sheets would offer a familiar
Chapter 1: Introduction 6
environment. I reasoned that there are many experienced Excel
VBA programmers around who might feel similarly so that is why
I wrote this book. There are of course now many people who use
Google products who are familiar with JavaScript but who may not
know much about spreadsheets. This book might also be of interest
to this group of users. This book assumes programming knowledge
in some programming language though not necessarily JavaScript.
1.7 Book Code Available On GitHub
The emphasis on this book is on practical code examples. Some
of the code examples are short and only practical in the sense
that they exemplify a GAS feature. GAS is a “moving target” in
that new features are added and deprecated frequently thereby
making it difficult to keep all code up-to-date. At the time of
writing, all the examples worked as expected but please email me²
if something is broken or if you get a warning of something having
been deprecated. To allow readers to follow along, I have tried
to document the code extensively using JSDoc³ and in-line code
comments. To run the examples, you can copy and paste from the
book to the GAS Script Editor. This will work but I recommend
getting the code from GitHub. All the code examples in this book
are available on a Github repository created specifically for this
updated version of the book. The user name is Rotifer and the
repository name is GoogleSpreadsheetProgramming_2015. The
full URL is here.⁴ You can use the Git command line tool to check out
the repository to your local machine or simply copy the examples
directly from the GitHub repository.
²mick@javascript-spreadsheet-programming.com
³usejsdoc.org/
⁴https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015
Chapter 1: Introduction 7
1.8 My Blog On Google Spreadsheet
Programming
I maintain a blog⁵ that pre-dates this book. The blog began in late
2010 so some of the early examples use deprecated or unsupported
features. That said, the blog inspired this book and is actively
maintained so it can be viewed as a complementary resource to
this book. It is worth checking for new entries from time to time
because I use it to explore and discuss new spreadsheet and GAS
features and I cover some more advanced JavaScript material there.
1.8 Guideline On Using This Book
I learn best from examples so this book is heavily example-driven.
I first like to see something working and then examine it and
learn from it. In order to derive maximum benefit from this book,
it is important to execute the code from your own spreadsheets.
Read the book descriptions and code documentation carefully and
make sure that you understand both the objective of the code as
well as how it works. Chapter 3 goes in to some depth on core
JavaScript concepts such as functions, arrays and objects but if you
are relatively inexperienced in JavaScript, then some background
reading will help enormously. Remember, GAS is JavaScript so the
better you understand JavaScript, the better you will be at writing
and understanding GAS. Do not be afraid to experiment with code,
change or re-write my examples at will! If you find better ways of
doing things, please let me know!
⁵http://www.javascript-spreadsheet-programming.com
Chapter 1: Introduction 8
1.9 2015 Update Notes
The first version of this book was released in November 2013 and the
feedback I have received on it has been largely positive. However,
I realise that some of the material is now out-of-date. For example,
UiApp and DocsList have both been deprecated since that version
of the book was released. I am also aware that the book could
be improved by better explanations, better examples and generally
better writing. I hope this version delivers a better product to its
readers.
As I stated earlier, Google Sheets and GAS are “moving targets” that
are subject to constant change. I intend to release a new version of
this book yearly from now on so that the material remains current
and the overall quality of the book improves. I will continue to blog
about new features and topics that I have not covered so far and,
if these look like a good fit and attract interest from readers, I will
incorporate such subjects into later version of the book.
Something I find annoying and expensive is when I buy a technical
book only to learn a few months later that a new edition has been
released. I have one shell programming book from 1990 that I still
use but shell programming is one of the few stable technologies that
I use (SQL is another, yes, features are added but the core is quite
stable). Most technical books that I have bought in the past become
obsolete, at least in part, in a year or two. My idea with this book is
to make sure those who buy it once get all the updates for free and
I plan to keep updating it indefinitely. Leanpub make this possible,
so a big thanks to them and thanks also to all of you who bought
the first version of this book!
Time to write some GAS!
Chapter 2: Getting Started
2.1 Introduction
The best way to learn JavaScript/Google Apps Script is to write
some code. Getting started is very straightforward: All that is
needed is a Gmail account and a browser with an Internet con-
nection. To run some example code, first go to Google Drive and
create a spreadsheet. To view the script editor, select Tools->Script
editor… from the spreadsheet menu bar. The first time you do this in
a new spreadsheet file, you will be presented with a pop-up window
entitled “Google Apps Script”, just ignore and close it for now.
Give the project a name, any name you like, by hovering over and
replacing the text “untitled project” on the top left. Delete the code
stub entitled “myFunction” so that the script editor is now blank.
Paste in the example code in the following sections and save (save
icon or menu action File->Save).
2.2 Google Apps Script Examples
Here are four example functions. When pasted into the script editor,
the code formatting applied by the editor becomes evident and
makes the code easier to read. The code for this chapter can be
viewed and downloaded from GitHub here.⁶
⁶https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015/blob/master/ch02.
gs
Chapter 2: Getting Started 10
1 function sayHelloAlert() {
2 // Declare a string literal variable.
3 var greeting = 'Hello world!',
4 ui = SpreadsheetApp.getUi();
5 // Display a message dialog with the greeting
6 //(visible from the containing spreadsheet).
7 // Older versions of Sheets used Browser.msgBox()
8 ui.alert(greeting);
9 }
10
11 function helloDocument() {
12 var greeting = 'Hello world!';
13 // Create DocumentApp instance.
14 var doc =
15 DocumentApp.create('test_DocumentApp');
16 // Write the greeting to a Google document.
17 doc.setText(greeting);
18 // Close the newly created document
19 doc.saveAndClose();
20 }
21
22 function helloLogger() {
23 var greeting = 'Hello world!';
24 //Write the greeting to a logging window.
25 // This is visible from the script editor
26 // window menu "View->Logs...".
27 Logger.log(greeting);
28 }
29
30
31 function helloSpreadsheet() {
32 var greeting = 'Hello world!',
33 sheet = SpreadsheetApp.getActiveSheet();
34 // Post the greeting variable value to cell A1
35 // of the active sheet in the containing
Chapter 2: Getting Started 11
36 // spreadsheet.
37 sheet.getRange('A1').setValue(greeting);
38 // Using the LanguageApp write the
39 // greeting to cell:
40 // A2 in Spanish,
41 // cell A3 in German,
42 // and cell A4 in French.
43 sheet.getRange('A2')
44 .setValue(LanguageApp.translate(
45 greeting, 'en', 'es'));
46 sheet.getRange('A3')
47 .setValue(LanguageApp.translate(
48 greeting, 'en', 'de'));
49 sheet.getRange('A4')
50 .setValue(LanguageApp.translate(
51 greeting, 'en', 'fr'));
52 }
2.2 Executing Code – One Function At A
Time
In order to execute code, there must be at least one valid function
in the script editor. After pasting the code above, there are four
functions that will each be executed in turn.
Chapter 2: Getting Started 12
Figure 2-1: Google Apps Script Editor displaying the code and the “Select
function” drop-down list.
Select function sayHelloAlert() from the “Select function” drop-
down list on the script editor toolbar and then press the execute
icon (to the left of the function list drop-down). You will need to
authorize the script when you first try to execute it. Subsequent
executions do not require authorisation. Once authorised, switch to
the spreadsheet and you will see a small window with the greeting
“Hello world”. These browser popup displays are modal meaning
that they block all subsequent code execution until they are closed.
For this reason, their use should be limited. The Logger is generally
a better tool for writing and displaying output.
New Sheets Feature
Browser.msgBox instead of alert() is used in older
versions and still works.
Chapter 2: Getting Started 13
Now select the second function named helloDocument() and exe-
cute it. This is a much more interesting example than the previous
one because it shows how GAS written in one application can be
used to manipulate other applications. The first time you try to
execute it, you will get a message saying, “Authorization required”.
Once you authorise it and then execute, it will create a new
Google Document and write the message to it. This example, though
trivial and useless, does demonstrate how GAS code written in
one application can manipulate other applications. This is a very
powerful feature and will be a recurring theme of this book.
The helloLogger() function, when executed, writes the message to
a logging area that is viewable from the script editor menu “View-
>Logs…”. It is equivalent to the “console.log” in Firebug and Node.js.
It will be used frequently in later code examples for output and for
error reporting.
The final function helloSpreadsheet() demonstrates two important
aspects of Google Apps Script:
Firstly, spreadsheets can be manipulated via the Spreadsheet object
(the Google documentation refers to Spreadsheet as a “class”). It
provides a method that returns an object representing the active
sheet (getActiveSheet()) and that this returned object has a method
that returns a range (getRange()), in this instance a single cell with
the address “A2”. The returned range object method, setValue(), is
then called with a string argument that is written to cell A1 of the
active sheet. These types of chained method calls look daunting at
first. The method call chain described above could be re-written as:
Chapter 2: Getting Started 14
1 var greeting = 'Hello world!',
2 activeSpreadsheet =
3 SpreadsheetApp.getActiveSpreadsheet(),
4 activeSheet =
5 activeSpreadsheet.getActiveSheet(),
6 rng = activeSheet.getRange('A1'),
7 greeting = 'Hello world!';
8 rng.setValue(greeting);
The code above uses a number of intermediate variables and may
be easier to understand initially but after experience with GAS,
the chained method call will start to feel easier and more natural.
The objects referenced in this example will be discussed in detail in
chapters 4 and 5.
Secondly, the example code shows how easy it is to call another
service from a Google Apps Script function. Here the LanguageApp
was used to translate a simple text message into Spanish, German,
and French. This ability to seamlessly access other Google services
is extremely powerful.
2.3 Summary
This chapter has shown how to access the GAS Script Editor and
execute functions from it. The examples demonstrated how GAS
can display simple alerts, write messages to the Logger, manipulate
ranges in spreadsheets and use other Google applications such
as Document and Google services such as LanguageApp. These
examples barely scrape the surface of what can be achieved using
GAS. The next chapter uses GAS to write user-defined functions
that can be called in the same manner as built-in spreadsheet
functions.
Chapter 3: User-Defined
Functions
3.1 Introduction
User-defined functions allow spreadsheet users and developers to
extend spreadsheet functionality. No spreadsheet application can
cater for all requirements for all users so a mechanism is provided
that allows users to write their own customised functions in the
hosted language, be that VBA in Excel or GAS in Google Sheets.
Definition
A user-defined function is one that can be called
using the equals (=) sign in a spreadsheet cell and
writes its return value or values to the spreadsheet.
User-defined functions are also known as custom functions and this
is the term used by the Google.
Google Custom Function Doc-
umentation
Worth Reading!⁷.
The source code for this chapter can be found here on GitHub.⁸ I
have adopted the convention of writing user-defined functions in
⁷https://developers.google.com/apps-script/guides/sheets/functions
⁸https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015/blob/master/ch03.
gs
Chapter 3: User-Defined Functions 16
all upper case, other fiunctions that are not intended to be called
as user-defined functions are written in camel case. This chapter is
quite long and covers a lot of material. It is also the chapter where
I put most effort into explaining basic JavaScript concepts such as
functions, arrays, objects and so on. Therefore, if you are unfamiliar
with GAS/JavaScript, then pay close attention to the code examples
and explanatory text. If my explanations are inadequate, then you
can take advantage of the extensive on-line JavaScript resources
available for all levels of user in addition to the many excellent
JavaScript textbooks (see Appendix B for information on resources
that I have found useful).
3.2 Built-in Versus User-Defined
Functions
Modern spreadsheet applications, including Google Sheets, supply
a large number of built-in functions and they owe much of their
utility and widespread usage in diverse domains of finance, science,
engineering and so on to these functions. There is also a high
degree of standardisation between spreadsheet applications regard-
ing function names, arguments, and usage so that they generally
work uniformly in Google Sheets, Microsoft Excel, OpenOffice
Calc and Gnumeric. Built-in Google Sheets functions are spread
over multiple categories, see Google Spreadsheet function list ⁹.
Most of the standard spreadsheet text, date, statistical, logic and
lookup functions are present and their usage is, in all cases that
I have encountered, identical to equivalents in other spreadsheet
applications.
Google Sheets also implements a number of novel functions. Some
of these are very convenient and it is worth being familiar with
them before you embark on writing your own functions so that you
do not end up implementing something that is already present. One
⁹https://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cs
Chapter 3: User-Defined Functions 17
of my favourites is the QUERY function and a good description of
its syntax and use can be found here¹⁰. This function comes from
the Google Visualization API and it uses an SQL-like syntax to
extract sub-sets of values from input spreadsheet data cells. If you
are already familiar with SQL, then you will feel right at home
with this function. Another group of functions worth exploring
are those that use regular expressions. The functions concerned
are REGEXMATCH, REGEXEXTRACT and REGEXREPLACE and I
have described them in a blog entry¹¹. Regular expressions are very
useful and GAS implements the full standard JavaScript regular
expression specification.
New Functionality
Google Sheets continues to add new functions
3.3 Why Write User-Defined Functions
The two main reasons for writing user-defined functions are for
clarity and to extend functionality. User-defined functions can add
to clarity by wrapping complex computations in a named and doc-
umented function. Spreadsheet power-users can often ingeniously
combine the built–in functions to effectively create new ones. The
disadvantage of this approach is that the resulting formulas can be
very difficult to read, understand and debug. When such function-
ality is captured in a function, it can be given a name, documented
and, tested. Secondly, user-defined functions allow developers to
customise spreadsheet applications by adding functionality for their
particular domain.
¹⁰https://anandexcels.wordpress.com/2013/11/01/query-function-in-google-sheets/
¹¹http://www.javascript-spreadsheet-programming.com/2013/09/regular-
expressions.html
Chapter 3: User-Defined Functions 18
3.4 What User-Defined Functions
Cannot Do
An important point about user-defined functions is that they cannot
be used to alter any properties, such as formats, of the spreadsheet
or any of its cells. They cannot be used to send e-mails and cannot
be used to insert new worksheets. Functions can be used to do
these things but they cannot be called as user-defined functions.
This is a common area of misunderstanding where users attempt to
call functions from the spreadsheet using the equals operator (=).
This results in an error because the function is trying to set some
spreadsheet property.
User-defined functions should be designed to work just like built-in
functions in that you pass in zero or more values as arguments and
they return a value or values in the form of an array. Their purpose
is their return values, not their side effects. Excel VBA makes a
distinction between subroutines and functions. Subroutines do not
return a result and cannot be called as user-defined functions. In
GAS we only have functions that either return values or do not
(void functions).
To illustrate how a user-defined function cannot alter spreadsheet
properties, consider the following function that takes a range ad-
dress argument (a string, not a Range object) and sets the font for
the range to bold:
Code Example 3.1
Chapter 3: User-Defined Functions 19
1 /**
2 * Simple function that cannot be called from
3 * the spreadsheet as a user-defined function
4 * because it sets a spreadsheet property.
5 *
6 * @param {String} rangeAddress
7 * @return {undefined}
8 */
9 function setRangeFontBold (rangeAddress) {
10 var sheet =
11 SpreadsheetApp.getActiveSheet();
12 sheet.getRange(rangeAddress)
13 .setFontWeight('bold');
14 }
The code uses objects that have not yet been discussed but the idea
is simple; Take a range address as input and set the font to bold for
that range. However, when the function is called from a spreadsheet,
it does not work.
Figure 3-1: Error displayed when calling a function with side effects from a
spreadsheet.
The error shown above refers to permissions but the problem is that
the called function is attempting to modify sheet properties.
To prove that the function setRangeFontBold() is valid, here is a
function that prompts for a range address using an prompt dialog.
It calls the setRangeFontBold() function passing the given range
address as an argument.
Chapter 3: User-Defined Functions 20
To See The Prompt
Call the function in the Script Editor Then switch to
the spreadsheet
Code Example 3.2
1 /**
2 * A function that demonstrates that function
3 * "setRangeFontBold() is valid although it
4 * cannot be called as a user-defined function.
5 *
6 * @return {undefined}
7 */
8 function call_setCellFontBold () {
9 var ui = SpreadsheetApp.getUi(),
10 response = ui.prompt(
11 'Set Range Font Bold',
12 'Provide a range address',
13 ui.ButtonSet.OK_CANCEL),
14 rangeAddress = response.getResponseText();
15 setRangeFontBold(rangeAddress);
16 }
When this function is called, the following prompt is displayed in
the spreadsheet view:
Chapter 3: User-Defined Functions 21
Figure 3-2: *Prompt dialog display for a range address.
The prompt mechanism for requesting user input will be discussed
in a later chapter. The important point here is that a function may
be valid but, if it has side effects such as altering range properties,
then it cannot be called as a user-defined function.
New Sheets Feature
Browser.inputBox instead of prompt() is used in older
versions and still works.
3.5 Introducing JavaScript Functions
User-defined functions can be called exactly like built-in ones using
the equals (=) operator in a spreadsheet cell. They can take zero
or more arguments of different types and these arguments can be
either cell references or literal values, just as with built-in functions.
The user-defined functions themselves are written in GAS and,
as I have repeated multiple times already, GAS is JavaScript. To
understand and write user-defined functions in Google Sheets
requires an understanding of JavaScript functions. The better you
understand JavaScript functions, the better you will be at crafting
your own user-defined GAS functions for Google Sheets!
Chapter 3: User-Defined Functions 22
JavaScript functions are immensely powerful and flexible. They
play a central role in many JavaScript idioms and patterns and mas-
tery of them is a prerequisite to becoming an advanced JavaScript
programmer. Only the basics of JavaScript functions are required
for the purposes of this chapter. There are different ways of defining
JavaScript functions but in this chapter most of the functions are
defined as function declarations in form:
1 function functionName(comma-separated
2 parameters) {
3 statements
4 }
Other types of function definition will be described as they are
introduced later in the book.
JavaScript Functions
Read this Mozilla resource¹²
The Mozilla resource above discusses various means of defining
JavaScript functions. For user-defined functions the decision on
the syntax to use to define our functions is made for us because
only function declarations work in this setting, named function
expressions and object methods will not work.
For the purposes of this chapter, here are the principal additional
points of note regarding JavaScript functions:
• When the function is called, the arguments passed in are
assigned to the parameters in the function definition.
• These arguments can then be used within the function body.
¹²https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Chapter 3: User-Defined Functions 23
• Parameters are always passed by value in JavaScript but
when reference types, such as arrays, are used, the behaviour
can appear pass-by-reference.
• If the number of arguments passed in is less than the number
of parameters in the function definition, the unassigned
parameters are given the value undefined.
• Variables declared within the function using the var state-
ment are local. That means that they are scoped to that
function and are not visible outside the function.
• Functions in JavaScript are objects and they define a number
of pre-defined properties.
• Two function properties are important for this chapter. These
are the arguments object and the length property.
• The arguments object is an array-like list that stores all the
arguments passed to the function when it is called.
• The arguments object is not an array but, like the Array
type, it does have a length property that stores the number
of arguments that were actually given when the function
was called and its elements can be accessed using array-like
indexing
• The length property of the function stores the number of
arguments the function expects based on the number of
parameters in the function definition.
• Since JavaScript functions can accept any number of ar-
guments of any type regardless of the parameter list, the
arguments.length value can be compared to the function
length property to check if the argument count is as expected.
• Functions can have an explicit return statement. If no return
statement is specified, the function will return the value
undefined.
• User-defined functions without a return statement are point-
less.
• A return statement on its own can be used to exit the function
Chapter 3: User-Defined Functions 24
and will return undefined, again, not much use in user-
defined functions.
• User-defined functions should always return some value
other than undefined.
• The returned value can be a primitive such as a string,
Boolean, or a number. It can also be a reference type such
as a JavaScript object or an array.
To see some of these points in action, paste the following code
example 3.3 into the Script Script editor and choose and run the
second function named call_testFunc. The point of this example is
to show how the number of function arguments and the argument
data types can be determined in JavaScript.
Code Example 3.3
1 /**
2 * Function to demonstrate how to check
3 * the number and types of passed arguments.
4 *
5 *
6 * @return {undefined}
7 */
8 function testFunc(arg1, arg2) {
9 var i;
10 Logger.log('Number of arguments given: ' +
11 arguments.length);
12 Logger.log('Number of arguments expected: ' +
13 testFunc.length);
14 for (i = 0; i< arguments.length; i += 1) {
15 Logger.log('The type of argument number ' +
16 (i + 1) + ' is ' +
17 typeof arguments[i]);
18 }
19 }
Chapter 3: User-Defined Functions 25
The function output demonstrates how JavaScript functions can
check the number of arguments passed in and the type of each
argument by:
1. Checking the argument count given when the function is
called (arguments.length) against the argument count ex-
pected based on the parameter list in the function definition
(the function length property).
2. Using the typeof operator to determine the type of each given
argument. The typeof operator can also be used to identify
missing argument values where the missing value will be of
type undefined. This check can be used to assign defaults
using the statement if (typeof arg === ‘undefined’ ) { arg =
default; }.
3.6 User-Defined Functions Versus
JavaScript Functions
When user-defined functions are called from within spreadsheet
cells, their string arguments must be provided in double quotes.
In JavaScript, either single or double quotes can be used to enclose a
string literal but only double quotes are acceptable for string literals
in user-defined functions. Single quote usage can lead to puzzling
errors so beware!
JavaScript function names and variable names are case-sensitive,
function afunc () { … } and function aFunc () { … } are two different
functions (unlike VBA). However, when called from a spreadsheet,
the function names are case-insensitive. The implication of this
is to be very careful when naming functions to be called from a
spreadsheet. Camel casing is the JavaScript standard and is used
throughout here except when defining testing functions that may
be given the prefix “testing”/”run” or when writing user-defined
functions where the function names are all in uppercase.
Chapter 3: User-Defined Functions 26
3.7 Using JSDoc To Document Functions
JSDoc is a markup language, inspired by its Java equivalent called
Javadoc, for adding comments and structured annotation to JavaScript
code. A sub-set of JSDoc can be used to document user-defined
functions. The JSDoc markup can then be extracted using various
tools to auto-generate documentation. It is defined by a special
type of multi-line commenting where the opening comment tag is
defined with a special opening tag of a forward slash followed by a
double asterisk:
1 /**
2 * Line describing the function
3 * @param {data type} parameter name
4 * @return {data type}
5 * @customfunction
6 */
The documentation example above contains a description line and
three types of annotation tags denoted by a leading “@”. Each
function paramater should be assigned an @param tag denoting
the expected data type and the parameter name. Unsurprisingly,
the return data type is given the @return tag. The final tag is called
@customfunction and it is used to signify that the function is is
intended to be called as a user-defined function. When JSDoc is used
with this tag, the user-defined functions appear in the autocomplete
on entering the function name preceded by an equals sign in a
spreadsheet cell.
3.8 Checking Input And Throwing Errors
JavaScript functions are flexible and can be called with any number
of arguments of any type. Stricter languages offer some protection
Chapter 3: User-Defined Functions 27
against bad argument values. Most languages throw errors if the
passed argument count does not match the parameter count while
static languages such as Java check the given data types of function
and method arguments. JavaScript takes a very relaxed approach
but inappropriate argument types can cause errors or, more seriosly,
bugs where the return value may not be what you expect. For
example:
Code Example 3.4
1 // Function that is expected
2 // to add numbers but will also
3 // "add" strings.
4 function adder(a, b) {
5 return a + b;
6 }
7 // Test "adder()" with numeric arguments
8 // and with one numeric and one string
9 // argument.
10 function run_adder() {
11 Logger.log(adder(1, 2));
12 Logger.log(adder('cat', 1));
13 }
The problem here is twofold. Firstly, the adder() function takes
arguments of any type. Secondly, the + operator can do string con-
catenation as well as numeric addition. When one of the operands
is a string, JavaScript silently coerces the other argument to type
string. Although this example is contrived, it does illustrate a
potential source of bugs. One way to guard against this is to
explicitly check each argument type and then throw an error if any
of the arguments is of the wrong type. The typeof operator can be
used to do this. Here is a version of the adder() function that does
exactly this:
Code Example 3.5
Chapter 3: User-Defined Functions 28
1 // Function that is expected
2 // to add numbers but will also
3 // "add" strings.
4 function adder(a, b) {
5 return a + b;
6 }
7
8 // Function that checks that
9 // both arguments are of type number.
10 // Throws an error if this is not true.
11 function adder(a, b) {
12 if (!(typeof a === 'number' &&
13 typeof b === 'number')) {
14 throw TypeError(
15 'TypeError: ' +
16 'Both arguments must be numeric!');
17 }
18 return a + b;
19 }
20
21 // Test "adder()" with numeric arguments
22 // Thrown error is caught, see logger.
23 function run_adder() {
24 Logger.log(adder(1, 2));
25 try {
26 Logger.log(adder('cat', 1));
27 } catch (error) {
28 Logger.log(error.message);
29 }
30 }
Now the function adder() throws an error if either of the arguments
is non-numeric. The test function run_adder() uses a try .. catch
construct to deal with the error. Detecting and dealing with incor-
rect arguments in functions may or may not be a priority depending
Chapter 3: User-Defined Functions 29
on circumstances. The typeof operator is adequate for primitive
data types such as numbers and strings but limited for objects. For
example, it reports arrays as type object, true but not very useful.
When passing objects to functions, the instanceof operator is better
suited for type checking.
3.9 Encapsulating A Complex Calculation
The relative standard deviation¹³ (RSD) is frequently used in
statistics to express and compare variability of data sets. It is not
provided as a built-in spreadsheet function. The formula to calculate
it is simply the sample standard deviation divided by the sample
mean multiplied by 100. Given the following values in cells A1 to
A10: 19.81 18.29 21.47 22.54 20.17 20.1 17.61 20.91 21.62 19.17 The
RSD rounded to two decimal places can be calculated using this
spreadsheet formula:
1 =ROUND(100*(STDEV(A1:A10)/AVERAGE(A1:A10)),2)
The functionality expressed in this spreadsheet formula can be
encapsulated in a user-defined function as follows:
Code Example 3.6
¹³http://en.wikipedia.org/wiki/Relative_standard_deviation
Chapter 3: User-Defined Functions 30
1 /**
2 * Given the man and standard deviation
3 * return the relative standard deviation.
4 *
5 * @param {number} stdev
6 * @param {number} mean
7 * @return {number}
8 * @customfunction
9 */
10 function RSD (stdev, mean) {
11 return 100 * (stdev/mean);
12 }
This function can be called as follows:
1 =RSD(STDEV(A1:A10),AVERAGE(A1:A10))
Figure 3-3: *Calling the RSD function in Google Sheets with provided auto-
complete.
The above function can be pasted into the Script Editor and called
as described in the documentation. So what was gained by writing
a user-defined function when a combination of spreadsheet built-
in functions can be used and the user-defined version still uses the
spreadsheet STDEV and AVERAGE built-ins? Firstly, the calcula-
tion now has a meaningful name. Secondly, argument checking can
be added as described in the previous section. Lastly, the logic is
captured in one place and is documented. These are all good reasons
Chapter 3: User-Defined Functions 31
to consider replacing complex spreadsheet formulas with user-
defined functions. In addition, our JSDoc description now appears
in the autocomplete.
3.10 Numeric Calculations
The following example takes a single numeric argument as degrees
Centigrade and uses that argument to return the temperature in
Fahrenheit. To use, paste the function into the Google Apps Script
editor and then call it by name in a cell in the containing spread-
sheet. For example, if cell A1 contains the value 0, then the formula
=CELSIUSTOFAHRENHEIT(A1) in cell B1 will return the result 32
as expected.
Code Example 3.7
1 /**
2 * Given a temperature in Celsius, return Fahrenheit va
3 lue.
4 *
5 * @param {number} celsius
6 * @return {number}
7 * @customfunction
8 */
9 function CELSIUSTOFAHRENHEIT(celsius) {
10 if (typeof celsius !== 'number') {
11 throw TypeError('Celsius value must be a number');
12 }
13 return ((celsius * 9) / 5) + 32;
14 }
Function CELSIUSTOFAHRENHEIT takes a numeric value repre-
senting degrees Celsius and returns the Fahrenheit equivalent. Be-
fore performing the calculation, it first checks that the given value is
Chapter 3: User-Defined Functions 32
numeric, if not, it throws a type error. Here is a screenshot showing
some input values and the outputs after calling this function:
Figure 3-4: Input and output for user-defined function CELSIUSTOFAHREN-
HEIT and .
See how the thrown error is reported as a comment in cells A5 to
A8. Without the typeof check, the date value in cell A7 would be
interpreted as a number of seconds and would return an unfeasibly
large value. The outcome of evaluating the cell A6 is even more
insidious because the blank is interpreted as zero and the function
evaluates to 32. Indeed, 0 Celsius is equal to 32 Fahrenheit but this
is highly misleading. Remove or comment out the typeof check
and see the effect! The text value in cell A5 will throw an error
regardless of the typeof check, which is to be expected. However,
the default interpretation of dates as numbers and blank cells as
zero is a serious trap for the unwary. The same problem occurs in
Excel VBA and is more difficult to guard against. This example of
a user-defined function is very simple but it highlights the need for
rigorous checking of inputs.
Verifying that arguments are within a valid range may also be
required to avoid invalid return values. As an example, the formula
to calculate the area of a circle is simple: Π * radius2. The following
function does this but it also checks that the given argument is both
Chapter 3: User-Defined Functions 33
numeric and not less than zero.
Code Example 3.8
1 /**
2 * Given the radius, return the area of the circle.
3 * @param {number} radius
4 * @return {number}
5 * @customfunction
6 */
7 function AREAOFCIRCLE (radius) {
8 if (typeof radius !== 'number' || radius < 0){
9 throw Error('Radius must be a positive number');
10 }
11 return Math.PI * (radius * radius);
12 }
In example 3.8, the function expects a single numeric argument for
the circle radius. However, since a negative radius makes no sense
in this context, there is an additional check to ensure that the radius
given is not negative. If either of these conditions fails, an error is
thrown (|| is the or operator). In this example, both checks were
performed togeter using the or operator. If greater granularity is
required, the checks could be performed in two separate checks
that would yield two different errors. This approach helps when
functions are part of larger applications.
3.11 Date Functions
Google Sheets provides a comprehensive set of date functions, see
here¹⁴ for the full list. However, if the provided functions do not
cover your requirements, you can write your own in GAS and
¹⁴https://support.google.com/docs/table/25273?hl=en&rd=2
Chapter 3: User-Defined Functions 34
call them from your spreadsheet as user-defined functions. Some
cautionary words: Dates and times can be quite complicated in any
application or programming language where you have to allow for
time zones, daylight saving time changes and leap years so rigorous
testing of inputs and outputs is highly advidable.
The examples given here also cover some important basic JavaScript
concepts such as date manipulation, objects and methods and
JavaScript arrays.
The first example (3.9) takes a date as its sole argument and returns
the day name (in English) for that date.
Code Example 3.9
1 /**
2 * Given a date, return the name of the
3 * day for that date.
4 *
5 * @param {Date} date
6 * @return {String}
7 * @customfunction
8 */
9 function DAYNAME(date) {
10 var dayNumberNameMap = {
11 0: 'Sunday',
12 1: 'Monday',
13 2: 'Tuesday',
14 3: 'Wednesday',
15 4: 'Thursday',
16 5: 'Friday',
17 6: 'Saturday'},
18 dayName,
19 dayNumber;
20 if(! date.getDay ) {
21 throw TypeError(
Chapter 3: User-Defined Functions 35
22 'TypeError: Argument is not of type "Date"!');
23 }
24 dayNumber = date.getDay();
25 dayName = dayNumberNameMap[dayNumber];
26 return dayName;
27 }
The most interesting points in the code example 3.9 are the use of
the object named dayNumberNameMap, how the argument type
is checked and how the Date object method getDay() is used. The
variable dayNumberNameMap is a JavaScript object. Since objects
are cornerstones of JavaScript programming, here is a short detour
that describes them. At their simplest, JavaScript objects provide
a mapping of keys to values. The values are called “properties”
and they can be other objects, scalar values, arrays or functions.
When object properties are functions, they are known as meth-
ods. JavaScript objects are analogous to hashes or dictionaries in
other languages. The very popular data interchange format called
JavaScript Object Notation (JSON) is based on them. Excel VBA
offers a Dictionary Object from the Microsoft Scripting Library¹⁵
that provides similar functionality but is much less flexible. The
object in the example above maps index numbers to the names of
the days of the week. Returning to the code example above, the
date argument is expected to be of type Date and the mechanism
used to test for it, that is the line if(! date.getDay ) {, merits some
explanation. If the argument is a Date object, then it will implement
a getDate() method. The test here is to see if the property exists,
notice how the getDate() method is not called because there are no
parentheses. If the argument does not have a getDate property, then
an error is raised. This type of checking for methods on objects is
common in client-side (browser) JavaScript where implementations
from different vendors may or may not provide certain methods. If
the argument passes the type check, then we are satisified that it is a
¹⁵https://support.microsoft.com/en-us/kb/187234/
Chapter 3: User-Defined Functions 36
Date object so we can call the getDay() method on it. The getDay()
method returns the week day as an integer starting with 0 (zero) for
Sunday. Having the day number, we can use it as key for our object
dayNumberNameMap to return the day name. To use the function
DAYNAME as a user-defined function, copy the code into the Script
Editor and call it from the spreadsheet like this where the return
value of the built-in TODAY() function is given as an argument:
1 =DAYNAME(TODAY())
All the user-defined functions given so far return a scalar value but
they can also return arrays where each array element is entered into
its own cell. An example will help to illustrate this. In this example,
we write a function that returns all dates that fall on a given day
between two dates.
Code Example 3.10
1 /**
2 * Add a given number of days to the given date
3 * and return the new date.
4 *
5 * @param {Date} date
6 * @param {number} days
7 * @return {Date}
8 */
9 function addDays(date, days) {
10 // Taken from Stackoverflow:
11 // questions/563406/add-days-to-datetime
12 var result = new Date(date);
13 result.setDate(result.getDate() + days);
14 return result;
15 }
16
17 /**
Chapter 3: User-Defined Functions 37
18 * Given a start date, an end date and a day name,
19 * return an array of all dates that fall (inclusive)
20 * between those two dates for the given day name.
21 *
22 * @param {Date} startDate
23 * @param {Date} endDate
24 * @param {String} dayName
25 * @return {Date[]}
26 * @customfunction
27 */
28 function DATESOFDAY(startDate, endDate, dayName) {
29 var dayNameDates = [],
30 testDate = startDate,
31 testDayName;
32 while(testDate <= endDate) {
33 testDayName = DAYNAME(testDate);
34 if(testDayName.toLowerCase() ===
35 dayName.toLowerCase()) {
36 dayNameDates.push(testDate);
37 }
38 testDate = addDays(testDate, 1);
39 }
40 return dayNameDates;
41 }
The code in example 3.10 defines a user-defined function called
DATESOFDAY() that calls two other GAS functions, addDays()
and DAYNAME() to perform some of the computation. Function
DAYNAME() was described in code example 3.9 above will be
needed when you paste this code into the Script Editor. The function
addDays() was copied from this location on Stackoverflow.¹⁶. I
stated earlier that date manipulation can be complex and the
discussion thread on this Stackoverflow entry certainly proves that.
¹⁶http://stackoverflow.com/questions/563406/add-days-to-datetime
Chapter 3: User-Defined Functions 38
Before discussing the actual code in example 3.10 in detail, first
note how a user-defined function can call other GAS functions to
perform some of its tasks as can be seen in this example where
two other functions are called and their return values are used by
DATESOFDAY(). By off-loading much of its work, DATESOFDAY()
remains small on manageable.
Make Functions Small
De-composing a programming task into multiple
small functions makes each function easier to test,
de-bug and re-use
DATESOFDAY() takes two dates and a day name as argument. I
have not added any checking of types or numbers of argument,
these could be easily added using the techniques discussed ear-
lier. The function declares two local variables, dayNameDates and
testDate. It initialises testDate to startDate and then enters the
while loop. Each round of the while loop gets the name of the
day for the testDate using the DAYNAME function described in
code example 3.9. The returned day name is then compared to
the given argument day name (dayName) using a case-insensitive
comparison by calling the string method toLowerCase() on both
string operands. If they are equal, the date is added to the array
using the Array push() method. This technique of building arrays
in loops will be seen throughout the book. JavaScript arrays are
extremely flexible and implement a range of very useful methods.
Many of these methods will be encountered later in this book. After
testing the day of the date, the test date is incremented by one day
using the addDays() function. The condition testDate <= endDate
is tested in the next round of the while loop and the loop finishes
when the condition evaluates to false and the dayNameDates array
is returned.
When the function DATESOFDAY() is called as a user-defined
Chapter 3: User-Defined Functions 39
function, it writes the entire array to a single column, see the
screenshot below:
Figure 3-5: Calling user-defined function that returns an array of values.
3.12 Text Functions
Google Spreadsheets text manipulation functions can also be com-
plemented and enhanced by writing user-defined functions. JavaScript,
like most programming languages, refers to the text type as “string”.
Strings in JavaScript are primitive types but they can be wrapped to
behave like objects. The wrapping of a primitive so that it becomes
an object is known as auto-boxing. Auto-boxing can also be applied
to Boolean and Number primitive types and though I have never
seen any use for it, with Boolean. The Number type has some
useful methods like toFixed(). Since auto-boxing is transparent to
the user/programmer, all that really matters is that strings can be
treated as though they have methods that can be used to extract
information from them and to generate new strings.
To see all the String properties supported by GAS/JavaScript, paste
the following code into the script editor and execute it. An alpha-
betical list of string properties is sent to the logger.
Code Example 3.11
Chapter 3: User-Defined Functions 40
1 /**
2 * Print all string properties to the
3 * Script Editor Logger
4 * @return {undefined}
5 */
6 function printStringMethods() {
7 var strMethods =
8 Object.getOwnPropertyNames(
9 String.prototype);
10 Logger.log('String has ' +
11 strMethods.length +
12 ' properties.');
13 Logger.log(strMethods.sort().join('n'));
14 }
The code above uses JavaScript’s very powerful introspection ca-
pabilities to extract an array of all the property names defined for
object String on what is known as its prototype. The prototype is
a property that refers to an object where the String methods are
defined in the prototype. Prototypes are quite an advanced topic
but they are very important and provide the basis for inheritance
in JavaScript. All JavaScript objects (that includes arrays and func-
tions) have a prototype property. The logger output shows that
there are 38 String properties. Most are methods but the important
length property, for example, is not. Code example 3.11 also uses
two important Array methods: sort() and join(). The sort() method
does an alphabetical sort in this example and join() then makes a
string of the array using the given argument (new line ‘n’ in this
example) to separate the concatenated array elements. Notice how
the method calls are “chained” one after the other. This is a common
approach in JavaScript. As an exercise, you could try writing an
equivalent function to print out all the array properties.
Since the String object has so many methods, we can use these
methods in user-defined functions. Here is a function that returns
Chapter 3: User-Defined Functions 41
the argument string in reverse character order.
Code Example 3.12
1 /**
2 * Given a string, return a new string
3 * with the characters in reverse order.
4 *
5 * @param {String} str
6 * @return {String}
7 * @customfunction
8 */
9 function REVERSESTRING(str) {
10 var strReversed = '',
11 lastCharIndex = str.length - 1,
12 i;
13 for (i = lastCharIndex; i >= 0; i -= 1) {
14 strReversed += str[i];
15 }
16 return strReversed;
17 }
Reversing strings might not strike you as the most useful func-
tionality unless of course you work with DNA or are interested
in palindromes. To see a palindrome example, call the function
with the word detartrated, yes, that word really exists. The example
function uses a JavaScript for loop to extract the string characters in
reverse order and appends them to a new string that is built within
the loop. The newly built string is returned upon completion of the
loop. If you declare the variable strReversed but do not assign it,
something unexpected happens. As the variable is unassigned, it is
undefined. If you concatenate a string to undefined you get another
of those troublesome implicit JavaScript conversions that I warned
about earlier where undefined becomes the string “undefined!
Beware!
Chapter 3: User-Defined Functions 42
Spreadsheets generally offer a large set of built-in text functions and
Google Sheets augments these with regular expression functions.
I have covered regular expressions in two blog entries (see part
1here¹⁷ and part 2 here¹⁸.) I will include a chapter on regular
expression later in this book and will give some regular expression-
based user-defined function examples there.
3.13 Using JavaScript Built-In Object
Methods
JavaScript provides a small number of built-in objects that provide
additional functionality that can be used in user-defined functions.
For example, the JavaScript Math object is available in GAS and
provides some useful methods. Simulation of a die throw can be
easily implemented using its methods:
Code Example 3.13
1 /**
2 * Simulate a throw of a die
3 * by returning a number between
4 * and 6.
5 *
6 * @return {number}
7 * @customfunction
8 */
9 function THROWDIE() {
10 return 1 + Math.floor(Math.random() * 6);
11 }
¹⁷http://www.javascript-spreadsheet-programming.com/2013/09/regular-
expressions.html
¹⁸http://www.javascript-spreadsheet-programming.com/2014/09/regular-expressions-
part-2.html
Chapter 3: User-Defined Functions 43
Try out the function by calling =THROWDIE() from any spreadsheet
cell.
This function uses two methods defined in the JavaScript built-in
Math object to simulate dice throwing. The Math round() method
could also be used here but, as is very well described here¹⁹, it leads
to biased results. This becomes apparent when the function is called
hundreds of times. The important point to note is the need for
testing and reading of documentation to avoid inadvertent errors
and biases.
3.14 Using A Function Callback
The object nature of JavaScript functions allows them to be both
passed as arguments to other functions and to be returned by other
functions. The following example provides an example of the power
and flexibility of JavaScript. It also shows how easy it is to use
a range of cells as an argument. The function concatenates an
input range of cells using a delimiter argument. There is an in-
built Google Spreadsheet function called JOIN that performs this
task but the user-defined version below has one additional feature:
It provides an option to enclose each individual element in single
quotes. Here is the code:
Code Example 3.14
¹⁹http://www.the-art-of-web.com/javascript/random/#.UPU8tKHC-nY
Random documents with unrelated
content Scribd suggests to you:
was recognized as the most convenient medium for official uses, and
the language most generally known in these sections of society
which had to administer justice.[19] In the second half of the
thirteenth century Robert of Gloucester complained that there was
no land "that holdeth not to its kindly speech save Englonde only,"
admitting at the same time, however, that ignorance of French was a
serious disadvantage. An idea of the extent to which the language
was current in England may be gathered from the fact that in 1301
Edward I. caused letters from the Pope to be translated into French
so that they might be understood by the whole army,[20] and in the
previous year the author of the Miroir des Justices wrote in French
as being the language "le plus entendable de la comun people."
French, indeed, appears to have been used among all classes, save
the very poorest;[21] some of the French literature of the time was
addressed more particularly to the middle classes.[22]
Nevertheless, as the thirteenth century advanced, French began to
hold its own with some difficulty. While it was in the unusual position
of a vernacular gradually losing its power as such, there appeared
the earliest extant treatise on the language. This, and those that
followed it, were to some extent lessons in the vernacular; yet not
entirely, as may be judged from the fact that they are set forth and
explained in Latin, the language of all scholarship. The first work on
the French language, dating from not later than the middle of the
thirteenth century, is in the form of a short Latin treatise on French
conjugations,[23] in which a comparison of the French with the Latin
tenses is instituted.[24] As it appeared at a time when French was
becoming the literary language of the law, and was being used freely
in correspondence, it may have been intended mainly for the use of
clerks. A treatise of considerably more importance composed
towards the end of the century, appears to have had the same
purpose. That he did not intend it exclusively for clerks, however, the
author showed by adding rules for pronunciation, syntax and even
morphology as well as for orthography. Like most of the early
grammatical writings on the French language, this Orthographia
Gallica is in Latin. The obscurity of many of its rules, however, called
forth commentaries in French which appeared during the fourteenth
century, and exceed the size of the original work. The Orthographia
was a very popular work, as the number of manuscripts extant and
the French commentary prove. The different copies vary
considerably, and there is a striking increase in the number of rules
given; from being about thirty in the earliest manuscript, they
number about a hundred in the latest.[25]
It opens with a rule that when the first or middle syllable of a
French word contains a short e, i must be placed before the e, as in
bien, rien, etc.—a curious, fumbling attempt to explain the
development of Latin free short e before nasals and oral consonants
into ie. On the other hand, continues the author, e acute need not
be preceded by i, as tenez. It is not surprising that these early
writers, in spite of much patient observation, should almost always
have failed to grasp fundamental laws, and group a series of
corresponding facts into the form of a general rule. We continually
find rules drawn up for a few isolated examples, with no general
application. The most striking feature in the treatment of French
orthography in this work is the continual reference to Latin roots,
and the clear statement of the principle that, wherever possible, the
spelling of French words should be based on that of Latin.
The Orthographia does not by any means limit its observations to
spelling; there are also rules for pronunciation, a subject which in
later times naturally held a very important place in French grammars
written for the use of Englishmen, while orthography became one of
the chief concerns of French grammarians. That orthography
received so much attention at this early period in this country, is
explained by the fact that these manuals were partly intended for
"clerks," who would frequently have to write in French. As to the
pronunciation, we find, amongst others, the familiar rule that when a
French word ending in a consonant comes before another word
beginning with a consonant, the first consonant is not pronounced.
An s occurring after a vowel and before an m, writes the author, in
another rule, is not pronounced, as in mandasmes, and l coming
after a, e, or o, and followed by a consonant is pronounced like u, as
in m'almi, loialment, and the like. A list of synonyms[26] is also
given, which throws some light on the English pronunciation of
French at this period, and there are also a few hints for the
translation of both Latin and English into French.
Nor are syntax and morphology neglected; rules concerning these
are scattered among those on orthography and pronunciation, with
the lack of orderly arrangement characteristic of the whole work.
Thus we are told to use me in the accusative case, and moy in all
other cases; that we should form the plural of verbs ending in t in
the singular by adding z, as il amet, il list become vous amez, vous
lisez; that when we ask any one for something, we may say vous pri
without je, but that, when we do this, we should write pri with a y,
as pry, and so on.
The claim of the Orthographia Gallica to be the first extant work
on French orthography, has been disputed by another treatise, also
written in Latin, and known as the Tractatus Orthographiae. More
methodically arranged than the Orthographia, this work deals more
particularly with pronunciation and orthography.[27] It opens with a
short introduction announcing that here are the means for the youth
of the time to make their way in the world speedily and learn French
pronunciation and orthography. Each letter of the alphabet is first
treated in turn,[28] and then come a few more general observations.
Like the author of the Orthographia, the writer of the Tractatus
would have the spelling of French words based on that of Latin
whenever possible. He claims that his own French is "secundum
dulce Gallicum" and "secundum usum et modum modernorum tam
partibus transmarinis quam cismarinis." Though he apparently places
the French of England and the French of France on the same
footing, it is noteworthy that he carefully distinguishes between the
two.
The Tractatus Orthographiae bears a striking resemblance to
another work of like nature, which is better known—the Tractatus
Orthographiae of Canon M. T. Coyfurelly, doctor in Law of
Orleans[29]—and for some time it was thought to be merely a
rehandling of Coyfurelly's treatise which did not appear till
somewhere about the end of the fourteenth century, if not later. But
Coyfurelly admits that his work was based on the labours of one 'T.
H. Parisii Studentis,' and there appears, on examination,[30] to be no
doubt as to the priority of the anonymous Tractatus described above,
which, on the contrary, is evidently the treatise rehandled by
Coyfurelly, and the work of 'T. H. Student of Paris.' Besides being the
original which Coyfurelly recast in his Tractatus, it also appears that
T. H. may reasonably dispute with the author of the Orthographia
Gallica, the honour of being the first in the field. His work shows no
advance on the rules given for pronunciation in the Orthographia,
while the orthography is of a decidedly older stamp.
At about the same time as these two treatises on orthography,
probably a few years earlier, there was composed a work of similar
purpose but very different character. It is of particular interest, and
shows that, towards the end of the thirteenth century, French was
beginning to be treated as a foreign language; the French is
accompanied by a partial English gloss, and the author states that
"touz dis troverez-vous primes le Frauncois et pus le Engleys
suaunt." The author, Gautier or Walter de Bibbesworth,[31] was an
Englishman, and appears to have mixed with the best society of the
day. He was a friend of the celebrated statesman of the reign of
Edward I., Henry de Lacy, Earl of Lincoln. The only work by which his
name is known to-day, in addition to the treatise in question, is a
short piece of Anglo-Norman verse,[32] written on the occasion of
the expedition of Edward I. to the Holy Land in 1270, shortly before
he came to the throne. We gather from letters of protection granted
him in that year that Bibbesworth himself took part in this venture.
In this poem he is pictured discussing the Crusade with Lacy, and
trying to persuade his friend to take part in it. The name of
Bibbesworth also occurs several times[33] in official documents of no
special interest, and as late as 1302 a writ of Privy Seal was
addressed to the Chancellor suing for a pardon under the Great Seal
to W. de Bibbesworth, in consideration of his good services rendered
in Scotland, for a breach of the park of Robert de Seales at
Ravenhall, and of the king's prison at Colchester.[34]
Bibbesworth, however, interests us less as a crusader or a
disturber of public order, than as the author of a treatise for teaching
the French language, entitled Le Treytyz qe mounsire Gauter de
Bibelesworthe fist a ma dame Dyonisie de Mounchensy[35] pur
aprise de langwage. The large number of manuscripts still in
existence[36] suggest that it was a popular text-book among the
children of the higher classes of society. The treatise reproduces, as
might be expected, the chief characteristics of the vocabularies for
teaching Latin. In addition to giving a collection of words and
phrases arranged in the form of a narrative, it also incidentally aims
at imparting some slight grammatical information. Its contents are of
a very practical character, and deal exclusively with the occurrences
and occupations of daily life. Beginning with the new-born child, it
tells in French verses how it is to be nursed and fed. Rime was no
doubt introduced to aid the memory, as the pupil would, in all
probability, have to learn the whole by heart. The French is
accompanied by a partial interlinear English gloss, giving the
equivalent of the more difficult French words. This may, perhaps, be
taken as an indication of the extent to which French was regarded as
a foreign language.[37]
After describing the life of the child during its earliest infancy,
Bibbesworth goes on to tell how it is to be taught French as soon as
it can speak, "that it may be better learned in speach and held up to
scorn by none":
Quaunt le enfes ad tel age
Ke il set entendre langage,
Primes en Fraunceys ly devez dire
Coment soun cors deyt descrivere,
Pur le ordre aver de moun et ma,
Toun et ta, soun et sa,
better lered
Ke en parlole seyt meut apris
scorned
E de nul autre escharnys.
In accordance with this programme the parts of the human body,
which almost invariably forms the central theme in this type of
manual, are enumerated. Special care is taken to distinguish the
genders and cases, to teach the children "Kaunt deivunt dire moun
et ma, soun et sa, le et la, moy et jo . . .," and to explain how the
meaning of words of similar sound often depends on their gender:
lippe and an hare
Vous avet la levere et le levere,
a pound a book
Et la livere et le livere.
La levere si enclost les dens;
Le levere en boys se tent dedens;
La livere sert en marchaundye;
Le livere nous aprent clergye.
Throughout Bibbesworth seizes every opportunity to point out
distinctions of gender of this kind, regardless, it appears, of the
difference between the definite and indefinite articles. When the
pupil can describe his body, the teacher proceeds to give him an
account of "all that concerns it both inside and out" ("kaunt ke il
apent dedens et deores"), that is of its clothing and food:
Vestet vos draps mes chers enfauns,
Chaucez vos brays, soulers, e gauns;
Mettet le chaperoun, covrez le chef, etc.
—a passage which illustrates the practical nature of the treatise,
Bibbesworth's aim being to teach children to know the properties of
the things they see ("les propretez des choses ke veyunt").
When the child is clothed, Bibbesworth next feeds him, giving a
full account of the meals and the food which is provided, and, by
way of variety, at the end of the dinner, he teaches his pupil the
names given to groups of different animals, and of the verbs used to
describe their various cries. ("Homme parle, cheval hennist," etc.).
By this time the child is ready to observe Nature, and to learn the
terms of husbandry,[38] and the processes by which his food is
produced. From the fields he passes to the woods and the river,
where he learns to hunt and to fish, subjects which naturally lead to
the introduction of the French names of the seasons, and of the
beasts and birds that are supposed to present themselves to his
view.
During the whole of this long category the verse form is
maintained, and the intention of avoiding a vocabulary pure and
simple is manifest. How superior this method was to the more
modern lists of words separated from the context is also evident.
Besides giving a description of all the objects with which the child
comes in contact, and of all the actions he has to perform, as well as
examples for the distinctions of genders and of moy and jo—
difficulties for which he makes no attempts to draw up rules—
Bibbesworth claims for his work that it provides gentlemen with
adequate instruction for conversational purposes ("tot le ordre en
parler e respoundre ke checun gentyshomme covent saver"). And as
he did not wish to neglect any of the items of daily life, he finally
gives a description of the building of a house and various domestic
arrangements, ending with a description of an old English feast with
its familiar dish, the boar's head:
Au primer fust apporté
a boris heued
La teste de un sengler tot armé,
the snout wit baneres of flurs
E au groyn le colere en banere;
E pus veneysoun, ou la fourmenté;
Assez par my la mesoun
tahen of gres tyme
De treste du fermeyson.
Pus avyent diversetez en rost,
Eit checun autre de cost,
Cranes, pokokes, swannes
Grues, pounes, e cygnes,
Wilde ges, gryses (porceaus), hennes,
Owes, rosées, porceus, gelyns;
Au tercez cours avient conyns en gravé,
Et viaunde de Cypre enfundré,
De maces, e quibibes, e clous de orré,
Vyn blanc e vermayl a graunt plenté.
wodekok
Pus avoyunt fesauns, assez, et perdriz,
Feldefares larkes
Grives, alowes, e pluviers ben rostez;
E braoun, e crispes, e fritune;
Ke soucre roset poudra la temprune.
Apres manger avyunt a graunt plenté
Blaunche poudre, ou la grosse dragé,
Et d'autre nobleie a fusoun,
Ensi vous fynys ceo sermoun;
Kar de fraunceis i ad assez,
De meynte manere dyversetez,
Dount le vous fynys, seynurs, ataunt
A filz Dieu vous comaund.
Ici finest la doctrine monsire Gauter De Byblesworde.
As time went on a conscious effort was made to retain the use of
the French language in England. Higden, writing at about the middle
of the fourteenth century,[39] informs us that English was then
neglected for two reasons: "One is bycause that children than gon to
schole lerne to speke first Englysshe and then ben compelled
constrewe ther lessons in Frenssh"; "Also gentilmens children ben
lerned and taught from theyr yougthe to speke frenssh.[40] And
uplandish men will counterfete and likene them self to gentilmen
and arn besy to speke frensshe for to be more sette by. Wherefor it
is sayd by a common proverbe Jack wold be a gentilmen if he coude
speke frensshe."
At the University of Oxford, likewise, the Grammar masters were
enjoined to teach the boys to construe in English and in French, "so
that the latter language be not forgotten."[41] The same university
gave some slight encouragement to the study of French. There were
special teachers who, although not enjoying the privileges of those
lecturing in the usual academic subjects, were none the less
recognised by the University. They had to observe the Statutes, and
to promise not to give their lessons at times which would interfere
with the ordinary lectures in arts. The French teachers were under
the superintendence of the masters of grammar, and had to pay
thirteen shillings a year to the Masters in Arts to compensate them
for any disadvantage they might suffer from any loss of pupils; if
there was only one teacher of French he had to pay the whole
amount himself. As for those learning "to write, to compose, and
speak French," they had to attend lectures in rhetoric and grammar
—the courses most akin to their studies[42]—and to contribute to the
maintenance of the lecturers in these subjects, there being no
ordinary lectures in French.
In the meantime, more treatises for teaching French appeared;
Bibbesworth's book soon found imitators, and early in the new
century an anonymous author, clearly an Englishman, made free use
of Bibbesworth in a treatise called The Nominale sive Verbale in
Gallicis cum expositione ejusdem in Anglicis.[43] This anonymous
writer[44] however, thought it necessary to make the interlinear
English gloss much fuller than Bibbesworth had done, which shows
that French had become more of a foreign language in the interval
between the two works. He also placed the English rendering after
the French, instead of above it. The later work differs further from
the earlier in the order of the subject headings, as well as by the
introduction of a few new topics. Enumerating the parts of the body,
[45] as Bibbesworth had done, the author proceeds to make his most
considerable addition to the subjects introduced by Bibbesworth in
describing "la noyse et des faitz que homme naturalment fait":
Homme parle et espire:
Man spekyth & vndyth.
Femme teinge et suspire:
Woman pantyth & syketh.
Homme bale et babeie:
Man dravelith & wlaffyth.
Femme bale et bleseie:
Woman galpyth & wlispyth.
He then describes all the daily actions and occupations of men:
Homme va a la herce:
Man goth at the harewe.
Femme bercelet berce:
Woman childe in cradel rokkith....
Enfant sa lessone reherce:
His lessone recordeth,
and so on for about 350 lines. Other additions are of little
importance, and, for the rest, the author treats subjects first
introduced by Bibbesworth, though the wording often differs to a
certain extent.[46]
When, towards the end of the thirteenth century, French began to
be used in correspondence, need for instruction in French epistolary
art arose; and early in the fourteenth century guides to letter-writing
in French, in the form of epistolaries or collections of model letters,
were produced.[47] The letters themselves are given in French, but
the accompanying rules and instructions for composing them are in
Latin. French and Latin have changed rôles; in earlier times Latin
had been explained to school children by means of French. Forms
for addressing members of the different grades of society are
supplied, from epistles to the king and high state and ecclesiastical
dignitaries down to commercial letters for merchants, and familiar
ones for private individuals. Women, too, were not forgotten; we
find similar examples covering the same range—from the queen and
the ladies of the nobility to her more humble subjects. Each letter is
almost invariably followed by its answer, likewise in French. Some
contain interesting references to the great men or events of the day,
but those of a more private nature possess a greater attraction, and
throw light on the family life of the age. A letter from a mother to
her son at school may be quoted:[48]
Salut avesque ma beniçon, tres chier filz. Sachiez que je desire
grandement de savoir bons nouelles de vous et de vostre estat: car
vostre pere et moy estions a la faisance de ces lettres en bon poynt le
Dieu merci. Et sachiez que je vous envoie par le portour de ces lettres
demy marc pur diverses necessaires que vous en avez a faire sans
escient de vostre pere. Et vous pri cherement, beau tres doulz filz,
que vous laissez tous mals et folyes et ne hantez mye mauvaise
compagnie, car si vous le faitez il vous fera grant damage, avant que
vous l'aperceiverez. Et je vous aiderai selon mon pooir oultre ce que
vostre pere vous donnra. Dieus vous doint sa beniçon, car je vous
donne la mienne. . . .
From about the middle of the fourteenth century a feeling of
discontent with the prerogative of the French language in England
becomes prominent. The loss of the greater part of the French
possessions, and the continued state of hostilities with France during
the reign of Edward III. brought home forcibly to the English mind
the fact that the French were a distinct nation, and French a foreign
tongue. This tardy recovery is sufficient proof of the strong
resistance which had to be overcome. Chaucer is the greatest
representative of the new movement. "Let Frenchmen endite their
quaint terms in French," he exclaims, "for it is kindly to their mouths,
but let us show our fantaisies in suche words as we learned from our
dames' tongues." His contemporary, Gower, was less quick to discern
the signs of the times. Of the four volumes of his works, two are in
Latin, one in French, and one in English; but the order in which he
uses these languages is instructive—first French, then Latin, and
lastly English. Some writers made a compromise by employing a
mixture of French and English.[49] French, however, continued to
hold an important place in prose writings until the middle of the
fifteenth century; but such works are of little literary value. The
reign of French as the literary language of England, as Chaucer had
been quick to discern, was approaching its end.
The same period is marked by a growing disrespect for Anglo-
French as compared with the French of France. The French of
England, cut off from the living source, had developed apart, and
often with more rapidity than the other French dialects on the
Continent. What is more, the language brought by the invaders was
not a pure form of the Norman dialect; men from various parts of
France had joined in William's expedition. The invaders, always
called 'French' by their contemporaries, brought in a strong Picard
element; and in the twelfth century there was a similar Angevin
influence. Moreover, during Norman and Angevin times, craftsmen
and others immigrated to England, each bringing with him the
dialectal peculiarities of his own province.[50] Thus no regular
development of Anglo-French was possible, and it can hardly be
regarded as an ordinary dialect, notwithstanding its literary
importance.[51] This disparity in the quality of Anglo-French is
illustrated in a remarkable way by the literature of the period. Those
who had received special educational advantages, or had travelled
on the Continent, spoke and wrote French correctly; others used
forms which contrasted pitiably with continental French. Moreover,
the fourteenth century saw the triumph of the Île de France dialect
in France; the other dialects ceased, as a rule, to be used in
literature,[52] and this change was not without effect on Anglo-
French, which shared their degradation. Chaucer lets us know the
poor opinion he had of the French of England; his Prioress speaks
French "full fayre and fetisly," but
After the scole of Stratford atte Bowe,
For French of Paris was to her unknowe.
William Langland admits that he knew "no frenche in feith, but of
the ferthest ende of Norfolke."[53] As early as the thirteenth century
English writers had felt bound to apologize as Englishmen for their
French. Nor were their excuses superfluous in many cases; William
of Wadington, the author of the Manuel des Pechiez, for example,
wrote:[54]
De le françois ne del rimer
Ne me doit nuls hom blamer,
Car en Engleterre fu né
Et nurri lenz et ordiné.
Such apologies became all the more necessary as time went on.
Even Gower, whose French was comparatively pure,[55] owing no
doubt to travel in France in early life, deemed it advisable to explain
that he wrote in French for "tout le monde en general," and to ask
pardon if he has not "de François la faconde":
Jeo suis Englois si quier par tiele voie
Estre excusé.
At about the same time the anonymous author of the Testament of
Love finds fault with the English for their persistence in writing in
bad French, "of which speech the Frenchmen have as good a fantasy
as we have in hearing of Frenchmen's English."[56]
The notoriety of the French of Englishmen reached France. Indeed
this was a time when the English were more generally known in
France than they were to be for several hundreds of years
afterwards—until the eighteenth century. Englishmen filled positions
in their possessions in France, and during the long wars between the
two countries in the reign of Edward III., many of the English
nobility resided in that country with their families. Montaigne refers
to traces of the English in Guyenne, which still remained in the
sixteenth century: "Il est une nation," he writes in one of his Essays,
"a laquelle ceux de mon quartier ont eu autrefois si privée
accointance qu'il reste encore en ma maison aucune trace de leur
ancien cousinage."[57] The opinions formed by the French of the
English were naturally anything but flattering. We find them
expressed in songs of the time.[58] But the recriminations were
mutual, and the English had already hit upon the epithet which for
centuries they applied to Frenchmen, and most other foreigners
indiscriminately:
Franche dogue dit un Anglois.
Vous ne faites que boire vin,
Si faisons bien dist le François,
Mais vous buvez le lunnequin. (bière.)[59]
Even in the Roman de Renart we come across traces of familiarity
with English ways, and also of the English language.[60]
It is not surprising, then, that Anglo-French was a subject of
remark in France, especially when we remember that already in the
thirteenth century the provincial accents of the different parts of
France herself had been the object of some considerable amount of
raillery.[61] The English, says Froissart, a good judge, for he spent
many years in England, "disoient bien que le françois que ils avoient
apris chies eulx d'enfance n'estoit pas de telle nature et condition
que celluy de France estoit."[62] And this 'condition' was soon
recognized as a plentiful store for facetious remarks and parodies of
all kinds. In the Roman de Jehan et Blonde, the young Frenchman's
rival, the Duke of Gloucester, is made to appear ridiculous by
speaking bad French; and one of the tricks played by Renart on
Ysengrin, in the Roman de Renart, is to pretend he is an
Englishman:[63]
Ez vos Renart qui le salue:
"Godehelpe," fait il, "bel Sire!
Non saver point ton reson dire."
And Ysengrin answers:
Et dex saut vos, bau dous amis!
Dont estes vos? de quel pais?
Vous n'estes mie nés de France,
Ne de la nostre connoissance.
A fabliau of the fourteenth century[64] pictures the dilemma of two
Englishmen trying to make their French understood in France; one of
them is ill and would have some lamb:
Si tu avez un anel cras
Mi porra bien mengier ce croi.
His friend sets out to try to get the 'anel' or 'lamb'; but no one
understands him, and he becomes the laughing-stock of the
villagers. At last some one gives him a 'small donkey' instead of the
desired 'agnel,' and out of this he makes a dish for the invalid who
finds the bones rather large. In the face of a reputation such as this
it is no wonder that the English found additional encouragement to
abandon the foreign language and cultivate their own tongue.
English was also beginning to make its way into official
documents.[65] In 1362 the King's Speech at the opening of
Parliament was pronounced in English, and in the following year it
was directed that all pleas in the courts of justice should be pleaded
and judged in English, because French was "trope desconue en ledit
realme." Despite that, the act was very tardily obeyed, and English
progressed but slowly, French continuing to be written long after it
ceased to be spoken in the Law Courts. There were a few public
documents issued in English at the end of the century, but the Acts
and Records of Parliament continued to be written in French for
many years subsequently. English first made its way into the
operative parts of the Statutes, and till 1503 the formal parts were
still written in French and Latin. Protests were made to Henry VIII.
against the continued use of French, "as thereby ys testyfied our
subjectyon to the Normannys"; yet it was not before the eighteenth
century that English was exclusively used in the Law Courts, and for
many years French, in its corrupt form, remained the literary
language of the English law. Till the seventeenth century works on
jurisprudence and reports on cases were mainly written in French.
Les Cases de Gray's Inn shows French in accounts of discussions on
difficult legal cases as late as 1680.[66] Sir John Fortescue (1394?
-1476), Lord Chief Justice of the King's Bench, in his De Laudibus
Legum Angliae, suggests that this Law French is more correct at
bottom than ordinary spoken French, which, he contends, is much
"altered by common use, whereas Law French is more often writ
than spoken." In later times no such illusions prevailed. Swift thus
estimates the value of the three languages of the English Law:[67]
Then from the bar harangues the bench,
In English vile, and viler French,
And Latin vilest of the three.
At about the same time as Swift wrote, the 'frenchified' Lady, then in
fashion, who prided herself on her knowledge of the "language à la
mode" is described as being able to "keep the field against a whole
army of Lawyers, and that in their own language, French gibberish."
[68] And long after French ceased to be used in the Law many law
terms and legal and official phrases remained, and are still in use to-
day.[69] Anglo-French also lingered in some of the religious houses
after it had fallen into discredit elsewhere, and continued to do so in
some cases till the time of their dissolution. The rules and accounts
of the nunneries were more often in French than not.[70] And John
ap Rhys, visitor of monasteries in the reign of Henry VIII., wrote to
Cromwell regarding the monastery of Laycock in Wiltshire, that he
had observed one thing "worthy th'advertisement; the ladies have
their Rule, th'institutes of their Religion and the ceremonies of the
same written in the Frenche tongue, which they understand well and
are very perfyt in the same, albeit that it varieth from vulgar Frenche
that is now used, and is moche like the Frenche that the common
Lawe is written in."[71]
During this same period English began to be used occasionally in
correspondence; but here again its progress was slow. Some idea of
the extent to which French was utilized for that purpose may be
gathered from the fact that three extant letters of William de
Wykeham, addressed to Englishmen, are all in that tongue. Not till
the second and third decades of the fifteenth century were English
and French employed in correspondence to an almost equal extent,
and during the following years, especially in the reign of Henry VI.,
English gradually became predominant.[72] French remained in use
longer in correspondence of a public and official nature, but became
more and more restricted to foreign diplomacy.
Towards the middle of the fourteenth century, at the beginning of
the long wars with France, French lost ground in England in yet
another direction. Edward III. is said to have found it necessary to
proclaim that all lords, barons, knights, burgesses, should see that
their children learn French for political and military reasons;[73] and
when Trevisa translated Higden's Polychronicon, he wrote in
correction of the earlier chronicler's description of the teaching of
French in the grammar schools of England:[74] "This maner was
moche used before the grete deth (1349). But syth it is somdele
chaunged. Now (i.e. 1387) they leave all Frensch in scholes, and use
all construction in Englisch. Wherin they have advantage on way that
they lerne the soner ther gramer. And in another disadvantage. For
nowe they lerne no Frenssh ne can none, whiche is hurte for them
that shall passe the see," and thus children of the grammar schools
know "no more French than knows their lefte heele."
Thus the custom of translating Latin into French passed out of use
early in the second half of the fourteenth century. No doubt there
had been signs of the approaching change in the preceding period,
and it is of interest here to notice that while Neckham's Latin
vocabulary, which dates from the second half of the twelfth century,
is glossed in French alone, that of Garlande, which belongs
approximately to the third decade of the following century, is
accompanied by translations in both French and English. In the
universities, however, where French had been slower in gaining a
foothold, it remained longer; in the fifteenth century teachers of
French were still allowed to lecture there as they had done
previously, but it is to be noticed that in all the colleges founded
after the Black Death (1349), from which the change in the grammar
schools is dated, the regulations encouraging the speaking of French
in Hall are absent. The change appears also to have affected the
higher classes, who did not usually frequent the grammar schools
and universities, but depended on more private methods of
instruction. Trevisa here again adds a correction to the earlier
chronicle, and informs us that "gentylmen haveth now myche lefte
for to teach their children Frensch."
We thus witness the gradual disappearance of the effects of the
Norman Conquest in the history of the use of the French language in
England. The Conquest had made Norman-French the language of
the Court, and to some extent, of the Church; it had brought with it
a French literature which nearly smothered the national literature
and replaced it temporarily; it had led to the system of translating
Latin into French as well as into English in the schools. In the later
fourteenth century French was no longer the chief language of the
Court, and the king spoke English and was addressed in the same
tongue. In the Church the employment of French had been
restricted and transitory, though, as has been mentioned, it lingered
in some of the monasteries until the sixteenth century; yet Latin
never found in it a serious rival in this sphere, and the ecclesiastical
department of the law never followed the civil in the adoption of the
use of French. How French lost ground in the other spheres has
already been traced: in all these cases its employment may be
regarded as a direct result of the Conquest.
This great event had also indirect results. French became the
official language of England, and the favourite medium of
correspondence in the thirteenth century, when the fusion between
the two races was complete. But it is highly improbable that French
would have spread in these directions if the Conquest had not in the
first place made French the vernacular of a considerable portion of
Englishmen, and that the most influential. With its use in official
documents and in correspondence, may be classed the slight
encouragement French received at Oxford. In all these spheres it
remained longer than it had done where its status had been a more
direct result of the Conquest.
Meanwhile the desire to cultivate and imitate the French of France
had been growing stronger and stronger; and when, towards the
end of the fourteenth century, the older influences were getting
feebler, and in some cases had passed away, the influence of the
continental French, especially the French of Paris, now supreme over
the other dialects, became more and more marked. And it is this
language which henceforth Englishmen strove to learn, gradually
relinquishing the corrupt idiom with which for so long their name
had been associated.
FOOTNOTES:
[1] This was the opinion of Ames: "This seems to be the first grammar
of the French language in our own country, if not in Europe." Dibdin,
Herbert Ames's Typographical Antiquities, 1819, iii. p. 365.
[2] The grammar of Jacques Sylvius or Dubois appeared in 1531, a year
after Palsgrave's. No attempt at a theoretical treatment of the French
language appeared in France in the Middle Ages. There are, however, two
Provençal ones extant. (F. Brunot, "Le Français à l'étranger," in L. Petit de
Julleville's Histoire de la langue et de la littérature française, ii. p. 528.)
[3] One of the chief effects of the Conquest in the schools is said to
have been the substitution of Norman for English schoolmasters (Leach,
Schools of Mediaeval England, 1915, p. 103).
[4] The majority of early Latin vocabularies extant, however, are
accompanied by English translations (cp. T. Wright, Volume of
Vocabularies, 2 vols., 1857), as was also the comparatively well-known
Promptorium Parvulorum (c. 1440), Camden Soc., 1865.
[5] The text is given in L. E. Menger's Anglo-Norman Dialect, Columbia
University Press, 1904, p. 14. The psalms, together with Cato, Ovid, or
possibly Virgil, formed the usual reading material in the Grammar Schools.
Cp. Rashdall, Universities of Europe in the Middle Ages, Oxford, 1895, ii.
p. 603.
[6] Adam du Petit Pont (d. 1150) wrote an epistle in Latin, many words
of which were glossed in French. But there is no evidence that it was used
in England. It was published by E. Scheler in his Trois traités de
lexicographie latine du 12e et 13e siècles, Leipzig, 1867.
[7] Ed. T. Wright, Volume of Vocabularies, i. 96, and Scheler, op. cit.
Both editions are deemed unsatisfactory by Paul Meyer (Romania, xxxvi.
482).
[8] It has been published five times: (1) At Caen by Vincent Correr in
1508 (Romania, ut supra); (2) H. Géraud, in Documents inédits sur
l'histoire de France: "Paris sous Philippe le Bel d'après les documents
originaux," 1837; (3) Kervyn de Lettenhove, 1851; (4) T. Wright, Volume
of Vocabularies, i. pp. 120 sqq.; (5) Scheler, Trois traités de lexicographie
latine.
[9] Wright, op. cit. pp. 139-141.
[10] Statutes of the Colleges of Oxford, 3 vols., Oxford and London,
1853; A. Clark, Colleges of Oxford, 1891, p. 140; H. C. Maxwell Lyte,
History of the University of Oxford, 1880, pp. 140-151.
[11] Documents relating to the Universities and Colleges of Cambridge,
1852, ii. p. 33; J. Bass Mullinger, The University of Cambridge, 1873; G.
Peacock, Observations on the Statutes of the University of Cambridge,
1841, p. 4.
[12] J. Heywood, Early Cambridge University and College Statutes,
1885, ii. p. 182.
[13] C. H. Cooper, Annals of Cambridge, Cambridge, 1852, i. p. 40.
[14] Rashdall, op. cit. ii. p. 519 n.
[15] Rashdall, op. cit. i. pp. 319 et seq. Later the English nation was
known as the German; it included all students from the north and east of
Europe. On the English in the University of Paris see Ch. Thurot, De
l'organisation de l'enseignement dans l'Université de Paris, Paris, 1850;
and J. E. Sandys, "English Scholars of Paris, and Franciscans of Oxford," in
The Cambridge History of English Literature, i., 1908, chap. x. pp. 183 et
seq.
[16] Quoted, E. J. B. Rathery, Les Relations sociales et intellectuelles
entre la France et l'Angleterre, Paris, 1856, p. 11.
[17] A writer of about 1180 says it was impossible to tell who were
Normans and who English ("Dialogus de Scaccario": Stubbs, Select
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.
More than just a book-buying platform, we strive to be a bridge
connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.
Join us on a journey of knowledge exploration, passion nurturing, and
personal growth every day!
ebookbell.com

More Related Content

PDF
Agile Web Development With Rails Third Edition Third Ruby Sam
xhessnanaj
 
PDF
Sustainable Web Development With Ruby On Rails Practical Tips For Building We...
ntxygopq606
 
PDF
Report-V1.5_with_comments
Mohamed Abdelsalam
 
PDF
java web_programming
bachector
 
PDF
Mysql To Db2 Conversion Guide Ibm Redbooks
iliqzrccg
 
PDF
Thesis_Report
Subramaniam Ramasubramanian
 
PDF
Open edX Building and Running a Course
Amish Gandhi
 
PDF
Java web programming
Mumbai Academisc
 
Agile Web Development With Rails Third Edition Third Ruby Sam
xhessnanaj
 
Sustainable Web Development With Ruby On Rails Practical Tips For Building We...
ntxygopq606
 
Report-V1.5_with_comments
Mohamed Abdelsalam
 
java web_programming
bachector
 
Mysql To Db2 Conversion Guide Ibm Redbooks
iliqzrccg
 
Open edX Building and Running a Course
Amish Gandhi
 
Java web programming
Mumbai Academisc
 

Similar to Google Sheets Programming With Google Apps Script Michael Maguire (20)

PDF
An Introduction to Computer Science - python
LuisFernandoLozano5
 
PDF
SAP MM Tutorial ds_42_tutorial_en.pdf
sjha120721
 
PDF
Pragmatic Version Control Using Subversion 1st Edition Mike Mason
kekgzcvr508
 
PDF
Yii2 guide
Steve Gaita
 
PDF
Javascript The Definitive Guideactivate Your Web Pages 6th Ed Flanagan
reknesluima
 
PDF
Openobject developer
Ali Mashduqi
 
PDF
Cognos v10.1
Exo-marker
 
PDF
Flask docs
Kunal Sangwan
 
PDF
eclipse.pdf
PerPerso
 
PDF
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
mustafa sarac
 
PDF
Perltut
Ashoka Vanjare
 
PDF
C++ For Quantitative Finance
ASAD ALI
 
PDF
python learn basic tutorial learn easy..
MURTHYVENKAT2
 
PDF
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
Satya Harish
 
PDF
Best Python tutorial (release 3.7.0)
youssef bouferdou
 
PDF
0802 python-tutorial
Zahid Hasan
 
PDF
Python everthing
AbdullahAbdullahabdu1
 
PDF
0802 python-tutorial
urvishathummar1
 
PDF
Tutorial edit
Boris Popov
 
An Introduction to Computer Science - python
LuisFernandoLozano5
 
SAP MM Tutorial ds_42_tutorial_en.pdf
sjha120721
 
Pragmatic Version Control Using Subversion 1st Edition Mike Mason
kekgzcvr508
 
Yii2 guide
Steve Gaita
 
Javascript The Definitive Guideactivate Your Web Pages 6th Ed Flanagan
reknesluima
 
Openobject developer
Ali Mashduqi
 
Cognos v10.1
Exo-marker
 
Flask docs
Kunal Sangwan
 
eclipse.pdf
PerPerso
 
Explorations in Parallel Distributed Processing: A Handbook of Models, Progra...
mustafa sarac
 
C++ For Quantitative Finance
ASAD ALI
 
python learn basic tutorial learn easy..
MURTHYVENKAT2
 
BOOK - IBM tivoli netcool service quality manager data mediation gateway deve...
Satya Harish
 
Best Python tutorial (release 3.7.0)
youssef bouferdou
 
0802 python-tutorial
Zahid Hasan
 
Python everthing
AbdullahAbdullahabdu1
 
0802 python-tutorial
urvishathummar1
 
Tutorial edit
Boris Popov
 
Ad

Recently uploaded (20)

PDF
PG-BPSDMP 2 TAHUN 2025PG-BPSDMP 2 TAHUN 2025.pdf
AshifaRamadhani
 
PDF
Review of Related Literature & Studies.pdf
Thelma Villaflores
 
PDF
The Picture of Dorian Gray summary and depiction
opaliyahemel
 
PPTX
Care of patients with elImination deviation.pptx
AneetaSharma15
 
PPTX
PREVENTIVE PEDIATRIC. pptx
AneetaSharma15
 
PDF
5.EXPLORING-FORCES-Detailed-Notes.pdf/8TH CLASS SCIENCE CURIOSITY
Sandeep Swamy
 
PDF
Phylum Arthropoda: Characteristics and Classification, Entomology Lecture
Miraj Khan
 
PPTX
Understanding operators in c language.pptx
auteharshil95
 
PDF
Landforms and landscapes data surprise preview
jpinnuck
 
PDF
Arihant Class 10 All in One Maths full pdf
sajal kumar
 
PPTX
An introduction to Prepositions for beginners.pptx
drsiddhantnagine
 
PDF
Virat Kohli- the Pride of Indian cricket
kushpar147
 
PPTX
vedic maths in python:unleasing ancient wisdom with modern code
mistrymuskan14
 
DOCX
SAROCES Action-Plan FOR ARAL PROGRAM IN DEPED
Levenmartlacuna1
 
PDF
Wings of Fire Book by Dr. A.P.J Abdul Kalam Full PDF
hetalvaishnav93
 
PPTX
CARE OF UNCONSCIOUS PATIENTS .pptx
AneetaSharma15
 
PPTX
Software Engineering BSC DS UNIT 1 .pptx
Dr. Pallawi Bulakh
 
PPTX
Measures_of_location_-_Averages_and__percentiles_by_DR SURYA K.pptx
Surya Ganesh
 
PPTX
IMMUNIZATION PROGRAMME pptx
AneetaSharma15
 
PPTX
Information Texts_Infographic on Forgetting Curve.pptx
Tata Sevilla
 
PG-BPSDMP 2 TAHUN 2025PG-BPSDMP 2 TAHUN 2025.pdf
AshifaRamadhani
 
Review of Related Literature & Studies.pdf
Thelma Villaflores
 
The Picture of Dorian Gray summary and depiction
opaliyahemel
 
Care of patients with elImination deviation.pptx
AneetaSharma15
 
PREVENTIVE PEDIATRIC. pptx
AneetaSharma15
 
5.EXPLORING-FORCES-Detailed-Notes.pdf/8TH CLASS SCIENCE CURIOSITY
Sandeep Swamy
 
Phylum Arthropoda: Characteristics and Classification, Entomology Lecture
Miraj Khan
 
Understanding operators in c language.pptx
auteharshil95
 
Landforms and landscapes data surprise preview
jpinnuck
 
Arihant Class 10 All in One Maths full pdf
sajal kumar
 
An introduction to Prepositions for beginners.pptx
drsiddhantnagine
 
Virat Kohli- the Pride of Indian cricket
kushpar147
 
vedic maths in python:unleasing ancient wisdom with modern code
mistrymuskan14
 
SAROCES Action-Plan FOR ARAL PROGRAM IN DEPED
Levenmartlacuna1
 
Wings of Fire Book by Dr. A.P.J Abdul Kalam Full PDF
hetalvaishnav93
 
CARE OF UNCONSCIOUS PATIENTS .pptx
AneetaSharma15
 
Software Engineering BSC DS UNIT 1 .pptx
Dr. Pallawi Bulakh
 
Measures_of_location_-_Averages_and__percentiles_by_DR SURYA K.pptx
Surya Ganesh
 
IMMUNIZATION PROGRAMME pptx
AneetaSharma15
 
Information Texts_Infographic on Forgetting Curve.pptx
Tata Sevilla
 
Ad

Google Sheets Programming With Google Apps Script Michael Maguire

  • 1. Google Sheets Programming With Google Apps Script Michael Maguire download https://ebookbell.com/product/google-sheets-programming-with- google-apps-script-michael-maguire-5321876 Explore and download more ebooks at ebookbell.com
  • 2. Here are some recommended products that we believe you will be interested in. You can click the link to download. Google Sheets Easy Coding For Beginners Learn Coding Fast Yao https://ebookbell.com/product/google-sheets-easy-coding-for-beginners- learn-coding-fast-yao-52856660 Improve Your Skills With Google Sheets Rmy Lentzner https://ebookbell.com/product/improve-your-skills-with-google-sheets- rmy-lentzner-23281692 Spreadsheets For Librarians Getting Results With Excel And Google Sheets Bruce White https://ebookbell.com/product/spreadsheets-for-librarians-getting- results-with-excel-and-google-sheets-bruce-white-43398080 A Beginners Guide To Google Drive And Sheets Step By Step Detailed Guide Tricks Tips And Shortcuts In Google Drive And Sheets William S Page https://ebookbell.com/product/a-beginners-guide-to-google-drive-and- sheets-step-by-step-detailed-guide-tricks-tips-and-shortcuts-in- google-drive-and-sheets-william-s-page-56901034
  • 3. A Beginners Guide To Google Drive And Sheets Step By Step Detailed Guide Tricks Tips Amd Shortcuts In Google Drive And Sheets 1st Edition William S Page https://ebookbell.com/product/a-beginners-guide-to-google-drive-and- sheets-step-by-step-detailed-guide-tricks-tips-amd-shortcuts-in- google-drive-and-sheets-1st-edition-william-s-page-12073556 Google Drive Docs In 30 Minutes The Unofficial Guide To The New Google Drive Docs Sheets Slides 2nd Edition Ian Lamont https://ebookbell.com/product/google-drive-docs-in-30-minutes-the- unofficial-guide-to-the-new-google-drive-docs-sheets-slides-2nd- edition-ian-lamont-6770030 Beginning Google Web Toolkit From Novice To Professional Beginning From Novice To Professional 1st Edition Bram Smeets https://ebookbell.com/product/beginning-google-web-toolkit-from- novice-to-professional-beginning-from-novice-to-professional-1st- edition-bram-smeets-1365342 Rainforest Google https://ebookbell.com/product/rainforest-google-22521924 Android Developer Fundamentals Unit 1 2nd Edition Google Developer Training Team https://ebookbell.com/product/android-developer-fundamentals- unit-1-2nd-edition-google-developer-training-team-36456436
  • 6. Google Sheets Programming With Google Apps Script (2015 Revision In Progress) Your Guide To Building Spreadsheet Applications In The Cloud Michael Maguire ©2016
  • 7. Tweet This Book! Please help Michael Maguire by spreading the word about this book on Twitter! The suggested hashtag for this book is #googlespreadsheetprogramming. Find out what other people are saying about the book by clicking on this link to search for this hashtag on Twitter: https://twitter.com/search?q=#googlespreadsheetprogramming
  • 8. Contents Chapter 1: Introduction . . . . . . . . . . . . . . . . . . . . 1 1.1 Google Sheets . . . . . . . . . . . . . . . . . . . . . 1 1.2 Google Apps Script (GAS) . . . . . . . . . . . . . . . 2 1.3 JavaScript or Google Apps Script? . . . . . . . . . . 3 1.4 Summary Of Topics Covered . . . . . . . . . . . . . 3 1.5 Software Requirements For This Book . . . . . . . . 5 1.6 Intended Readership . . . . . . . . . . . . . . . . . . 5 1.7 Book Code Available On GitHub . . . . . . . . . . . 6 1.8 My Blog On Google Spreadsheet Programming . . . 7 1.8 Guideline On Using This Book . . . . . . . . . . . . 7 1.9 2015 Update Notes . . . . . . . . . . . . . . . . . . . 8 Chapter 2: Getting Started . . . . . . . . . . . . . . . . . . 9 2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 9 2.2 Google Apps Script Examples . . . . . . . . . . . . . 9 2.2 Executing Code – One Function At A Time . . . . . 11 2.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . 14 Chapter 3: User-Defined Functions . . . . . . . . . . . . . 15 3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 15 3.2 Built-in Versus User-Defined Functions . . . . . . . 16 3.3 Why Write User-Defined Functions . . . . . . . . . 17 3.4 What User-Defined Functions Cannot Do . . . . . . 18 3.5 Introducing JavaScript Functions . . . . . . . . . . . 21 3.6 User-Defined Functions Versus JavaScript Functions 25 3.7 Using JSDoc To Document Functions . . . . . . . . . 26
  • 9. CONTENTS 3.8 Checking Input And Throwing Errors . . . . . . . . 26 3.9 Encapsulating A Complex Calculation . . . . . . . . 29 3.10 Numeric Calculations . . . . . . . . . . . . . . . . 31 3.11 Date Functions . . . . . . . . . . . . . . . . . . . . 33 3.12 Text Functions . . . . . . . . . . . . . . . . . . . . 39 3.13 Using JavaScript Built-In Object Methods . . . . . . 42 3.14 Using A Function Callback . . . . . . . . . . . . . 43 3.15 Extracting Useful Information About The Spreadsheet 45 3.16 Using Google Services . . . . . . . . . . . . . . . . 49 3.18 Summary . . . . . . . . . . . . . . . . . . . . . . . 50 Chapter 4: Spreadsheets and Sheets . . . . . . . . . . . . . 52 4.1 A Note On Nomenclature . . . . . . . . . . . . . . . 52 4.2 Native And Host Objects . . . . . . . . . . . . . . . 53 4.3 A Note On Method Overloading In Google Apps Script 53 4.5 Object Hierarchies . . . . . . . . . . . . . . . . . . . 54 4.6 SpreadsheetApp . . . . . . . . . . . . . . . . . . . . 57 4.7 The Spreadsheet Object . . . . . . . . . . . . . . . . 58 4.8 The Sheet Object . . . . . . . . . . . . . . . . . . . . 62 4.9 Practical Examples Using Spreadsheet And Sheet Objects . . . . . . . . . . . . . . . . . . . . . . . 63 4.10 Summary . . . . . . . . . . . . . . . . . . . . . . . 69 Chapter 5: The Range Object . . . . . . . . . . . . . . . . . 71 5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 71 5.2 Range Objects Are Complex . . . . . . . . . . . . . 73 5.3 Creating A Range Object . . . . . . . . . . . . . . . 74 5.4 Getting And Setting Range Properties . . . . . . . . 75 5.5 The Range offset() Method . . . . . . . . . . . . . . 78 5.6 The Sheet Data Range . . . . . . . . . . . . . . . . . 80 5.7 Transferring Values Between JavaScript Arrays And Ranges . . . . . . . . . . . . . . . . . . . . . . . . 82 5.8 Named Ranges . . . . . . . . . . . . . . . . . . . . . 89 5.9 Practical Examples . . . . . . . . . . . . . . . . . . . 91 5.11 Concluding Remarks . . . . . . . . . . . . . . . . . 104
  • 10. CONTENTS 5.12 Summary . . . . . . . . . . . . . . . . . . . . . . . 105 Chapter 6: MySQL And JDBC . . . . . . . . . . . . . . . . 106 6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 106 6.2 What Is JDBC? . . . . . . . . . . . . . . . . . . . . . 107 6.3 MySQL Preliminaries . . . . . . . . . . . . . . . . . 108 6.4 Connecting to a Cloud MySQL Database from the mysql Client . . . . . . . . . . . . . . . . . . . . . 109 6.5 An Overview of JDBC . . . . . . . . . . . . . . . . . 111 6.6 Note on Code Examples . . . . . . . . . . . . . . . . 112 6.7 Connecting to the Database . . . . . . . . . . . . . . 113 6.8 Create, Load, Query, Update and Delete a Database Table . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.9 Prepared Statements . . . . . . . . . . . . . . . . . . 126 6.10 Transactions . . . . . . . . . . . . . . . . . . . . . 129 6.11 Database Metadata . . . . . . . . . . . . . . . . . . 131 6.12 A Practical GAS Example . . . . . . . . . . . . . . 133 6.13 Summary . . . . . . . . . . . . . . . . . . . . . . . 143 Chapter 7: User Interfaces - Menus and Forms . . . . . . . 144 7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 144 7.2 Adding A Menu . . . . . . . . . . . . . . . . . . . . 145 7.3 Building Forms With HtmlService . . . . . . . . . . 147 7.3.3 Defining Form Layout in CSS . . . . . . . . . . . . 158 7.4 Transferring Data from Google Sheets To an HtmlSer- vice Web Application . . . . . . . . . . . . . . . . 163 7.5 Create Professional-looking Forms the Easy Way - Use Bootstrap . . . . . . . . . . . . . . . . . . . . 173 7.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . 177 Chapter 8: Google Drive, Folders, Files, And Permissions 178 8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 178 8.2 List Google Drive File And Folder Names . . . . . . 180 8.3 Creating And Removing Files And Folders . . . . . . 183 8.4 Adding Files To And Removing Files From Folders . 186
  • 11. CONTENTS 8.5 File And Folder Permissions . . . . . . . . . . . . . 190 8.6 Practical Examples . . . . . . . . . . . . . . . . . . . 197 8.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . 210 Chapter 9: Email and Calendars . . . . . . . . . . . . . . . 211 9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . 211 9.2 Sending An Email Using MailApp . . . . . . . . . . 212 9.3 Sending An Email With An Attachment Using MailApp 214 9.4 GmailApp . . . . . . . . . . . . . . . . . . . . . . . 216 9.5 Calendars . . . . . . . . . . . . . . . . . . . . . . . 229 9.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . 236 Appendix A: Excel VBA And Google Apps Script Com- parison . . . . . . . . . . . . . . . . . . . . . . . . . . . 237 Introduction . . . . . . . . . . . . . . . . . . . . . . . . 237 Spreadsheets and Sheets . . . . . . . . . . . . . . . . . 238 Ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Appendix B: Final Notes . . . . . . . . . . . . . . . . . . . 268 Additional Resources . . . . . . . . . . . . . . . . . . . 268 JSLint . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 Getting Source code For This Book From Github . . . . 270 Blog Updates . . . . . . . . . . . . . . . . . . . . . . . . 270
  • 12. Chapter 1: Introduction 1.1 Google Sheets Google Sheets is one of the core components of Google cloud applications. If you have a Gmail account, you can create and share your spreadsheets with others, even with those who do not have a Gmail account. Google Sheets offers a comprehensive set of standard spreadsheet features and functions similar to those found in other spreadsheet applications such as Microsoft Excel. In addition, it also supports some novel features such as the very versatile QUERY function and regular expression functions such REGEXMATCH. What really distinguished Google Sheets from desktop spreadsheet applications like Excel is its cloud nature. The spreadsheet appli- cation runs in a browser and the spreadsheet files themselves are stored remotely. The spreadsheet files can be shared with others in read-only or read-edit modes making them ideal collaborative tools. Spreadsheets form just one part, albeit an important one, of the Google suite of products. Others are Google Documents, Gmail, calendars, forms, and so on and all of these products are inter-operable at least to some degree resulting in a very productive environment perfectly suited to collaborative work. When I began using Google Sheets back in 2010 it was quite limited in terms of data volume, speed and functionality. It has undergone significant development since then and got a major upgrade in March 2014¹. If your experience of Google Sheets was negatively influenced by experience with earlier versions, I encourage you to try it again, I think you will notice a big improvement. The ¹https://support.google.com/docs/answer/3544847?hl=en
  • 13. Chapter 1: Introduction 2 old 400,000 cell limit per spreadsheet is gone and is now at least 2,000,000. It will comfortably deal with tens of thousands of rows which is, I believe, quite acceptable for any spreadsheet. Other spreadsheet applications such as Excel can handle a million plus rows but when data volumes grow to this size, it is advisable to switch to a database or a dedicated statistical application to handle such data sizes. 1.2 Google Apps Script (GAS) The Google Sheets application also hosts a programming language called Google Apps Script (GAS) that is executed, not in the browser but remotely on the Google cloud. Google define Google Apps Script as follows: “Google Apps Script is a JavaScript cloud scripting language that provides easy ways to automate tasks across Google products and third party services.” If Google Sheets is so feature-rich, you might wonder why it needs to host a programming language. Here are few reasons why GAS is needed: • Write user-defined functions for Google Sheets • Write simple “macro” type applications • Develop spreadsheet-based applications • Integrate other Google products and services • Develop Graphical User Interfaces (GUIs) that can be run as web applications • Interact with cloud-based relational databases via Google JDBC Services. GAS plays a similar role in Google Sheets to that played by Visual Basic for Applications (VBA) in Excel. Both are hosted by their
  • 14. Chapter 1: Introduction 3 respective applications and both are used to extend functionality and integrate with other applications and services. 1.3 JavaScript or Google Apps Script? The emphasis here is on using GAS to enhance and control Google Sheets. Other Google services are discussed in the context of how they can be used with Google Sheets. Since GAS is JavaScript (Google describe it as a sub-set of JavaScript 1.8), there will in- evitably be discussion of JavaScript as a programming language. There is, therefore, some discussion of JavaScript topics as they relate to the code examples given. Regarding terminology, when discussing a general JavaScript fea- ture, the code may be referred to as “JavaScript” but when dealing with a Google App specific example, it may be referred to as “Google Apps Script” or “GAS”. The meaning of whichever term is used should be clear from the context. For example, the Spreadsheet object is central to Google Sheets programming. It is, however, pro- vided by the hosting environment and is not part of JavaScript itself. This duality of the programming language and the objects provided by the hosting environment is similar to JavaScript running on the web client and the Document Object Model (DOM) entities that it manipulates. 1.4 Summary Of Topics Covered This book aims to provide the reader with a solid knowledge of the GAS language both as it applies to Google Sheets and how it is used to allow Google Sheets to inter-operate with other Google products and services as well as with relational databases. Chapter 2 introduces the GAS language and sets the scene for the chapters that follow. One of the most important applications
  • 15. Chapter 1: Introduction 4 of the hosted spreadsheet language, be it VBA or GAS, is to allow users to write user-defined functions (also known as custom functions). These are covered in depth in chapter 3 and this chapter merits careful reading for any readers not familiar with JavaScript. Functions are central to JavaScript and, by extension, to GAS. The Spreadsheet, Sheet, and Range objects are crucial for manip- ulating Google Sheets with GAS and these objects are covered in depth in chapters 4 and 5. All subsequent chapters assume that the reader is comfortable with these objects, their methods and their uses. Having covered the basics of user-defined functions and the fun- damental spreadsheet objects, chapter 6 explains how GAS can be used to work with a back-end relational database (MySQL). Spreadsheets are great tools but they have their limitations and, as applications increase both in complexity and in data volume, there comes a point where a more robust data storage solution is needed that that offered by spreadsheets. In order to build spreadsheet applications some sort of Graphical User Interface (GUI) is usually required. Chapters 7 and 8 cover menus, alerts, prompts and user forms created using Google Html Service. Creating forms with Html Service offers the opportunity to develop web skills such as HTML, CSS and client-side JavaScript. For those not experienced in frontend development, this material offers a gentle introduction to a very important skill. In addition to being an excellent collaborative tool, Google Sheets is part of a larger set of applications with which it can interact. GAS written in Google Sheets can be used to manipulate other Google products such as Google Drive, and Google Calendar and this aspect of GAS programming is covered in chapters 9 and 10. For those coming to GAS from Excel VBA, appendix A will be of especial interest as it gives example code and explanations of how to perform common spreadsheet programming tasks in both languages. Appendix B gives an example of a quite complex spread-
  • 16. Chapter 1: Introduction 5 sheet application written in GAS that brings together much of the material covered earlier. It describes how to build an application that takes spreadsheet data as input and uses it to generate SQL for table creation and row insertion. Appendix C discusses additional GAS and JavaScript resources that will be of interest to readers. 1.5 Software Requirements For This Book Not many! Modern cloud-based applications such as Google Sheets greatly reduce the technical barriers for new entrants. In the old days, you might have needed a specific operating system running some proprietary and often expensive software to get started. Not anymore! Anyone with a modern browser, an internet connection and a Gmail account running on Windows, Mac OS X or any version of Linux will be able to follow along with this book and run the code examples given. The code examples should run in any modern browser but I mainly use Chrome and Firefox and never use Internet Explorer (IE) although I expect that all the code will run fine in any post IE7 version. 1.6 Intended Readership This book is written for those who wish to learn how to program- matically manipulate Google Sheets using GAS. I began learning GAS for two reasons. Firstly, I was using Google Sheets as a collaborative tool in my work and, secondly, I had become aware of the increasing importance of JavaScript generally and was keen to learn it. Being able to use the JavaScript-based language that is GAS in spreadsheets appealed to me because I was already quite experienced in programming Excel using VBA so I felt that learning GAS to manipulate Google Sheets would offer a familiar
  • 17. Chapter 1: Introduction 6 environment. I reasoned that there are many experienced Excel VBA programmers around who might feel similarly so that is why I wrote this book. There are of course now many people who use Google products who are familiar with JavaScript but who may not know much about spreadsheets. This book might also be of interest to this group of users. This book assumes programming knowledge in some programming language though not necessarily JavaScript. 1.7 Book Code Available On GitHub The emphasis on this book is on practical code examples. Some of the code examples are short and only practical in the sense that they exemplify a GAS feature. GAS is a “moving target” in that new features are added and deprecated frequently thereby making it difficult to keep all code up-to-date. At the time of writing, all the examples worked as expected but please email me² if something is broken or if you get a warning of something having been deprecated. To allow readers to follow along, I have tried to document the code extensively using JSDoc³ and in-line code comments. To run the examples, you can copy and paste from the book to the GAS Script Editor. This will work but I recommend getting the code from GitHub. All the code examples in this book are available on a Github repository created specifically for this updated version of the book. The user name is Rotifer and the repository name is GoogleSpreadsheetProgramming_2015. The full URL is here.⁴ You can use the Git command line tool to check out the repository to your local machine or simply copy the examples directly from the GitHub repository. ²[email protected] ³usejsdoc.org/ ⁴https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015
  • 18. Chapter 1: Introduction 7 1.8 My Blog On Google Spreadsheet Programming I maintain a blog⁵ that pre-dates this book. The blog began in late 2010 so some of the early examples use deprecated or unsupported features. That said, the blog inspired this book and is actively maintained so it can be viewed as a complementary resource to this book. It is worth checking for new entries from time to time because I use it to explore and discuss new spreadsheet and GAS features and I cover some more advanced JavaScript material there. 1.8 Guideline On Using This Book I learn best from examples so this book is heavily example-driven. I first like to see something working and then examine it and learn from it. In order to derive maximum benefit from this book, it is important to execute the code from your own spreadsheets. Read the book descriptions and code documentation carefully and make sure that you understand both the objective of the code as well as how it works. Chapter 3 goes in to some depth on core JavaScript concepts such as functions, arrays and objects but if you are relatively inexperienced in JavaScript, then some background reading will help enormously. Remember, GAS is JavaScript so the better you understand JavaScript, the better you will be at writing and understanding GAS. Do not be afraid to experiment with code, change or re-write my examples at will! If you find better ways of doing things, please let me know! ⁵http://www.javascript-spreadsheet-programming.com
  • 19. Chapter 1: Introduction 8 1.9 2015 Update Notes The first version of this book was released in November 2013 and the feedback I have received on it has been largely positive. However, I realise that some of the material is now out-of-date. For example, UiApp and DocsList have both been deprecated since that version of the book was released. I am also aware that the book could be improved by better explanations, better examples and generally better writing. I hope this version delivers a better product to its readers. As I stated earlier, Google Sheets and GAS are “moving targets” that are subject to constant change. I intend to release a new version of this book yearly from now on so that the material remains current and the overall quality of the book improves. I will continue to blog about new features and topics that I have not covered so far and, if these look like a good fit and attract interest from readers, I will incorporate such subjects into later version of the book. Something I find annoying and expensive is when I buy a technical book only to learn a few months later that a new edition has been released. I have one shell programming book from 1990 that I still use but shell programming is one of the few stable technologies that I use (SQL is another, yes, features are added but the core is quite stable). Most technical books that I have bought in the past become obsolete, at least in part, in a year or two. My idea with this book is to make sure those who buy it once get all the updates for free and I plan to keep updating it indefinitely. Leanpub make this possible, so a big thanks to them and thanks also to all of you who bought the first version of this book! Time to write some GAS!
  • 20. Chapter 2: Getting Started 2.1 Introduction The best way to learn JavaScript/Google Apps Script is to write some code. Getting started is very straightforward: All that is needed is a Gmail account and a browser with an Internet con- nection. To run some example code, first go to Google Drive and create a spreadsheet. To view the script editor, select Tools->Script editor… from the spreadsheet menu bar. The first time you do this in a new spreadsheet file, you will be presented with a pop-up window entitled “Google Apps Script”, just ignore and close it for now. Give the project a name, any name you like, by hovering over and replacing the text “untitled project” on the top left. Delete the code stub entitled “myFunction” so that the script editor is now blank. Paste in the example code in the following sections and save (save icon or menu action File->Save). 2.2 Google Apps Script Examples Here are four example functions. When pasted into the script editor, the code formatting applied by the editor becomes evident and makes the code easier to read. The code for this chapter can be viewed and downloaded from GitHub here.⁶ ⁶https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015/blob/master/ch02. gs
  • 21. Chapter 2: Getting Started 10 1 function sayHelloAlert() { 2 // Declare a string literal variable. 3 var greeting = 'Hello world!', 4 ui = SpreadsheetApp.getUi(); 5 // Display a message dialog with the greeting 6 //(visible from the containing spreadsheet). 7 // Older versions of Sheets used Browser.msgBox() 8 ui.alert(greeting); 9 } 10 11 function helloDocument() { 12 var greeting = 'Hello world!'; 13 // Create DocumentApp instance. 14 var doc = 15 DocumentApp.create('test_DocumentApp'); 16 // Write the greeting to a Google document. 17 doc.setText(greeting); 18 // Close the newly created document 19 doc.saveAndClose(); 20 } 21 22 function helloLogger() { 23 var greeting = 'Hello world!'; 24 //Write the greeting to a logging window. 25 // This is visible from the script editor 26 // window menu "View->Logs...". 27 Logger.log(greeting); 28 } 29 30 31 function helloSpreadsheet() { 32 var greeting = 'Hello world!', 33 sheet = SpreadsheetApp.getActiveSheet(); 34 // Post the greeting variable value to cell A1 35 // of the active sheet in the containing
  • 22. Chapter 2: Getting Started 11 36 // spreadsheet. 37 sheet.getRange('A1').setValue(greeting); 38 // Using the LanguageApp write the 39 // greeting to cell: 40 // A2 in Spanish, 41 // cell A3 in German, 42 // and cell A4 in French. 43 sheet.getRange('A2') 44 .setValue(LanguageApp.translate( 45 greeting, 'en', 'es')); 46 sheet.getRange('A3') 47 .setValue(LanguageApp.translate( 48 greeting, 'en', 'de')); 49 sheet.getRange('A4') 50 .setValue(LanguageApp.translate( 51 greeting, 'en', 'fr')); 52 } 2.2 Executing Code – One Function At A Time In order to execute code, there must be at least one valid function in the script editor. After pasting the code above, there are four functions that will each be executed in turn.
  • 23. Chapter 2: Getting Started 12 Figure 2-1: Google Apps Script Editor displaying the code and the “Select function” drop-down list. Select function sayHelloAlert() from the “Select function” drop- down list on the script editor toolbar and then press the execute icon (to the left of the function list drop-down). You will need to authorize the script when you first try to execute it. Subsequent executions do not require authorisation. Once authorised, switch to the spreadsheet and you will see a small window with the greeting “Hello world”. These browser popup displays are modal meaning that they block all subsequent code execution until they are closed. For this reason, their use should be limited. The Logger is generally a better tool for writing and displaying output. New Sheets Feature Browser.msgBox instead of alert() is used in older versions and still works.
  • 24. Chapter 2: Getting Started 13 Now select the second function named helloDocument() and exe- cute it. This is a much more interesting example than the previous one because it shows how GAS written in one application can be used to manipulate other applications. The first time you try to execute it, you will get a message saying, “Authorization required”. Once you authorise it and then execute, it will create a new Google Document and write the message to it. This example, though trivial and useless, does demonstrate how GAS code written in one application can manipulate other applications. This is a very powerful feature and will be a recurring theme of this book. The helloLogger() function, when executed, writes the message to a logging area that is viewable from the script editor menu “View- >Logs…”. It is equivalent to the “console.log” in Firebug and Node.js. It will be used frequently in later code examples for output and for error reporting. The final function helloSpreadsheet() demonstrates two important aspects of Google Apps Script: Firstly, spreadsheets can be manipulated via the Spreadsheet object (the Google documentation refers to Spreadsheet as a “class”). It provides a method that returns an object representing the active sheet (getActiveSheet()) and that this returned object has a method that returns a range (getRange()), in this instance a single cell with the address “A2”. The returned range object method, setValue(), is then called with a string argument that is written to cell A1 of the active sheet. These types of chained method calls look daunting at first. The method call chain described above could be re-written as:
  • 25. Chapter 2: Getting Started 14 1 var greeting = 'Hello world!', 2 activeSpreadsheet = 3 SpreadsheetApp.getActiveSpreadsheet(), 4 activeSheet = 5 activeSpreadsheet.getActiveSheet(), 6 rng = activeSheet.getRange('A1'), 7 greeting = 'Hello world!'; 8 rng.setValue(greeting); The code above uses a number of intermediate variables and may be easier to understand initially but after experience with GAS, the chained method call will start to feel easier and more natural. The objects referenced in this example will be discussed in detail in chapters 4 and 5. Secondly, the example code shows how easy it is to call another service from a Google Apps Script function. Here the LanguageApp was used to translate a simple text message into Spanish, German, and French. This ability to seamlessly access other Google services is extremely powerful. 2.3 Summary This chapter has shown how to access the GAS Script Editor and execute functions from it. The examples demonstrated how GAS can display simple alerts, write messages to the Logger, manipulate ranges in spreadsheets and use other Google applications such as Document and Google services such as LanguageApp. These examples barely scrape the surface of what can be achieved using GAS. The next chapter uses GAS to write user-defined functions that can be called in the same manner as built-in spreadsheet functions.
  • 26. Chapter 3: User-Defined Functions 3.1 Introduction User-defined functions allow spreadsheet users and developers to extend spreadsheet functionality. No spreadsheet application can cater for all requirements for all users so a mechanism is provided that allows users to write their own customised functions in the hosted language, be that VBA in Excel or GAS in Google Sheets. Definition A user-defined function is one that can be called using the equals (=) sign in a spreadsheet cell and writes its return value or values to the spreadsheet. User-defined functions are also known as custom functions and this is the term used by the Google. Google Custom Function Doc- umentation Worth Reading!⁷. The source code for this chapter can be found here on GitHub.⁸ I have adopted the convention of writing user-defined functions in ⁷https://developers.google.com/apps-script/guides/sheets/functions ⁸https://github.com/Rotifer/GoogleSpreadsheetProgramming_2015/blob/master/ch03. gs
  • 27. Chapter 3: User-Defined Functions 16 all upper case, other fiunctions that are not intended to be called as user-defined functions are written in camel case. This chapter is quite long and covers a lot of material. It is also the chapter where I put most effort into explaining basic JavaScript concepts such as functions, arrays, objects and so on. Therefore, if you are unfamiliar with GAS/JavaScript, then pay close attention to the code examples and explanatory text. If my explanations are inadequate, then you can take advantage of the extensive on-line JavaScript resources available for all levels of user in addition to the many excellent JavaScript textbooks (see Appendix B for information on resources that I have found useful). 3.2 Built-in Versus User-Defined Functions Modern spreadsheet applications, including Google Sheets, supply a large number of built-in functions and they owe much of their utility and widespread usage in diverse domains of finance, science, engineering and so on to these functions. There is also a high degree of standardisation between spreadsheet applications regard- ing function names, arguments, and usage so that they generally work uniformly in Google Sheets, Microsoft Excel, OpenOffice Calc and Gnumeric. Built-in Google Sheets functions are spread over multiple categories, see Google Spreadsheet function list ⁹. Most of the standard spreadsheet text, date, statistical, logic and lookup functions are present and their usage is, in all cases that I have encountered, identical to equivalents in other spreadsheet applications. Google Sheets also implements a number of novel functions. Some of these are very convenient and it is worth being familiar with them before you embark on writing your own functions so that you do not end up implementing something that is already present. One ⁹https://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cs
  • 28. Chapter 3: User-Defined Functions 17 of my favourites is the QUERY function and a good description of its syntax and use can be found here¹⁰. This function comes from the Google Visualization API and it uses an SQL-like syntax to extract sub-sets of values from input spreadsheet data cells. If you are already familiar with SQL, then you will feel right at home with this function. Another group of functions worth exploring are those that use regular expressions. The functions concerned are REGEXMATCH, REGEXEXTRACT and REGEXREPLACE and I have described them in a blog entry¹¹. Regular expressions are very useful and GAS implements the full standard JavaScript regular expression specification. New Functionality Google Sheets continues to add new functions 3.3 Why Write User-Defined Functions The two main reasons for writing user-defined functions are for clarity and to extend functionality. User-defined functions can add to clarity by wrapping complex computations in a named and doc- umented function. Spreadsheet power-users can often ingeniously combine the built–in functions to effectively create new ones. The disadvantage of this approach is that the resulting formulas can be very difficult to read, understand and debug. When such function- ality is captured in a function, it can be given a name, documented and, tested. Secondly, user-defined functions allow developers to customise spreadsheet applications by adding functionality for their particular domain. ¹⁰https://anandexcels.wordpress.com/2013/11/01/query-function-in-google-sheets/ ¹¹http://www.javascript-spreadsheet-programming.com/2013/09/regular- expressions.html
  • 29. Chapter 3: User-Defined Functions 18 3.4 What User-Defined Functions Cannot Do An important point about user-defined functions is that they cannot be used to alter any properties, such as formats, of the spreadsheet or any of its cells. They cannot be used to send e-mails and cannot be used to insert new worksheets. Functions can be used to do these things but they cannot be called as user-defined functions. This is a common area of misunderstanding where users attempt to call functions from the spreadsheet using the equals operator (=). This results in an error because the function is trying to set some spreadsheet property. User-defined functions should be designed to work just like built-in functions in that you pass in zero or more values as arguments and they return a value or values in the form of an array. Their purpose is their return values, not their side effects. Excel VBA makes a distinction between subroutines and functions. Subroutines do not return a result and cannot be called as user-defined functions. In GAS we only have functions that either return values or do not (void functions). To illustrate how a user-defined function cannot alter spreadsheet properties, consider the following function that takes a range ad- dress argument (a string, not a Range object) and sets the font for the range to bold: Code Example 3.1
  • 30. Chapter 3: User-Defined Functions 19 1 /** 2 * Simple function that cannot be called from 3 * the spreadsheet as a user-defined function 4 * because it sets a spreadsheet property. 5 * 6 * @param {String} rangeAddress 7 * @return {undefined} 8 */ 9 function setRangeFontBold (rangeAddress) { 10 var sheet = 11 SpreadsheetApp.getActiveSheet(); 12 sheet.getRange(rangeAddress) 13 .setFontWeight('bold'); 14 } The code uses objects that have not yet been discussed but the idea is simple; Take a range address as input and set the font to bold for that range. However, when the function is called from a spreadsheet, it does not work. Figure 3-1: Error displayed when calling a function with side effects from a spreadsheet. The error shown above refers to permissions but the problem is that the called function is attempting to modify sheet properties. To prove that the function setRangeFontBold() is valid, here is a function that prompts for a range address using an prompt dialog. It calls the setRangeFontBold() function passing the given range address as an argument.
  • 31. Chapter 3: User-Defined Functions 20 To See The Prompt Call the function in the Script Editor Then switch to the spreadsheet Code Example 3.2 1 /** 2 * A function that demonstrates that function 3 * "setRangeFontBold() is valid although it 4 * cannot be called as a user-defined function. 5 * 6 * @return {undefined} 7 */ 8 function call_setCellFontBold () { 9 var ui = SpreadsheetApp.getUi(), 10 response = ui.prompt( 11 'Set Range Font Bold', 12 'Provide a range address', 13 ui.ButtonSet.OK_CANCEL), 14 rangeAddress = response.getResponseText(); 15 setRangeFontBold(rangeAddress); 16 } When this function is called, the following prompt is displayed in the spreadsheet view:
  • 32. Chapter 3: User-Defined Functions 21 Figure 3-2: *Prompt dialog display for a range address. The prompt mechanism for requesting user input will be discussed in a later chapter. The important point here is that a function may be valid but, if it has side effects such as altering range properties, then it cannot be called as a user-defined function. New Sheets Feature Browser.inputBox instead of prompt() is used in older versions and still works. 3.5 Introducing JavaScript Functions User-defined functions can be called exactly like built-in ones using the equals (=) operator in a spreadsheet cell. They can take zero or more arguments of different types and these arguments can be either cell references or literal values, just as with built-in functions. The user-defined functions themselves are written in GAS and, as I have repeated multiple times already, GAS is JavaScript. To understand and write user-defined functions in Google Sheets requires an understanding of JavaScript functions. The better you understand JavaScript functions, the better you will be at crafting your own user-defined GAS functions for Google Sheets!
  • 33. Chapter 3: User-Defined Functions 22 JavaScript functions are immensely powerful and flexible. They play a central role in many JavaScript idioms and patterns and mas- tery of them is a prerequisite to becoming an advanced JavaScript programmer. Only the basics of JavaScript functions are required for the purposes of this chapter. There are different ways of defining JavaScript functions but in this chapter most of the functions are defined as function declarations in form: 1 function functionName(comma-separated 2 parameters) { 3 statements 4 } Other types of function definition will be described as they are introduced later in the book. JavaScript Functions Read this Mozilla resource¹² The Mozilla resource above discusses various means of defining JavaScript functions. For user-defined functions the decision on the syntax to use to define our functions is made for us because only function declarations work in this setting, named function expressions and object methods will not work. For the purposes of this chapter, here are the principal additional points of note regarding JavaScript functions: • When the function is called, the arguments passed in are assigned to the parameters in the function definition. • These arguments can then be used within the function body. ¹²https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
  • 34. Chapter 3: User-Defined Functions 23 • Parameters are always passed by value in JavaScript but when reference types, such as arrays, are used, the behaviour can appear pass-by-reference. • If the number of arguments passed in is less than the number of parameters in the function definition, the unassigned parameters are given the value undefined. • Variables declared within the function using the var state- ment are local. That means that they are scoped to that function and are not visible outside the function. • Functions in JavaScript are objects and they define a number of pre-defined properties. • Two function properties are important for this chapter. These are the arguments object and the length property. • The arguments object is an array-like list that stores all the arguments passed to the function when it is called. • The arguments object is not an array but, like the Array type, it does have a length property that stores the number of arguments that were actually given when the function was called and its elements can be accessed using array-like indexing • The length property of the function stores the number of arguments the function expects based on the number of parameters in the function definition. • Since JavaScript functions can accept any number of ar- guments of any type regardless of the parameter list, the arguments.length value can be compared to the function length property to check if the argument count is as expected. • Functions can have an explicit return statement. If no return statement is specified, the function will return the value undefined. • User-defined functions without a return statement are point- less. • A return statement on its own can be used to exit the function
  • 35. Chapter 3: User-Defined Functions 24 and will return undefined, again, not much use in user- defined functions. • User-defined functions should always return some value other than undefined. • The returned value can be a primitive such as a string, Boolean, or a number. It can also be a reference type such as a JavaScript object or an array. To see some of these points in action, paste the following code example 3.3 into the Script Script editor and choose and run the second function named call_testFunc. The point of this example is to show how the number of function arguments and the argument data types can be determined in JavaScript. Code Example 3.3 1 /** 2 * Function to demonstrate how to check 3 * the number and types of passed arguments. 4 * 5 * 6 * @return {undefined} 7 */ 8 function testFunc(arg1, arg2) { 9 var i; 10 Logger.log('Number of arguments given: ' + 11 arguments.length); 12 Logger.log('Number of arguments expected: ' + 13 testFunc.length); 14 for (i = 0; i< arguments.length; i += 1) { 15 Logger.log('The type of argument number ' + 16 (i + 1) + ' is ' + 17 typeof arguments[i]); 18 } 19 }
  • 36. Chapter 3: User-Defined Functions 25 The function output demonstrates how JavaScript functions can check the number of arguments passed in and the type of each argument by: 1. Checking the argument count given when the function is called (arguments.length) against the argument count ex- pected based on the parameter list in the function definition (the function length property). 2. Using the typeof operator to determine the type of each given argument. The typeof operator can also be used to identify missing argument values where the missing value will be of type undefined. This check can be used to assign defaults using the statement if (typeof arg === ‘undefined’ ) { arg = default; }. 3.6 User-Defined Functions Versus JavaScript Functions When user-defined functions are called from within spreadsheet cells, their string arguments must be provided in double quotes. In JavaScript, either single or double quotes can be used to enclose a string literal but only double quotes are acceptable for string literals in user-defined functions. Single quote usage can lead to puzzling errors so beware! JavaScript function names and variable names are case-sensitive, function afunc () { … } and function aFunc () { … } are two different functions (unlike VBA). However, when called from a spreadsheet, the function names are case-insensitive. The implication of this is to be very careful when naming functions to be called from a spreadsheet. Camel casing is the JavaScript standard and is used throughout here except when defining testing functions that may be given the prefix “testing”/”run” or when writing user-defined functions where the function names are all in uppercase.
  • 37. Chapter 3: User-Defined Functions 26 3.7 Using JSDoc To Document Functions JSDoc is a markup language, inspired by its Java equivalent called Javadoc, for adding comments and structured annotation to JavaScript code. A sub-set of JSDoc can be used to document user-defined functions. The JSDoc markup can then be extracted using various tools to auto-generate documentation. It is defined by a special type of multi-line commenting where the opening comment tag is defined with a special opening tag of a forward slash followed by a double asterisk: 1 /** 2 * Line describing the function 3 * @param {data type} parameter name 4 * @return {data type} 5 * @customfunction 6 */ The documentation example above contains a description line and three types of annotation tags denoted by a leading “@”. Each function paramater should be assigned an @param tag denoting the expected data type and the parameter name. Unsurprisingly, the return data type is given the @return tag. The final tag is called @customfunction and it is used to signify that the function is is intended to be called as a user-defined function. When JSDoc is used with this tag, the user-defined functions appear in the autocomplete on entering the function name preceded by an equals sign in a spreadsheet cell. 3.8 Checking Input And Throwing Errors JavaScript functions are flexible and can be called with any number of arguments of any type. Stricter languages offer some protection
  • 38. Chapter 3: User-Defined Functions 27 against bad argument values. Most languages throw errors if the passed argument count does not match the parameter count while static languages such as Java check the given data types of function and method arguments. JavaScript takes a very relaxed approach but inappropriate argument types can cause errors or, more seriosly, bugs where the return value may not be what you expect. For example: Code Example 3.4 1 // Function that is expected 2 // to add numbers but will also 3 // "add" strings. 4 function adder(a, b) { 5 return a + b; 6 } 7 // Test "adder()" with numeric arguments 8 // and with one numeric and one string 9 // argument. 10 function run_adder() { 11 Logger.log(adder(1, 2)); 12 Logger.log(adder('cat', 1)); 13 } The problem here is twofold. Firstly, the adder() function takes arguments of any type. Secondly, the + operator can do string con- catenation as well as numeric addition. When one of the operands is a string, JavaScript silently coerces the other argument to type string. Although this example is contrived, it does illustrate a potential source of bugs. One way to guard against this is to explicitly check each argument type and then throw an error if any of the arguments is of the wrong type. The typeof operator can be used to do this. Here is a version of the adder() function that does exactly this: Code Example 3.5
  • 39. Chapter 3: User-Defined Functions 28 1 // Function that is expected 2 // to add numbers but will also 3 // "add" strings. 4 function adder(a, b) { 5 return a + b; 6 } 7 8 // Function that checks that 9 // both arguments are of type number. 10 // Throws an error if this is not true. 11 function adder(a, b) { 12 if (!(typeof a === 'number' && 13 typeof b === 'number')) { 14 throw TypeError( 15 'TypeError: ' + 16 'Both arguments must be numeric!'); 17 } 18 return a + b; 19 } 20 21 // Test "adder()" with numeric arguments 22 // Thrown error is caught, see logger. 23 function run_adder() { 24 Logger.log(adder(1, 2)); 25 try { 26 Logger.log(adder('cat', 1)); 27 } catch (error) { 28 Logger.log(error.message); 29 } 30 } Now the function adder() throws an error if either of the arguments is non-numeric. The test function run_adder() uses a try .. catch construct to deal with the error. Detecting and dealing with incor- rect arguments in functions may or may not be a priority depending
  • 40. Chapter 3: User-Defined Functions 29 on circumstances. The typeof operator is adequate for primitive data types such as numbers and strings but limited for objects. For example, it reports arrays as type object, true but not very useful. When passing objects to functions, the instanceof operator is better suited for type checking. 3.9 Encapsulating A Complex Calculation The relative standard deviation¹³ (RSD) is frequently used in statistics to express and compare variability of data sets. It is not provided as a built-in spreadsheet function. The formula to calculate it is simply the sample standard deviation divided by the sample mean multiplied by 100. Given the following values in cells A1 to A10: 19.81 18.29 21.47 22.54 20.17 20.1 17.61 20.91 21.62 19.17 The RSD rounded to two decimal places can be calculated using this spreadsheet formula: 1 =ROUND(100*(STDEV(A1:A10)/AVERAGE(A1:A10)),2) The functionality expressed in this spreadsheet formula can be encapsulated in a user-defined function as follows: Code Example 3.6 ¹³http://en.wikipedia.org/wiki/Relative_standard_deviation
  • 41. Chapter 3: User-Defined Functions 30 1 /** 2 * Given the man and standard deviation 3 * return the relative standard deviation. 4 * 5 * @param {number} stdev 6 * @param {number} mean 7 * @return {number} 8 * @customfunction 9 */ 10 function RSD (stdev, mean) { 11 return 100 * (stdev/mean); 12 } This function can be called as follows: 1 =RSD(STDEV(A1:A10),AVERAGE(A1:A10)) Figure 3-3: *Calling the RSD function in Google Sheets with provided auto- complete. The above function can be pasted into the Script Editor and called as described in the documentation. So what was gained by writing a user-defined function when a combination of spreadsheet built- in functions can be used and the user-defined version still uses the spreadsheet STDEV and AVERAGE built-ins? Firstly, the calcula- tion now has a meaningful name. Secondly, argument checking can be added as described in the previous section. Lastly, the logic is captured in one place and is documented. These are all good reasons
  • 42. Chapter 3: User-Defined Functions 31 to consider replacing complex spreadsheet formulas with user- defined functions. In addition, our JSDoc description now appears in the autocomplete. 3.10 Numeric Calculations The following example takes a single numeric argument as degrees Centigrade and uses that argument to return the temperature in Fahrenheit. To use, paste the function into the Google Apps Script editor and then call it by name in a cell in the containing spread- sheet. For example, if cell A1 contains the value 0, then the formula =CELSIUSTOFAHRENHEIT(A1) in cell B1 will return the result 32 as expected. Code Example 3.7 1 /** 2 * Given a temperature in Celsius, return Fahrenheit va 3 lue. 4 * 5 * @param {number} celsius 6 * @return {number} 7 * @customfunction 8 */ 9 function CELSIUSTOFAHRENHEIT(celsius) { 10 if (typeof celsius !== 'number') { 11 throw TypeError('Celsius value must be a number'); 12 } 13 return ((celsius * 9) / 5) + 32; 14 } Function CELSIUSTOFAHRENHEIT takes a numeric value repre- senting degrees Celsius and returns the Fahrenheit equivalent. Be- fore performing the calculation, it first checks that the given value is
  • 43. Chapter 3: User-Defined Functions 32 numeric, if not, it throws a type error. Here is a screenshot showing some input values and the outputs after calling this function: Figure 3-4: Input and output for user-defined function CELSIUSTOFAHREN- HEIT and . See how the thrown error is reported as a comment in cells A5 to A8. Without the typeof check, the date value in cell A7 would be interpreted as a number of seconds and would return an unfeasibly large value. The outcome of evaluating the cell A6 is even more insidious because the blank is interpreted as zero and the function evaluates to 32. Indeed, 0 Celsius is equal to 32 Fahrenheit but this is highly misleading. Remove or comment out the typeof check and see the effect! The text value in cell A5 will throw an error regardless of the typeof check, which is to be expected. However, the default interpretation of dates as numbers and blank cells as zero is a serious trap for the unwary. The same problem occurs in Excel VBA and is more difficult to guard against. This example of a user-defined function is very simple but it highlights the need for rigorous checking of inputs. Verifying that arguments are within a valid range may also be required to avoid invalid return values. As an example, the formula to calculate the area of a circle is simple: Π * radius2. The following function does this but it also checks that the given argument is both
  • 44. Chapter 3: User-Defined Functions 33 numeric and not less than zero. Code Example 3.8 1 /** 2 * Given the radius, return the area of the circle. 3 * @param {number} radius 4 * @return {number} 5 * @customfunction 6 */ 7 function AREAOFCIRCLE (radius) { 8 if (typeof radius !== 'number' || radius < 0){ 9 throw Error('Radius must be a positive number'); 10 } 11 return Math.PI * (radius * radius); 12 } In example 3.8, the function expects a single numeric argument for the circle radius. However, since a negative radius makes no sense in this context, there is an additional check to ensure that the radius given is not negative. If either of these conditions fails, an error is thrown (|| is the or operator). In this example, both checks were performed togeter using the or operator. If greater granularity is required, the checks could be performed in two separate checks that would yield two different errors. This approach helps when functions are part of larger applications. 3.11 Date Functions Google Sheets provides a comprehensive set of date functions, see here¹⁴ for the full list. However, if the provided functions do not cover your requirements, you can write your own in GAS and ¹⁴https://support.google.com/docs/table/25273?hl=en&rd=2
  • 45. Chapter 3: User-Defined Functions 34 call them from your spreadsheet as user-defined functions. Some cautionary words: Dates and times can be quite complicated in any application or programming language where you have to allow for time zones, daylight saving time changes and leap years so rigorous testing of inputs and outputs is highly advidable. The examples given here also cover some important basic JavaScript concepts such as date manipulation, objects and methods and JavaScript arrays. The first example (3.9) takes a date as its sole argument and returns the day name (in English) for that date. Code Example 3.9 1 /** 2 * Given a date, return the name of the 3 * day for that date. 4 * 5 * @param {Date} date 6 * @return {String} 7 * @customfunction 8 */ 9 function DAYNAME(date) { 10 var dayNumberNameMap = { 11 0: 'Sunday', 12 1: 'Monday', 13 2: 'Tuesday', 14 3: 'Wednesday', 15 4: 'Thursday', 16 5: 'Friday', 17 6: 'Saturday'}, 18 dayName, 19 dayNumber; 20 if(! date.getDay ) { 21 throw TypeError(
  • 46. Chapter 3: User-Defined Functions 35 22 'TypeError: Argument is not of type "Date"!'); 23 } 24 dayNumber = date.getDay(); 25 dayName = dayNumberNameMap[dayNumber]; 26 return dayName; 27 } The most interesting points in the code example 3.9 are the use of the object named dayNumberNameMap, how the argument type is checked and how the Date object method getDay() is used. The variable dayNumberNameMap is a JavaScript object. Since objects are cornerstones of JavaScript programming, here is a short detour that describes them. At their simplest, JavaScript objects provide a mapping of keys to values. The values are called “properties” and they can be other objects, scalar values, arrays or functions. When object properties are functions, they are known as meth- ods. JavaScript objects are analogous to hashes or dictionaries in other languages. The very popular data interchange format called JavaScript Object Notation (JSON) is based on them. Excel VBA offers a Dictionary Object from the Microsoft Scripting Library¹⁵ that provides similar functionality but is much less flexible. The object in the example above maps index numbers to the names of the days of the week. Returning to the code example above, the date argument is expected to be of type Date and the mechanism used to test for it, that is the line if(! date.getDay ) {, merits some explanation. If the argument is a Date object, then it will implement a getDate() method. The test here is to see if the property exists, notice how the getDate() method is not called because there are no parentheses. If the argument does not have a getDate property, then an error is raised. This type of checking for methods on objects is common in client-side (browser) JavaScript where implementations from different vendors may or may not provide certain methods. If the argument passes the type check, then we are satisified that it is a ¹⁵https://support.microsoft.com/en-us/kb/187234/
  • 47. Chapter 3: User-Defined Functions 36 Date object so we can call the getDay() method on it. The getDay() method returns the week day as an integer starting with 0 (zero) for Sunday. Having the day number, we can use it as key for our object dayNumberNameMap to return the day name. To use the function DAYNAME as a user-defined function, copy the code into the Script Editor and call it from the spreadsheet like this where the return value of the built-in TODAY() function is given as an argument: 1 =DAYNAME(TODAY()) All the user-defined functions given so far return a scalar value but they can also return arrays where each array element is entered into its own cell. An example will help to illustrate this. In this example, we write a function that returns all dates that fall on a given day between two dates. Code Example 3.10 1 /** 2 * Add a given number of days to the given date 3 * and return the new date. 4 * 5 * @param {Date} date 6 * @param {number} days 7 * @return {Date} 8 */ 9 function addDays(date, days) { 10 // Taken from Stackoverflow: 11 // questions/563406/add-days-to-datetime 12 var result = new Date(date); 13 result.setDate(result.getDate() + days); 14 return result; 15 } 16 17 /**
  • 48. Chapter 3: User-Defined Functions 37 18 * Given a start date, an end date and a day name, 19 * return an array of all dates that fall (inclusive) 20 * between those two dates for the given day name. 21 * 22 * @param {Date} startDate 23 * @param {Date} endDate 24 * @param {String} dayName 25 * @return {Date[]} 26 * @customfunction 27 */ 28 function DATESOFDAY(startDate, endDate, dayName) { 29 var dayNameDates = [], 30 testDate = startDate, 31 testDayName; 32 while(testDate <= endDate) { 33 testDayName = DAYNAME(testDate); 34 if(testDayName.toLowerCase() === 35 dayName.toLowerCase()) { 36 dayNameDates.push(testDate); 37 } 38 testDate = addDays(testDate, 1); 39 } 40 return dayNameDates; 41 } The code in example 3.10 defines a user-defined function called DATESOFDAY() that calls two other GAS functions, addDays() and DAYNAME() to perform some of the computation. Function DAYNAME() was described in code example 3.9 above will be needed when you paste this code into the Script Editor. The function addDays() was copied from this location on Stackoverflow.¹⁶. I stated earlier that date manipulation can be complex and the discussion thread on this Stackoverflow entry certainly proves that. ¹⁶http://stackoverflow.com/questions/563406/add-days-to-datetime
  • 49. Chapter 3: User-Defined Functions 38 Before discussing the actual code in example 3.10 in detail, first note how a user-defined function can call other GAS functions to perform some of its tasks as can be seen in this example where two other functions are called and their return values are used by DATESOFDAY(). By off-loading much of its work, DATESOFDAY() remains small on manageable. Make Functions Small De-composing a programming task into multiple small functions makes each function easier to test, de-bug and re-use DATESOFDAY() takes two dates and a day name as argument. I have not added any checking of types or numbers of argument, these could be easily added using the techniques discussed ear- lier. The function declares two local variables, dayNameDates and testDate. It initialises testDate to startDate and then enters the while loop. Each round of the while loop gets the name of the day for the testDate using the DAYNAME function described in code example 3.9. The returned day name is then compared to the given argument day name (dayName) using a case-insensitive comparison by calling the string method toLowerCase() on both string operands. If they are equal, the date is added to the array using the Array push() method. This technique of building arrays in loops will be seen throughout the book. JavaScript arrays are extremely flexible and implement a range of very useful methods. Many of these methods will be encountered later in this book. After testing the day of the date, the test date is incremented by one day using the addDays() function. The condition testDate <= endDate is tested in the next round of the while loop and the loop finishes when the condition evaluates to false and the dayNameDates array is returned. When the function DATESOFDAY() is called as a user-defined
  • 50. Chapter 3: User-Defined Functions 39 function, it writes the entire array to a single column, see the screenshot below: Figure 3-5: Calling user-defined function that returns an array of values. 3.12 Text Functions Google Spreadsheets text manipulation functions can also be com- plemented and enhanced by writing user-defined functions. JavaScript, like most programming languages, refers to the text type as “string”. Strings in JavaScript are primitive types but they can be wrapped to behave like objects. The wrapping of a primitive so that it becomes an object is known as auto-boxing. Auto-boxing can also be applied to Boolean and Number primitive types and though I have never seen any use for it, with Boolean. The Number type has some useful methods like toFixed(). Since auto-boxing is transparent to the user/programmer, all that really matters is that strings can be treated as though they have methods that can be used to extract information from them and to generate new strings. To see all the String properties supported by GAS/JavaScript, paste the following code into the script editor and execute it. An alpha- betical list of string properties is sent to the logger. Code Example 3.11
  • 51. Chapter 3: User-Defined Functions 40 1 /** 2 * Print all string properties to the 3 * Script Editor Logger 4 * @return {undefined} 5 */ 6 function printStringMethods() { 7 var strMethods = 8 Object.getOwnPropertyNames( 9 String.prototype); 10 Logger.log('String has ' + 11 strMethods.length + 12 ' properties.'); 13 Logger.log(strMethods.sort().join('n')); 14 } The code above uses JavaScript’s very powerful introspection ca- pabilities to extract an array of all the property names defined for object String on what is known as its prototype. The prototype is a property that refers to an object where the String methods are defined in the prototype. Prototypes are quite an advanced topic but they are very important and provide the basis for inheritance in JavaScript. All JavaScript objects (that includes arrays and func- tions) have a prototype property. The logger output shows that there are 38 String properties. Most are methods but the important length property, for example, is not. Code example 3.11 also uses two important Array methods: sort() and join(). The sort() method does an alphabetical sort in this example and join() then makes a string of the array using the given argument (new line ‘n’ in this example) to separate the concatenated array elements. Notice how the method calls are “chained” one after the other. This is a common approach in JavaScript. As an exercise, you could try writing an equivalent function to print out all the array properties. Since the String object has so many methods, we can use these methods in user-defined functions. Here is a function that returns
  • 52. Chapter 3: User-Defined Functions 41 the argument string in reverse character order. Code Example 3.12 1 /** 2 * Given a string, return a new string 3 * with the characters in reverse order. 4 * 5 * @param {String} str 6 * @return {String} 7 * @customfunction 8 */ 9 function REVERSESTRING(str) { 10 var strReversed = '', 11 lastCharIndex = str.length - 1, 12 i; 13 for (i = lastCharIndex; i >= 0; i -= 1) { 14 strReversed += str[i]; 15 } 16 return strReversed; 17 } Reversing strings might not strike you as the most useful func- tionality unless of course you work with DNA or are interested in palindromes. To see a palindrome example, call the function with the word detartrated, yes, that word really exists. The example function uses a JavaScript for loop to extract the string characters in reverse order and appends them to a new string that is built within the loop. The newly built string is returned upon completion of the loop. If you declare the variable strReversed but do not assign it, something unexpected happens. As the variable is unassigned, it is undefined. If you concatenate a string to undefined you get another of those troublesome implicit JavaScript conversions that I warned about earlier where undefined becomes the string “undefined! Beware!
  • 53. Chapter 3: User-Defined Functions 42 Spreadsheets generally offer a large set of built-in text functions and Google Sheets augments these with regular expression functions. I have covered regular expressions in two blog entries (see part 1here¹⁷ and part 2 here¹⁸.) I will include a chapter on regular expression later in this book and will give some regular expression- based user-defined function examples there. 3.13 Using JavaScript Built-In Object Methods JavaScript provides a small number of built-in objects that provide additional functionality that can be used in user-defined functions. For example, the JavaScript Math object is available in GAS and provides some useful methods. Simulation of a die throw can be easily implemented using its methods: Code Example 3.13 1 /** 2 * Simulate a throw of a die 3 * by returning a number between 4 * and 6. 5 * 6 * @return {number} 7 * @customfunction 8 */ 9 function THROWDIE() { 10 return 1 + Math.floor(Math.random() * 6); 11 } ¹⁷http://www.javascript-spreadsheet-programming.com/2013/09/regular- expressions.html ¹⁸http://www.javascript-spreadsheet-programming.com/2014/09/regular-expressions- part-2.html
  • 54. Chapter 3: User-Defined Functions 43 Try out the function by calling =THROWDIE() from any spreadsheet cell. This function uses two methods defined in the JavaScript built-in Math object to simulate dice throwing. The Math round() method could also be used here but, as is very well described here¹⁹, it leads to biased results. This becomes apparent when the function is called hundreds of times. The important point to note is the need for testing and reading of documentation to avoid inadvertent errors and biases. 3.14 Using A Function Callback The object nature of JavaScript functions allows them to be both passed as arguments to other functions and to be returned by other functions. The following example provides an example of the power and flexibility of JavaScript. It also shows how easy it is to use a range of cells as an argument. The function concatenates an input range of cells using a delimiter argument. There is an in- built Google Spreadsheet function called JOIN that performs this task but the user-defined version below has one additional feature: It provides an option to enclose each individual element in single quotes. Here is the code: Code Example 3.14 ¹⁹http://www.the-art-of-web.com/javascript/random/#.UPU8tKHC-nY
  • 55. Random documents with unrelated content Scribd suggests to you:
  • 56. was recognized as the most convenient medium for official uses, and the language most generally known in these sections of society which had to administer justice.[19] In the second half of the thirteenth century Robert of Gloucester complained that there was no land "that holdeth not to its kindly speech save Englonde only," admitting at the same time, however, that ignorance of French was a serious disadvantage. An idea of the extent to which the language was current in England may be gathered from the fact that in 1301 Edward I. caused letters from the Pope to be translated into French so that they might be understood by the whole army,[20] and in the previous year the author of the Miroir des Justices wrote in French as being the language "le plus entendable de la comun people." French, indeed, appears to have been used among all classes, save the very poorest;[21] some of the French literature of the time was addressed more particularly to the middle classes.[22] Nevertheless, as the thirteenth century advanced, French began to hold its own with some difficulty. While it was in the unusual position of a vernacular gradually losing its power as such, there appeared the earliest extant treatise on the language. This, and those that followed it, were to some extent lessons in the vernacular; yet not entirely, as may be judged from the fact that they are set forth and explained in Latin, the language of all scholarship. The first work on the French language, dating from not later than the middle of the thirteenth century, is in the form of a short Latin treatise on French conjugations,[23] in which a comparison of the French with the Latin tenses is instituted.[24] As it appeared at a time when French was becoming the literary language of the law, and was being used freely in correspondence, it may have been intended mainly for the use of clerks. A treatise of considerably more importance composed towards the end of the century, appears to have had the same purpose. That he did not intend it exclusively for clerks, however, the author showed by adding rules for pronunciation, syntax and even morphology as well as for orthography. Like most of the early grammatical writings on the French language, this Orthographia Gallica is in Latin. The obscurity of many of its rules, however, called
  • 57. forth commentaries in French which appeared during the fourteenth century, and exceed the size of the original work. The Orthographia was a very popular work, as the number of manuscripts extant and the French commentary prove. The different copies vary considerably, and there is a striking increase in the number of rules given; from being about thirty in the earliest manuscript, they number about a hundred in the latest.[25] It opens with a rule that when the first or middle syllable of a French word contains a short e, i must be placed before the e, as in bien, rien, etc.—a curious, fumbling attempt to explain the development of Latin free short e before nasals and oral consonants into ie. On the other hand, continues the author, e acute need not be preceded by i, as tenez. It is not surprising that these early writers, in spite of much patient observation, should almost always have failed to grasp fundamental laws, and group a series of corresponding facts into the form of a general rule. We continually find rules drawn up for a few isolated examples, with no general application. The most striking feature in the treatment of French orthography in this work is the continual reference to Latin roots, and the clear statement of the principle that, wherever possible, the spelling of French words should be based on that of Latin. The Orthographia does not by any means limit its observations to spelling; there are also rules for pronunciation, a subject which in later times naturally held a very important place in French grammars written for the use of Englishmen, while orthography became one of the chief concerns of French grammarians. That orthography received so much attention at this early period in this country, is explained by the fact that these manuals were partly intended for "clerks," who would frequently have to write in French. As to the pronunciation, we find, amongst others, the familiar rule that when a French word ending in a consonant comes before another word beginning with a consonant, the first consonant is not pronounced. An s occurring after a vowel and before an m, writes the author, in another rule, is not pronounced, as in mandasmes, and l coming
  • 58. after a, e, or o, and followed by a consonant is pronounced like u, as in m'almi, loialment, and the like. A list of synonyms[26] is also given, which throws some light on the English pronunciation of French at this period, and there are also a few hints for the translation of both Latin and English into French. Nor are syntax and morphology neglected; rules concerning these are scattered among those on orthography and pronunciation, with the lack of orderly arrangement characteristic of the whole work. Thus we are told to use me in the accusative case, and moy in all other cases; that we should form the plural of verbs ending in t in the singular by adding z, as il amet, il list become vous amez, vous lisez; that when we ask any one for something, we may say vous pri without je, but that, when we do this, we should write pri with a y, as pry, and so on. The claim of the Orthographia Gallica to be the first extant work on French orthography, has been disputed by another treatise, also written in Latin, and known as the Tractatus Orthographiae. More methodically arranged than the Orthographia, this work deals more particularly with pronunciation and orthography.[27] It opens with a short introduction announcing that here are the means for the youth of the time to make their way in the world speedily and learn French pronunciation and orthography. Each letter of the alphabet is first treated in turn,[28] and then come a few more general observations. Like the author of the Orthographia, the writer of the Tractatus would have the spelling of French words based on that of Latin whenever possible. He claims that his own French is "secundum dulce Gallicum" and "secundum usum et modum modernorum tam partibus transmarinis quam cismarinis." Though he apparently places the French of England and the French of France on the same footing, it is noteworthy that he carefully distinguishes between the two. The Tractatus Orthographiae bears a striking resemblance to another work of like nature, which is better known—the Tractatus Orthographiae of Canon M. T. Coyfurelly, doctor in Law of
  • 59. Orleans[29]—and for some time it was thought to be merely a rehandling of Coyfurelly's treatise which did not appear till somewhere about the end of the fourteenth century, if not later. But Coyfurelly admits that his work was based on the labours of one 'T. H. Parisii Studentis,' and there appears, on examination,[30] to be no doubt as to the priority of the anonymous Tractatus described above, which, on the contrary, is evidently the treatise rehandled by Coyfurelly, and the work of 'T. H. Student of Paris.' Besides being the original which Coyfurelly recast in his Tractatus, it also appears that T. H. may reasonably dispute with the author of the Orthographia Gallica, the honour of being the first in the field. His work shows no advance on the rules given for pronunciation in the Orthographia, while the orthography is of a decidedly older stamp. At about the same time as these two treatises on orthography, probably a few years earlier, there was composed a work of similar purpose but very different character. It is of particular interest, and shows that, towards the end of the thirteenth century, French was beginning to be treated as a foreign language; the French is accompanied by a partial English gloss, and the author states that "touz dis troverez-vous primes le Frauncois et pus le Engleys suaunt." The author, Gautier or Walter de Bibbesworth,[31] was an Englishman, and appears to have mixed with the best society of the day. He was a friend of the celebrated statesman of the reign of Edward I., Henry de Lacy, Earl of Lincoln. The only work by which his name is known to-day, in addition to the treatise in question, is a short piece of Anglo-Norman verse,[32] written on the occasion of the expedition of Edward I. to the Holy Land in 1270, shortly before he came to the throne. We gather from letters of protection granted him in that year that Bibbesworth himself took part in this venture. In this poem he is pictured discussing the Crusade with Lacy, and trying to persuade his friend to take part in it. The name of Bibbesworth also occurs several times[33] in official documents of no special interest, and as late as 1302 a writ of Privy Seal was addressed to the Chancellor suing for a pardon under the Great Seal to W. de Bibbesworth, in consideration of his good services rendered
  • 60. in Scotland, for a breach of the park of Robert de Seales at Ravenhall, and of the king's prison at Colchester.[34] Bibbesworth, however, interests us less as a crusader or a disturber of public order, than as the author of a treatise for teaching the French language, entitled Le Treytyz qe mounsire Gauter de Bibelesworthe fist a ma dame Dyonisie de Mounchensy[35] pur aprise de langwage. The large number of manuscripts still in existence[36] suggest that it was a popular text-book among the children of the higher classes of society. The treatise reproduces, as might be expected, the chief characteristics of the vocabularies for teaching Latin. In addition to giving a collection of words and phrases arranged in the form of a narrative, it also incidentally aims at imparting some slight grammatical information. Its contents are of a very practical character, and deal exclusively with the occurrences and occupations of daily life. Beginning with the new-born child, it tells in French verses how it is to be nursed and fed. Rime was no doubt introduced to aid the memory, as the pupil would, in all probability, have to learn the whole by heart. The French is accompanied by a partial interlinear English gloss, giving the equivalent of the more difficult French words. This may, perhaps, be taken as an indication of the extent to which French was regarded as a foreign language.[37] After describing the life of the child during its earliest infancy, Bibbesworth goes on to tell how it is to be taught French as soon as it can speak, "that it may be better learned in speach and held up to scorn by none": Quaunt le enfes ad tel age Ke il set entendre langage, Primes en Fraunceys ly devez dire Coment soun cors deyt descrivere, Pur le ordre aver de moun et ma, Toun et ta, soun et sa, better lered
  • 61. Ke en parlole seyt meut apris scorned E de nul autre escharnys. In accordance with this programme the parts of the human body, which almost invariably forms the central theme in this type of manual, are enumerated. Special care is taken to distinguish the genders and cases, to teach the children "Kaunt deivunt dire moun et ma, soun et sa, le et la, moy et jo . . .," and to explain how the meaning of words of similar sound often depends on their gender: lippe and an hare Vous avet la levere et le levere, a pound a book Et la livere et le livere. La levere si enclost les dens; Le levere en boys se tent dedens; La livere sert en marchaundye; Le livere nous aprent clergye. Throughout Bibbesworth seizes every opportunity to point out distinctions of gender of this kind, regardless, it appears, of the difference between the definite and indefinite articles. When the pupil can describe his body, the teacher proceeds to give him an account of "all that concerns it both inside and out" ("kaunt ke il apent dedens et deores"), that is of its clothing and food: Vestet vos draps mes chers enfauns, Chaucez vos brays, soulers, e gauns; Mettet le chaperoun, covrez le chef, etc. —a passage which illustrates the practical nature of the treatise, Bibbesworth's aim being to teach children to know the properties of the things they see ("les propretez des choses ke veyunt"). When the child is clothed, Bibbesworth next feeds him, giving a full account of the meals and the food which is provided, and, by
  • 62. way of variety, at the end of the dinner, he teaches his pupil the names given to groups of different animals, and of the verbs used to describe their various cries. ("Homme parle, cheval hennist," etc.). By this time the child is ready to observe Nature, and to learn the terms of husbandry,[38] and the processes by which his food is produced. From the fields he passes to the woods and the river, where he learns to hunt and to fish, subjects which naturally lead to the introduction of the French names of the seasons, and of the beasts and birds that are supposed to present themselves to his view. During the whole of this long category the verse form is maintained, and the intention of avoiding a vocabulary pure and simple is manifest. How superior this method was to the more modern lists of words separated from the context is also evident. Besides giving a description of all the objects with which the child comes in contact, and of all the actions he has to perform, as well as examples for the distinctions of genders and of moy and jo— difficulties for which he makes no attempts to draw up rules— Bibbesworth claims for his work that it provides gentlemen with adequate instruction for conversational purposes ("tot le ordre en parler e respoundre ke checun gentyshomme covent saver"). And as he did not wish to neglect any of the items of daily life, he finally gives a description of the building of a house and various domestic arrangements, ending with a description of an old English feast with its familiar dish, the boar's head: Au primer fust apporté a boris heued La teste de un sengler tot armé, the snout wit baneres of flurs E au groyn le colere en banere; E pus veneysoun, ou la fourmenté; Assez par my la mesoun tahen of gres tyme De treste du fermeyson.
  • 63. Pus avyent diversetez en rost, Eit checun autre de cost, Cranes, pokokes, swannes Grues, pounes, e cygnes, Wilde ges, gryses (porceaus), hennes, Owes, rosées, porceus, gelyns; Au tercez cours avient conyns en gravé, Et viaunde de Cypre enfundré, De maces, e quibibes, e clous de orré, Vyn blanc e vermayl a graunt plenté. wodekok Pus avoyunt fesauns, assez, et perdriz, Feldefares larkes Grives, alowes, e pluviers ben rostez; E braoun, e crispes, e fritune; Ke soucre roset poudra la temprune. Apres manger avyunt a graunt plenté Blaunche poudre, ou la grosse dragé, Et d'autre nobleie a fusoun, Ensi vous fynys ceo sermoun; Kar de fraunceis i ad assez, De meynte manere dyversetez, Dount le vous fynys, seynurs, ataunt A filz Dieu vous comaund. Ici finest la doctrine monsire Gauter De Byblesworde. As time went on a conscious effort was made to retain the use of the French language in England. Higden, writing at about the middle of the fourteenth century,[39] informs us that English was then neglected for two reasons: "One is bycause that children than gon to schole lerne to speke first Englysshe and then ben compelled constrewe ther lessons in Frenssh"; "Also gentilmens children ben lerned and taught from theyr yougthe to speke frenssh.[40] And uplandish men will counterfete and likene them self to gentilmen and arn besy to speke frensshe for to be more sette by. Wherefor it
  • 64. is sayd by a common proverbe Jack wold be a gentilmen if he coude speke frensshe." At the University of Oxford, likewise, the Grammar masters were enjoined to teach the boys to construe in English and in French, "so that the latter language be not forgotten."[41] The same university gave some slight encouragement to the study of French. There were special teachers who, although not enjoying the privileges of those lecturing in the usual academic subjects, were none the less recognised by the University. They had to observe the Statutes, and to promise not to give their lessons at times which would interfere with the ordinary lectures in arts. The French teachers were under the superintendence of the masters of grammar, and had to pay thirteen shillings a year to the Masters in Arts to compensate them for any disadvantage they might suffer from any loss of pupils; if there was only one teacher of French he had to pay the whole amount himself. As for those learning "to write, to compose, and speak French," they had to attend lectures in rhetoric and grammar —the courses most akin to their studies[42]—and to contribute to the maintenance of the lecturers in these subjects, there being no ordinary lectures in French. In the meantime, more treatises for teaching French appeared; Bibbesworth's book soon found imitators, and early in the new century an anonymous author, clearly an Englishman, made free use of Bibbesworth in a treatise called The Nominale sive Verbale in Gallicis cum expositione ejusdem in Anglicis.[43] This anonymous writer[44] however, thought it necessary to make the interlinear English gloss much fuller than Bibbesworth had done, which shows that French had become more of a foreign language in the interval between the two works. He also placed the English rendering after the French, instead of above it. The later work differs further from the earlier in the order of the subject headings, as well as by the introduction of a few new topics. Enumerating the parts of the body, [45] as Bibbesworth had done, the author proceeds to make his most
  • 65. considerable addition to the subjects introduced by Bibbesworth in describing "la noyse et des faitz que homme naturalment fait": Homme parle et espire: Man spekyth & vndyth. Femme teinge et suspire: Woman pantyth & syketh. Homme bale et babeie: Man dravelith & wlaffyth. Femme bale et bleseie: Woman galpyth & wlispyth. He then describes all the daily actions and occupations of men: Homme va a la herce: Man goth at the harewe. Femme bercelet berce: Woman childe in cradel rokkith.... Enfant sa lessone reherce: His lessone recordeth, and so on for about 350 lines. Other additions are of little importance, and, for the rest, the author treats subjects first introduced by Bibbesworth, though the wording often differs to a certain extent.[46] When, towards the end of the thirteenth century, French began to be used in correspondence, need for instruction in French epistolary art arose; and early in the fourteenth century guides to letter-writing in French, in the form of epistolaries or collections of model letters, were produced.[47] The letters themselves are given in French, but the accompanying rules and instructions for composing them are in Latin. French and Latin have changed rôles; in earlier times Latin had been explained to school children by means of French. Forms for addressing members of the different grades of society are supplied, from epistles to the king and high state and ecclesiastical dignitaries down to commercial letters for merchants, and familiar
  • 66. ones for private individuals. Women, too, were not forgotten; we find similar examples covering the same range—from the queen and the ladies of the nobility to her more humble subjects. Each letter is almost invariably followed by its answer, likewise in French. Some contain interesting references to the great men or events of the day, but those of a more private nature possess a greater attraction, and throw light on the family life of the age. A letter from a mother to her son at school may be quoted:[48] Salut avesque ma beniçon, tres chier filz. Sachiez que je desire grandement de savoir bons nouelles de vous et de vostre estat: car vostre pere et moy estions a la faisance de ces lettres en bon poynt le Dieu merci. Et sachiez que je vous envoie par le portour de ces lettres demy marc pur diverses necessaires que vous en avez a faire sans escient de vostre pere. Et vous pri cherement, beau tres doulz filz, que vous laissez tous mals et folyes et ne hantez mye mauvaise compagnie, car si vous le faitez il vous fera grant damage, avant que vous l'aperceiverez. Et je vous aiderai selon mon pooir oultre ce que vostre pere vous donnra. Dieus vous doint sa beniçon, car je vous donne la mienne. . . . From about the middle of the fourteenth century a feeling of discontent with the prerogative of the French language in England becomes prominent. The loss of the greater part of the French possessions, and the continued state of hostilities with France during the reign of Edward III. brought home forcibly to the English mind the fact that the French were a distinct nation, and French a foreign tongue. This tardy recovery is sufficient proof of the strong resistance which had to be overcome. Chaucer is the greatest representative of the new movement. "Let Frenchmen endite their quaint terms in French," he exclaims, "for it is kindly to their mouths, but let us show our fantaisies in suche words as we learned from our dames' tongues." His contemporary, Gower, was less quick to discern the signs of the times. Of the four volumes of his works, two are in Latin, one in French, and one in English; but the order in which he uses these languages is instructive—first French, then Latin, and lastly English. Some writers made a compromise by employing a mixture of French and English.[49] French, however, continued to
  • 67. hold an important place in prose writings until the middle of the fifteenth century; but such works are of little literary value. The reign of French as the literary language of England, as Chaucer had been quick to discern, was approaching its end. The same period is marked by a growing disrespect for Anglo- French as compared with the French of France. The French of England, cut off from the living source, had developed apart, and often with more rapidity than the other French dialects on the Continent. What is more, the language brought by the invaders was not a pure form of the Norman dialect; men from various parts of France had joined in William's expedition. The invaders, always called 'French' by their contemporaries, brought in a strong Picard element; and in the twelfth century there was a similar Angevin influence. Moreover, during Norman and Angevin times, craftsmen and others immigrated to England, each bringing with him the dialectal peculiarities of his own province.[50] Thus no regular development of Anglo-French was possible, and it can hardly be regarded as an ordinary dialect, notwithstanding its literary importance.[51] This disparity in the quality of Anglo-French is illustrated in a remarkable way by the literature of the period. Those who had received special educational advantages, or had travelled on the Continent, spoke and wrote French correctly; others used forms which contrasted pitiably with continental French. Moreover, the fourteenth century saw the triumph of the Île de France dialect in France; the other dialects ceased, as a rule, to be used in literature,[52] and this change was not without effect on Anglo- French, which shared their degradation. Chaucer lets us know the poor opinion he had of the French of England; his Prioress speaks French "full fayre and fetisly," but After the scole of Stratford atte Bowe, For French of Paris was to her unknowe. William Langland admits that he knew "no frenche in feith, but of the ferthest ende of Norfolke."[53] As early as the thirteenth century
  • 68. English writers had felt bound to apologize as Englishmen for their French. Nor were their excuses superfluous in many cases; William of Wadington, the author of the Manuel des Pechiez, for example, wrote:[54] De le françois ne del rimer Ne me doit nuls hom blamer, Car en Engleterre fu né Et nurri lenz et ordiné. Such apologies became all the more necessary as time went on. Even Gower, whose French was comparatively pure,[55] owing no doubt to travel in France in early life, deemed it advisable to explain that he wrote in French for "tout le monde en general," and to ask pardon if he has not "de François la faconde": Jeo suis Englois si quier par tiele voie Estre excusé. At about the same time the anonymous author of the Testament of Love finds fault with the English for their persistence in writing in bad French, "of which speech the Frenchmen have as good a fantasy as we have in hearing of Frenchmen's English."[56] The notoriety of the French of Englishmen reached France. Indeed this was a time when the English were more generally known in France than they were to be for several hundreds of years afterwards—until the eighteenth century. Englishmen filled positions in their possessions in France, and during the long wars between the two countries in the reign of Edward III., many of the English nobility resided in that country with their families. Montaigne refers to traces of the English in Guyenne, which still remained in the sixteenth century: "Il est une nation," he writes in one of his Essays, "a laquelle ceux de mon quartier ont eu autrefois si privée accointance qu'il reste encore en ma maison aucune trace de leur ancien cousinage."[57] The opinions formed by the French of the English were naturally anything but flattering. We find them
  • 69. expressed in songs of the time.[58] But the recriminations were mutual, and the English had already hit upon the epithet which for centuries they applied to Frenchmen, and most other foreigners indiscriminately: Franche dogue dit un Anglois. Vous ne faites que boire vin, Si faisons bien dist le François, Mais vous buvez le lunnequin. (bière.)[59] Even in the Roman de Renart we come across traces of familiarity with English ways, and also of the English language.[60] It is not surprising, then, that Anglo-French was a subject of remark in France, especially when we remember that already in the thirteenth century the provincial accents of the different parts of France herself had been the object of some considerable amount of raillery.[61] The English, says Froissart, a good judge, for he spent many years in England, "disoient bien que le françois que ils avoient apris chies eulx d'enfance n'estoit pas de telle nature et condition que celluy de France estoit."[62] And this 'condition' was soon recognized as a plentiful store for facetious remarks and parodies of all kinds. In the Roman de Jehan et Blonde, the young Frenchman's rival, the Duke of Gloucester, is made to appear ridiculous by speaking bad French; and one of the tricks played by Renart on Ysengrin, in the Roman de Renart, is to pretend he is an Englishman:[63] Ez vos Renart qui le salue: "Godehelpe," fait il, "bel Sire! Non saver point ton reson dire." And Ysengrin answers: Et dex saut vos, bau dous amis! Dont estes vos? de quel pais? Vous n'estes mie nés de France,
  • 70. Ne de la nostre connoissance. A fabliau of the fourteenth century[64] pictures the dilemma of two Englishmen trying to make their French understood in France; one of them is ill and would have some lamb: Si tu avez un anel cras Mi porra bien mengier ce croi. His friend sets out to try to get the 'anel' or 'lamb'; but no one understands him, and he becomes the laughing-stock of the villagers. At last some one gives him a 'small donkey' instead of the desired 'agnel,' and out of this he makes a dish for the invalid who finds the bones rather large. In the face of a reputation such as this it is no wonder that the English found additional encouragement to abandon the foreign language and cultivate their own tongue. English was also beginning to make its way into official documents.[65] In 1362 the King's Speech at the opening of Parliament was pronounced in English, and in the following year it was directed that all pleas in the courts of justice should be pleaded and judged in English, because French was "trope desconue en ledit realme." Despite that, the act was very tardily obeyed, and English progressed but slowly, French continuing to be written long after it ceased to be spoken in the Law Courts. There were a few public documents issued in English at the end of the century, but the Acts and Records of Parliament continued to be written in French for many years subsequently. English first made its way into the operative parts of the Statutes, and till 1503 the formal parts were still written in French and Latin. Protests were made to Henry VIII. against the continued use of French, "as thereby ys testyfied our subjectyon to the Normannys"; yet it was not before the eighteenth century that English was exclusively used in the Law Courts, and for many years French, in its corrupt form, remained the literary language of the English law. Till the seventeenth century works on jurisprudence and reports on cases were mainly written in French. Les Cases de Gray's Inn shows French in accounts of discussions on
  • 71. difficult legal cases as late as 1680.[66] Sir John Fortescue (1394? -1476), Lord Chief Justice of the King's Bench, in his De Laudibus Legum Angliae, suggests that this Law French is more correct at bottom than ordinary spoken French, which, he contends, is much "altered by common use, whereas Law French is more often writ than spoken." In later times no such illusions prevailed. Swift thus estimates the value of the three languages of the English Law:[67] Then from the bar harangues the bench, In English vile, and viler French, And Latin vilest of the three. At about the same time as Swift wrote, the 'frenchified' Lady, then in fashion, who prided herself on her knowledge of the "language à la mode" is described as being able to "keep the field against a whole army of Lawyers, and that in their own language, French gibberish." [68] And long after French ceased to be used in the Law many law terms and legal and official phrases remained, and are still in use to- day.[69] Anglo-French also lingered in some of the religious houses after it had fallen into discredit elsewhere, and continued to do so in some cases till the time of their dissolution. The rules and accounts of the nunneries were more often in French than not.[70] And John ap Rhys, visitor of monasteries in the reign of Henry VIII., wrote to Cromwell regarding the monastery of Laycock in Wiltshire, that he had observed one thing "worthy th'advertisement; the ladies have their Rule, th'institutes of their Religion and the ceremonies of the same written in the Frenche tongue, which they understand well and are very perfyt in the same, albeit that it varieth from vulgar Frenche that is now used, and is moche like the Frenche that the common Lawe is written in."[71] During this same period English began to be used occasionally in correspondence; but here again its progress was slow. Some idea of the extent to which French was utilized for that purpose may be gathered from the fact that three extant letters of William de Wykeham, addressed to Englishmen, are all in that tongue. Not till
  • 72. the second and third decades of the fifteenth century were English and French employed in correspondence to an almost equal extent, and during the following years, especially in the reign of Henry VI., English gradually became predominant.[72] French remained in use longer in correspondence of a public and official nature, but became more and more restricted to foreign diplomacy. Towards the middle of the fourteenth century, at the beginning of the long wars with France, French lost ground in England in yet another direction. Edward III. is said to have found it necessary to proclaim that all lords, barons, knights, burgesses, should see that their children learn French for political and military reasons;[73] and when Trevisa translated Higden's Polychronicon, he wrote in correction of the earlier chronicler's description of the teaching of French in the grammar schools of England:[74] "This maner was moche used before the grete deth (1349). But syth it is somdele chaunged. Now (i.e. 1387) they leave all Frensch in scholes, and use all construction in Englisch. Wherin they have advantage on way that they lerne the soner ther gramer. And in another disadvantage. For nowe they lerne no Frenssh ne can none, whiche is hurte for them that shall passe the see," and thus children of the grammar schools know "no more French than knows their lefte heele." Thus the custom of translating Latin into French passed out of use early in the second half of the fourteenth century. No doubt there had been signs of the approaching change in the preceding period, and it is of interest here to notice that while Neckham's Latin vocabulary, which dates from the second half of the twelfth century, is glossed in French alone, that of Garlande, which belongs approximately to the third decade of the following century, is accompanied by translations in both French and English. In the universities, however, where French had been slower in gaining a foothold, it remained longer; in the fifteenth century teachers of French were still allowed to lecture there as they had done previously, but it is to be noticed that in all the colleges founded after the Black Death (1349), from which the change in the grammar
  • 73. schools is dated, the regulations encouraging the speaking of French in Hall are absent. The change appears also to have affected the higher classes, who did not usually frequent the grammar schools and universities, but depended on more private methods of instruction. Trevisa here again adds a correction to the earlier chronicle, and informs us that "gentylmen haveth now myche lefte for to teach their children Frensch." We thus witness the gradual disappearance of the effects of the Norman Conquest in the history of the use of the French language in England. The Conquest had made Norman-French the language of the Court, and to some extent, of the Church; it had brought with it a French literature which nearly smothered the national literature and replaced it temporarily; it had led to the system of translating Latin into French as well as into English in the schools. In the later fourteenth century French was no longer the chief language of the Court, and the king spoke English and was addressed in the same tongue. In the Church the employment of French had been restricted and transitory, though, as has been mentioned, it lingered in some of the monasteries until the sixteenth century; yet Latin never found in it a serious rival in this sphere, and the ecclesiastical department of the law never followed the civil in the adoption of the use of French. How French lost ground in the other spheres has already been traced: in all these cases its employment may be regarded as a direct result of the Conquest. This great event had also indirect results. French became the official language of England, and the favourite medium of correspondence in the thirteenth century, when the fusion between the two races was complete. But it is highly improbable that French would have spread in these directions if the Conquest had not in the first place made French the vernacular of a considerable portion of Englishmen, and that the most influential. With its use in official documents and in correspondence, may be classed the slight encouragement French received at Oxford. In all these spheres it
  • 74. remained longer than it had done where its status had been a more direct result of the Conquest. Meanwhile the desire to cultivate and imitate the French of France had been growing stronger and stronger; and when, towards the end of the fourteenth century, the older influences were getting feebler, and in some cases had passed away, the influence of the continental French, especially the French of Paris, now supreme over the other dialects, became more and more marked. And it is this language which henceforth Englishmen strove to learn, gradually relinquishing the corrupt idiom with which for so long their name had been associated. FOOTNOTES: [1] This was the opinion of Ames: "This seems to be the first grammar of the French language in our own country, if not in Europe." Dibdin, Herbert Ames's Typographical Antiquities, 1819, iii. p. 365. [2] The grammar of Jacques Sylvius or Dubois appeared in 1531, a year after Palsgrave's. No attempt at a theoretical treatment of the French language appeared in France in the Middle Ages. There are, however, two Provençal ones extant. (F. Brunot, "Le Français à l'étranger," in L. Petit de Julleville's Histoire de la langue et de la littérature française, ii. p. 528.) [3] One of the chief effects of the Conquest in the schools is said to have been the substitution of Norman for English schoolmasters (Leach, Schools of Mediaeval England, 1915, p. 103). [4] The majority of early Latin vocabularies extant, however, are accompanied by English translations (cp. T. Wright, Volume of Vocabularies, 2 vols., 1857), as was also the comparatively well-known Promptorium Parvulorum (c. 1440), Camden Soc., 1865. [5] The text is given in L. E. Menger's Anglo-Norman Dialect, Columbia University Press, 1904, p. 14. The psalms, together with Cato, Ovid, or possibly Virgil, formed the usual reading material in the Grammar Schools. Cp. Rashdall, Universities of Europe in the Middle Ages, Oxford, 1895, ii. p. 603.
  • 75. [6] Adam du Petit Pont (d. 1150) wrote an epistle in Latin, many words of which were glossed in French. But there is no evidence that it was used in England. It was published by E. Scheler in his Trois traités de lexicographie latine du 12e et 13e siècles, Leipzig, 1867. [7] Ed. T. Wright, Volume of Vocabularies, i. 96, and Scheler, op. cit. Both editions are deemed unsatisfactory by Paul Meyer (Romania, xxxvi. 482). [8] It has been published five times: (1) At Caen by Vincent Correr in 1508 (Romania, ut supra); (2) H. Géraud, in Documents inédits sur l'histoire de France: "Paris sous Philippe le Bel d'après les documents originaux," 1837; (3) Kervyn de Lettenhove, 1851; (4) T. Wright, Volume of Vocabularies, i. pp. 120 sqq.; (5) Scheler, Trois traités de lexicographie latine. [9] Wright, op. cit. pp. 139-141. [10] Statutes of the Colleges of Oxford, 3 vols., Oxford and London, 1853; A. Clark, Colleges of Oxford, 1891, p. 140; H. C. Maxwell Lyte, History of the University of Oxford, 1880, pp. 140-151. [11] Documents relating to the Universities and Colleges of Cambridge, 1852, ii. p. 33; J. Bass Mullinger, The University of Cambridge, 1873; G. Peacock, Observations on the Statutes of the University of Cambridge, 1841, p. 4. [12] J. Heywood, Early Cambridge University and College Statutes, 1885, ii. p. 182. [13] C. H. Cooper, Annals of Cambridge, Cambridge, 1852, i. p. 40. [14] Rashdall, op. cit. ii. p. 519 n. [15] Rashdall, op. cit. i. pp. 319 et seq. Later the English nation was known as the German; it included all students from the north and east of Europe. On the English in the University of Paris see Ch. Thurot, De l'organisation de l'enseignement dans l'Université de Paris, Paris, 1850; and J. E. Sandys, "English Scholars of Paris, and Franciscans of Oxford," in The Cambridge History of English Literature, i., 1908, chap. x. pp. 183 et seq. [16] Quoted, E. J. B. Rathery, Les Relations sociales et intellectuelles entre la France et l'Angleterre, Paris, 1856, p. 11. [17] A writer of about 1180 says it was impossible to tell who were Normans and who English ("Dialogus de Scaccario": Stubbs, Select
  • 76. Welcome to our website – the perfect destination for book lovers and knowledge seekers. We believe that every book holds a new world, offering opportunities for learning, discovery, and personal growth. That’s why we are dedicated to bringing you a diverse collection of books, ranging from classic literature and specialized publications to self-development guides and children's books. More than just a book-buying platform, we strive to be a bridge connecting you with timeless cultural and intellectual values. With an elegant, user-friendly interface and a smart search system, you can quickly find the books that best suit your interests. Additionally, our special promotions and home delivery services help you save time and fully enjoy the joy of reading. Join us on a journey of knowledge exploration, passion nurturing, and personal growth every day! ebookbell.com