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 Michael Maguire
Information Texts_Infographic on Forgetting Curve.pptxTata 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
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
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
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