google spgoogle spreadsheet programming

Upload: mcmisst

Post on 01-Jun-2018

227 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 Google Spgoogle spreadsheet programming

    1/95

  • 8/9/2019 Google Spgoogle spreadsheet programming

    2/95

    Google SpreadsheetProgrammingUse JavaScript To Build SpreadsheetApplications In The Cloud

    Michael MaguireThis book is for sale athttp://leanpub.com/googlespreadsheetprogramming

    This version was published on 2013-10-03

    This is a Leanpub book. Leanpub empowers authors andpublishers with the Lean Publishing process. LeanPublishing is the act of publishing an in-progress ebookusing lightweight tools and many iterations to get readerfeedback, pivot until you have the right book and build

    traction once you do.

    ©2013 Michael Maguire

    http://leanpub.com/manifestohttp://leanpub.com/manifestohttp://leanpub.com/http://leanpub.com/googlespreadsheetprogramming

  • 8/9/2019 Google Spgoogle spreadsheet programming

    3/95

    Tweet This Book!Please help Michael Maguire by spreading the word aboutthis book on Twitter !

    The suggested hashtag for this book is#googlespreadsheetprogramming .

    Find out what other people are saying about the book byclicking on this link to search for this hashtag on Twitter:

    https://twitter.com/search/#googlespreadsheetprogramming

    https://twitter.com/search/#googlespreadsheetprogramminghttps://twitter.com/search/#googlespreadsheetprogramminghttps://twitter.com/search/#googlespreadsheetprogramminghttp://twitter.com/

  • 8/9/2019 Google Spgoogle spreadsheet programming

    4/95

    Contents

    Chapter 1: Introduction . . . . . . . . . . . . . . . 11.1 What Is Google Apps Scripting? . . . . . . . 11.2 JavaScript or Google Apps Script? . . . . . . 21.3 Summary Of Topics Covered . . . . . . . . . 31.4 What Is Needed To Use This Book . . . . . . 4

    1.5 Intended Readership . . . . . . . . . . . . . 41.6 Note On Code and Code Examples . . . . . . 51.7 Google Spreadsheet Limitations . . . . . . . 51.8 How To Use This Book . . . . . . . . . . . . 61.9 Structure Of This Book . . . . . . . . . . . . 7

    Chapter 2: Getting Started . . . . . . . . . . . . . 92.1 Introduction . . . . . . . . . . . . . . . . . . 92.2 Google Apps Script Examples . . . . . . . . 92.2 Executing Code – One Function At A Time . 122.3 Summary . . . . . . . . . . . . . . . . . . . 14

    Chapter 3: User-Defined Functions . . . . . . . . 163.1 Introduction . . . . . . . . . . . . . . . . . . 163.2 Built-in Versus User-Defined Functions . . . 17

  • 8/9/2019 Google Spgoogle spreadsheet programming

    5/95

    CONTENTS

    3.3 Why Write User-Defined Functions . . . . . 183.4 What User-Defined Function Cannot Do . . 183.5 Using User-Defined Functions . . . . . . . . 223.6 Introducing JavaScript Functions . . . . . . . 223.7 User-Defined Functions Versus JavaScript Func-

    tions . . . . . . . . . . . . . . . . . . . . . 273.8 Checking Input And Throwing Errors . . . . 273.9 Encapsulating A Complex Calculation . . . . 283.10 Numeric Calculations . . . . . . . . . . . . 303.11 Date Functions . . . . . . . . . . . . . . . . 353.12 Text Functions . . . . . . . . . . . . . . . . 383.13 Using JavaScript Library Methods . . . . . 413.14 Using A Function Callback . . . . . . . . . 433.15 Extracting Useful Information About The

    Spreadsheet . . . . . . . . . . . . . . . . . 453.16 Using Google Services . . . . . . . . . . . . 473.17 Summary . . . . . . . . . . . . . . . . . . . 51

    Appendix A: Excel VBA And Google Apps ScriptComparison . . . . . . . . . . . . . . . . . . . 53Introduction . . . . . . . . . . . . . . . . . . . . 53Spreadsheets and Sheets . . . . . . . . . . . . . 55

    Ranges . . . . . . . . . . . . . . . . . . . . . . . 67

  • 8/9/2019 Google Spgoogle spreadsheet programming

    6/95

    Chapter 1: Introduction

    1.1 What Is Google Apps Scripting?

    Google Spreadsheets is one of the core components of Google cloud applications and is available to anyone witha Gmail account. It offers a comprehensive set of standardspreadsheet features via built-in functions. The spreadsheetfiles themselves are stored remotely, are accessible fromweb browsers, and can be shared with others in read-onlyor read-edit modes making them ideal collaborative tools.

    The Google Spreadsheets application also hosts a program-ming language called Google Apps Script (GAS) that isexecuted, not in the browser but remotely on the Googlecloud. Google define Google Apps Script as follows:

    “Google Apps Script is a JavaScript cloud scripting lan- guage that provides easy ways to automate tasks across Google products and third party services.”

    Google Apps Script can be used to:

    • Write user-defined functions forGoogle Spreadsheets.• Write simple “macro” type applications.• Develop spreadsheet-based applications.• Integrate other Google products and services.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    7/95

    Chapter 1: Introduction 2

    • Develop Graphical User Interfaces (GUIs) that can berun as web applications.

    • Interact with cloud-based relational databases viaGoogle JDBC Services.

    In summary, Google Apps Script provides the ability ex-tend and integrate Google services to deliver cloud-based

    software solutions.

    1.2 JavaScript or Google AppsScript?

    The emphasis here is on using Google Apps Script to

    enhance and control Google Spreadsheets. Other Googleservices are discussed in the context of how they can beused with Google Spreadsheets. Since Google Apps Scriptis JavaScript (Google describe it as a sub-set of JavaScript1.8), there will inevitably be discussion of JavaScript as aprogramming language. There is therefore some discussionof JavaScript topics as they relate to the code examples

    given.Regarding terminology, when discussing a general JavaScriptfeature, the code may be referred to as “JavaScript” butwhen dealing with a Google App specific example, it maybe referred to as “Google Apps Script”. The meaning of whichever term is used should be clear from the context.For example, the Spreadsheet object is central to Google

  • 8/9/2019 Google Spgoogle spreadsheet programming

    8/95

    Chapter 1: Introduction 3

    Spreadsheet programming. It is, however, provided by thehosting environment and is not part of JavaScript itself.This duality of the programming language and the ob- jects provided by the hosting environment is similar to JavaScript running on the web client and the DocumentObject Model (DOM) entities that it manipulates.

    1.3 Summary Of Topics Covered

    • User-defined functions.• Detailed descriptions of Google App Spreadsheet ,

    Sheet , and Range objects and examples of how tomanipulate them.

    • Use of the Google JDBC Service to interact withrelational databases.

    • Accessing and manipulating other Google servicesincluding e-mail, Google Documents, etc.

    • User-interface construction.• Turning spreadsheet applications into web applica-

    tions.• Examples and discussion of more advanced JavaScript

    features such as object-oriented programming andcallbacks. There will be an emphasis on how thesetechniques can be applied to Google Spreadsheetprogramming.

    • An appendix showing how to translate commonspreadsheet application tasks from Excel Visual Ba-

  • 8/9/2019 Google Spgoogle spreadsheet programming

    9/95

    Chapter 1: Introduction 4

    sic for Applications (VBA) code into Google AppsScript.

    1.4 What Is Needed To Use ThisBook

    • A Gmail account.• Some programming experience and/or spreadsheet

    power user level. The latter being defined as some-one who uses spreadsheet functions such as IF, VLOOKUP,etc .

    • A desire to learn and apply JavaScript.

    1.5 Intended Readership

    • Spreadsheet power users with experience in Mi-crosoft Excel or some other spreadsheet application.

    • Excel VBA developers wishing to add Google Spread-sheet application development to their skills set.

    • Anyone wishing to learn Google Apps Scriptingto deliver cloud-based, cross-platform spreadsheetapplications.

    • Those for whom the content of this blog¹ is of interest.

    ¹http://www.javascript-spreadsheet-programming.com/

    http://www.javascript-spreadsheet-programming.com/http://www.javascript-spreadsheet-programming.com/

  • 8/9/2019 Google Spgoogle spreadsheet programming

    10/95

    Chapter 1: Introduction 5

    1.6 Note On Code and CodeExamples

    The emphasis on this book is on practical code examples.Some of the code examples are short and only practical inthe sense that they exemplify a Google Apps Script feature.All the code examples in this book are available on Github.The user name is Rotifer and the file name is simply“book_code.gs”. The full URL is here.² There is some HTMLand Excel VBA in this file and where present it is enclosedin JavaScript multi-line comment blocks (/* */). The codeexamples have been formatted exactly as they appear inthe book. JavaScript features deemed to be problematic (asdefined in Douglas Crockford’s O’Reilly book JavaScript

    The Good Parts ) are generally avoided.

    1.7 Google Spreadsheet Limitations

    According to Google, a Google Spreadsheet cannot ex-ceed 400,000 cells in size and each sheet is limited to

    256 columns. Although this is small compared to Mi-crosoft Excel, it is adequate for the examples given here.Databases are better suited to large-scale data storage thanspreadsheets and Google Spreadsheets can connect to suchdatabases. The use of Google Spreadsheets as a front-end for a relational database running in the cloud will be

    ²https://github.com/Rotifer/JavaScript/blob/master/book_code.gs

    https://github.com/Rotifer/JavaScript/blob/master/book_code.gshttps://github.com/Rotifer/JavaScript/blob/master/book_code.gs

  • 8/9/2019 Google Spgoogle spreadsheet programming

    11/95

    Chapter 1: Introduction 6

    discussed in later chapters.

    1.8 How To Use This Book

    There are a lot of code examples in this book and theseshould be copied and pasted into the Google Apps Script

    editor and then executed. They are generally heavily com-mented with further discussion in the text.

    To get maximum benefit from the codeexamples:

    • Read the comments and text discussion.

    • Execute the code.• Examine the output (written to the log or a spread-

    sheet).• Experiment with the code by changing it to see how

    the output is affected.

    Just like learning a human language, reading and studying

    grammar can only get you so far. Proficiency in the lan-guage is only gained by a willingness to speak it, to makemistakes and to learn from these mistakes.

    The more JavaScript you know, the easier you will findthe content here. JavaScript features are discussed whererelevant in the text but the book aims to teach GoogleApps Script as used by Google Spreadsheets so it is not a

  • 8/9/2019 Google Spgoogle spreadsheet programming

    12/95

    Chapter 1: Introduction 7

    JavaScript introduction. See the Useful Resources sectionfor details.

    1.9 Structure Of This Book

    In order to get started chapter 2 introduces Google Apps

    Script so that you can run simple scripts. Some of theobjects and concepts it uses are not discussed until laterchapters. Chapters 3 to 5 are fundamental to everythingthat follows because they discuss JavaScript functions andthe core Google App Application Programming Interfaces(APIs) needed for Google Spreadsheet programming.

    User-defined functions (also known as custom spreadsheet

    functions) are discussed in depth in Chapter 3. User-definedfunctions are an important topic in any discussion of spreadsheet programming. They have an added importancein this context because JavaScript functions, which areso important in JavaScript programming generally, areintroduced here.

    Chapters 4 and 5 cover the core Google Spreadsheet APIs:

    • SpreadsheetApp • Spreadsheet • Sheet • Range

  • 8/9/2019 Google Spgoogle spreadsheet programming

    13/95

    Chapter 1: Introduction 8

    There are a lot of code examples in these chapters to getyou up-to-speed with the important techniques needed tomanipulate spreadsheets, sheets and ranges.

    Chapter 6 uses the Google Jdbc API to interact with acloud instance MySQL database. To follow along with theexamples in this chapter, the reader will need program-matic access to a cloud-based MySQL instance. The chapter

    shows how to set up one such an instance using GoogleCloud SQL.

    Menus, message box and input box dialogs are introducedin chapter 7. More complex user interfaces are introducedusing the UiApp toolset.

    Manipulation of Google Drive, email and calendars is

    discussed in chapters 8 and 9.The final chapter, chapter 10, introduces Html Service forthe creation of spreadsheet-backed web apps.

    The first of the two appendices will be of interest to ExcelVBA programmers. It presents Google Apps Script andequivalent VBA code for some common spreadsheet pro-gramming tasks. The final appendix provides informationon additional resources such as books, blogs, and websitesthat I have found useful. It also provides details on howto acquire from Github all the code examples given in thebook.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    14/95

    Chapter 2: GettingStarted

    2.1 Introduction

    The best way to learn JavaScript/Google Apps Script is towrite some code. Getting started is very straightforward:All that is needed is a Gmail account and a browser withan Internet connection. To run some example code, firstgo to the Google Drive area and create a spreadsheet. Toview the script editor, select Tools->Script editor… fromthe spreadsheet menu bar. The first time you do this in anew spreadsheet file, you will be presented with a pop-upwindow entitled “Google Apps Script”, just ignore and closeit for now. Give the project a name, any name you like, byhovering over and replacing the text “untitled project” onthe top left. Delete the code stub entitled “myFunction” sothat the script editor is now blank. Paste in the example

    code in the following sections and save (save icon or menuaction File->Save ).

    2.2 Google Apps Script Examples

    Here are four example functions. When pasted into thescript editor, the code formatting applied by the editor

  • 8/9/2019 Google Spgoogle spreadsheet programming

    15/95

    Chapter 2: Getting Started 10

    becomes evident and makes the code easier to read.

    1 function sayHelloBrowser() {2 // Declare a string literal variable.3 var greeting = 'Hello world!' ;4 // Display a message dialog with the greeting5 //(visible from the containing spreadsheet).

    6 Browser.msgBox(greeting);7 } 8

    9 function helloDocument() {10 var greeting = 'Hello world!' ;11 // Create DocumentApp instance.12 var doc =13 DocumentApp.create( 'test_DocumentApp' );14 // Write the greeting to a Google document.15 doc.setText(greeting);16 // Close the newly created document17 doc.saveAndClose();18 }19

    20 function helloLogger() {21 var greeting = 'Hello world!' ;22 //Write the greeting to a logging window.23 // This is visible from the script editor24 // window menu "View->Logs...".25 Logger.log(greeting);26 }27

  • 8/9/2019 Google Spgoogle spreadsheet programming

    16/95

    Chapter 2: Getting Started 11

    2829 function helloSpreadsheet() {30 var greeting = 'Hello world!' ,31 sheet = SpreadsheetApp.getActiveSheet();32 // Post the greeting variable value to cell A133 // of the active sheet in the containing34 // spreadsheet.35 sheet.getRange( 'A1' ).setValue(greeting);36 // Using the LanguageApp write the37 // greeting to cell:38 // A2 in Spanish,39 // cell A3 in German,40 // and cell A4 in French.41 sheet.getRange( 'A2' )42 .setValue(LanguageApp.translate(43 greeting, 'en' , 'es' ));44 sheet.getRange( 'A3' )45 .setValue(LanguageApp.translate(46 greeting, 'en' , 'de' ));47 sheet.getRange( 'A4' )48 .setValue(LanguageApp.translate(49 greeting, 'en' , 'fr' ));

    50 }

  • 8/9/2019 Google Spgoogle spreadsheet programming

    17/95

    Chapter 2: Getting Started 12

    2.2 Executing Code – One FunctionAt A Time

    In order to execute code, there must be at least one validfunction in the script editor. After pasting the code above,there are four functions that will each be executed in turn.

    Figure 2-1: Google Apps Script Editor displaying the code and the“Select function” drop-down list.

    Select function sayHelloBrowser() from the “Select func-

    tion” drop-down list on the script editor toolbar and thenpress the execute icon (to the left of the function list drop-down). Switch to the spreadsheet and you will see a smallwindow with the greeting “Hello world”. These browserpopup displays are modal meaning that they block allsubsequent code execution until they are closed. For thisreason, their use should be limited. The Logger is generallya better tool for writing and displaying output.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    18/95

    Chapter 2: Getting Started 13

    Now select the second function named helloDocument() and execute it. This is a much more interesting examplethan the previous one because it shows how one GoogleApps Script can be used to manipulate other applications.The first time you try to execute it, you will get a messagesaying, “Authorization required”. Once you authorise it andthen execute, it will create a new Google document andwrite the message to it. This example, though trivial anduseless, does demonstrate how Google App Script codewritten in one application can manipulate other applica-tions. This is a very powerful feature and will be a recurringtheme of this book.

    The helloLogger() function, when executed, writes the mes-sage 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 and is generally more useful thanthe Browser.messageBox method used earlier. It will beused frequently in later code examples.

    The final function helloSpreadsheet() demonstrates twoimportant aspects of Google Apps Script:

    Firstly, spreadsheets can be manipulated via the Spread- sheet object (the Google documentation refers to Spread- sheet as a “class”). It provides a method that returns anobject representing the active sheet and that this returnedobject has a method that returns a range, in this instance asingle cell with the address “A2” . The returned range objectmethod, setValue() , is then called with a string argumentthat is written to cell A1 of the active sheet. These types

  • 8/9/2019 Google Spgoogle spreadsheet programming

    19/95

    Chapter 2: Getting Started 14

    of chained method calls look daunting at first. The methodcall chain described above could be re-written as:

    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 variablesand may be easier to understand initially but after ex-

    perience with JavaScript generally, the chained methodcall will start to feel easier and more natural. The objectsreferenced in this example will be discussed in detail inchapters 4 and 5.

    Secondly, the example code shows how easy it is to callanother service from a Google Apps Script function. Herethe LanguageApp was used to translate a simple text

    message into Spanish, German, and French. This abilityto seamlessly access other Google services is extremelypowerful.

    2.3 Summary

    • Anyone with a modern browser, an Internet connec-

  • 8/9/2019 Google Spgoogle spreadsheet programming

    20/95

    Chapter 2: Getting Started 15

    tion, and a Gmail account can write useful code inGoogle Apps Script.

    • The script editor provides a simple Integrated Devel-opment Environment (IDE) that can display objectproperties; provide code highlighting, and debug-ging.

    • To execute code, there must be at least one valid

    function in the script editor.• Google Apps Script developed in Google Spread-sheets can access and manipulate other Google prod-ucts and services.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    21/95

    Chapter 3: User-DefinedFunctions

    3.1 Introduction

    User-defined functions, also known as custom spreadsheet functions , allow spreadsheet users and developers to extendspreadsheet functionality. Since spreadsheets are widelyused in finance, engineering, science, etc. there is a need tooffer customised functionality and user-defined functionsare one of the most common and easiest ways to do this.

    User-defined functions are a good starting point for learn-ing Google Apps Script for a number of reasons becausethey:

    • Extend functionality.• Provide practice in JavaScript.

    • Can be learned without having to deal with thecomplexities if the Google Apps APIs.

    Learning Google Apps Script poses two challenges: (1) JavaScript and (2) The Google Apps APIs. Spending sometime on user-defined functions really helps with the firstof these challenges and is good preparation for the secondone.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    22/95

    Chapter 3: User-Defined Functions 17

    DefinitionA user-defined function is one that can becalled using the equals (=) sign in a spread-sheet cells and writes its return value to thecell.

    3.2 Built-in Versus User-DefinedFunctions

    Modern spreadsheet applications, including Google Spread-sheets, supply a large number of built-in functions andthey owe much of their utility and widespread usage to

    these functions. There is also a high degree of standard-isation between spreadsheet applications with respect tofunction names, arguments, and usage to such a degree thatthey generally work uniformly in Google Spreadsheets,Microsoft Excel, OpenOffice Calc and Gnumeric. GoogleSpreadsheets currently has 316 built-in functions spreadover multiple categories, Google Spreadsheet function list³.

    ³https://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cs

    https://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cshttps://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cshttps://support.google.com/drive/bin/static.py?hl=en&topic=25273&page=table.cs

  • 8/9/2019 Google Spgoogle spreadsheet programming

    23/95

    Chapter 3: User-Defined Functions 18

    3.3 Why Write User-DefinedFunctions

    Familiarity with built-in spreadsheet functionality shouldbe a prerequisite for writing user-defined functions. Re-implementing a function that already exists shows igno-rance of the application, is a waste of time, and has thepotential to introduce bugs. The two main justifications forwriting user-defined functions are for clarity and to extendfunctionality. User-defined functions can add to clarityby giving a name to complex computations. Spreadsheetpower-users can often ingeniously combine the built–infunctions to effectively create new ones. The disadvantageof this approach is that the resulting formulas can be very

    difficult to read, understand and debug. When such func-tionality is captured in a function, it can be given a name,documented and, tested. Secondly, user-defined functionsallow developers to customise spreadsheet applications byadding functionality for their particular domain.

    3.4 What User-Defined FunctionCannot Do

    The single-most important point about user-defined func-tions is that they cannot be used to alter any properties,such as formats, of the spreadsheet or any of its cells. Theycannot be used to send e-mails and cannot be used to insert

  • 8/9/2019 Google Spgoogle spreadsheet programming

    24/95

    Chapter 3: User-Defined Functions 19

    new worksheets. Functions can be used to do these thingsbut they cannot be called as user-defined functions. This isa common area of misunderstanding where users attemptto call functions from the spreadsheet using the equalsoperator (=). This results in an error because the functionis trying to alter some spreadsheet property.

    User-defined functions should be thought of as mathemati-

    cal functions that have defined inputs and return an output.Their purpose is their return values not their side effects.Excel VBA makes a distinction between subroutines andfunctions. Subroutines do not return a result and cannotbe called as user-defined functions. Consider the followingfunction that takes a range address argument and sets thefont for the range to bold:

    1 function setRangeFontBold (rangeAddress) {2 var sheet =3 SpreadsheetApp.getActiveSheet();4 sheet.getRange(rangeAddress)5 .setFontWeight( 'bold' ); 6 }

    The code uses Google Apps objects that have not yet beendiscussed but the idea is simple; Take a range input and setthe font to bold for that range. However, when the functionis called from a spreadsheet, it does not work.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    25/95

    Chapter 3: User-Defined Functions 20

    Figure 3-1: Error displayed when calling a function with side effectsfrom a spreadsheet.

    The error shown above refers to permissions but the prob-lem is that the called function is attempting to modify sheetproperties.

    To prove that the function setRangeFontBold() is valid, hereis a function that prompts for a range address using anBrowser.inputBox dialog. It calls the setRangeFontBold()

    function passing the given range address as an argument.Note that to see the input dialog, you have to call the func-tion in the script editor and then switch to the spreadsheet.

    1 function call_setCellFontBold () {2 var rangeAddress = Browser.inputBox(3 'Set Range Font Bold' ,

    4 'Provide a range address' ,5 Browser.Buttons.OK_CANCEL); 6 if (rangeAddress) {7 setRangeFontBold(rangeAddress); 8 } 9 }

    Code Notes:

  • 8/9/2019 Google Spgoogle spreadsheet programming

    26/95

    Chapter 3: User-Defined Functions 21

    • Display an input dialog that prompts for a rangeaddress in “A1:B10” format (NOT case-sensitive).

    • For a single cell, input, enter just the cell address.• If OK is pressed, then call function setRangeFont-

    Bold() .• Remember that when calling this function, you must

    switch to the spreadsheet view to see the input

    dialog!

    When this function is called, the following input dialog isdisplayed in the spreadsheet view:

    Figure 3-2: Browser.inputBox prompting for a range address.

    The Browser.inputBox mechanism for requesting user in-put will be discussed in a later chapter. The important pointis that a function may be valid but, if it has side effects suchas altering range properties, then it cannot be called as auser-defined function.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    27/95

    Chapter 3: User-Defined Functions 22

    3.5 Using User-Defined FunctionsUser-defined functions can be called exactly like built-inones using the equals (=) operator in a spreadsheet cell.They can take zero or more arguments of different typesand these arguments can be either cell references or literalvalues, just like built-in functions. The user-defined func-

    tions themselves are written in Google Apps Script that,as stated earlier, is JavaScript. To understand and writeuser-defined functions in Google Spreadsheets requires anunderstanding of JavaScript functions.

    3.6 Introducing JavaScript

    Functions JavaScript functions are immensely powerful and key tomastering the idioms and patterns of the language. Onlythe basics of JavaScript functions are required for thepurposes of this chapter. There are different ways of declar-ing functions and functions can be nested inside other

    functions to create closures . Functions can be passed asarguments to other functions and they can be the returnvalues of functions. Functions passed around in this waycan be used as callbacks . These features add great powerbut also complexity. An example using a callback is givenlater in this chapter.

    For the purposes of this chapter here are the principal points

  • 8/9/2019 Google Spgoogle spreadsheet programming

    28/95

    Chapter 3: User-Defined Functions 23

    of note regarding JavaScript functions:

    • A function declaration takes the form:

    1 function functionName(comma - separated2 parameters) {

    3 statements4 }

    • When the function is called, the arguments passedin are assigned to the parameters in the functiondefinition.

    • These arguments can then be used within the func-tion body.

    • Parameters are always passed by value in JavaScriptbut when reference types, such as arrays, are used,the behaviour can appear pass-by-reference.

    • If the number of arguments passed in is less thanthe number of parameters in the function definition,the unassigned parameters are given the value unde- fined .

    • Variables declared within the function using the var statement are local, i.e. scoped to, that function andare not visible outside the function.

    • Functions in JavaScript are objects and are equippedwith a number of pre-defined attributes.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    29/95

    Chapter 3: User-Defined Functions 24

    • Two function attributes are important for this chap-ter. These are the arguments object and the length property.

    • The arguments object is an array-like list that storesall the arguments passed to the function when it iscalled.

    • The arguments object is not an array but like the

    Array type it does have a length property that storesthe number of arguments that were actually givenwhen the function was called and its elements canbe accessed using array-like indexing.

    • The length property of the function stores the num-ber of arguments the function expects based on thenumber of parameters in the function definition.

    • Since JavaScript functions can accept any number of arguments of any type regardless of the parameterlist, the arguments.length value can be compared tothe function length property to check if the argumentcount is as expected.

    • Functions can have an explicit return statement. If noreturn statement is specified, the function will returnthe value undefined .

    • User-defined functions without a return statementare pointless.

    • A return statement on its own can be used to exit thefunction and will return undefined , again, not muchuse in user-defined functions.

    • User-defined functions should always return somevalue other than undefined .

  • 8/9/2019 Google Spgoogle spreadsheet programming

    30/95

    Chapter 3: User-Defined Functions 25

    • The returned value can be a primitive such as astring, Boolean, or a number. It can also be a ref-erence type such as a JavaScript object or an array.

    To see some of these points in action, paste the followingcode into the Google Apps Script editor and choose and runthe second function named call_testFunc .

    1 function testFunc(arg1, arg2) {2 var i;3 Logger.log( 'Number of arguments given: ' +4 arguments.length);5 Logger.log( 'Number of arguments expected: ' + 6 testFunc.length);7 for (i = 0; i < arguments.length; i += 1) { 8 Logger.log( 'The type of argument number ' + 9 (i + 1) + ' i s ' +

    10 typeof arguments [ i ] );11 }12 }

    Code Notes:

    • Testing function properties:• Determine the number of arguments expected against

    the number of arguments passed in.• Determine the types of all given arguments using the

    typeof operator

  • 8/9/2019 Google Spgoogle spreadsheet programming

    31/95

    Chapter 3: User-Defined Functions 26

    1 function call_testFunc() {2 Logger.log( 'First Invocation:' );3 testFunc( 'arg1' , 2);4 Logger.log( 'Second Invocation:' );5 testFunc( 'arg1' , 2, 'arg3' , false , 6 new Date (), null , undefined );7 }

    Code Notes:

    • Call function ‘testFunc()’ twice with different argu-ment lists.

    • To see the logger output select ‘View->Logs…’ fromthe script editor menu!

    The function output demonstrates how JavaScript func-tions can be made more stringent by:

    1. Checking the argument count given when the func-tion is called (arguments.length ) against the argu-ment count expected based on the parameter list inthe function definition (the function length prop-

    erty).2. Using the typeof operator to determine the typeof each given argument. The typeof operator canalso be used to identify missing argument valueswhere the missing value will be of type undefined.This check can be used to assign defaults using thestatement if (typeof arg === ‘undefined’ ) { arg =default; } .

  • 8/9/2019 Google Spgoogle spreadsheet programming

    32/95

    Chapter 3: User-Defined Functions 27

    3.7 User-Defined Functions Versus JavaScript Functions

    When user-defined functions are called from within spread-sheet cells, their string arguments must be provided indouble quotes . In JavaScript, either single or double quotescan be used to enclose a string literal but only double quotesare acceptable for string literals in user-defined functions.Single quote usage can lead to puzzling errors so beware!

    JavaScript function names are case-sensitive, function afunc () { … } and function aFunc () { … } are two differentfunctions. VBA users, watch out for this “gotcha”! How-ever, when called from a spreadsheet, the function namesare case-insensitive . The implication of this is to be verycareful when naming functions to be called from a spread-sheet. Camel-casing is the JavaScript standard and is usedthroughout here except when defining testing functionsthat may be given the prefix “testing_”.

    3.8 Checking Input And ThrowingErrors

    JavaScript functions are flexible and can be called withany number of arguments of any type. These issues shouldnot be ignored when writing user-defined functions. Thenumber and type of all given arguments should be verified.In some instances, arguments may have a valid range and

  • 8/9/2019 Google Spgoogle spreadsheet programming

    33/95

    Chapter 3: User-Defined Functions 28

    any arguments outside this range should be rejected. Forexample, for numeric arguments negative values may notbe valid.

    The code examples here generally implement argumentchecking and raise an error if any argument is invalid. Theyall use the throw statement followed by an object literal -defined by the curly braces- that contains two properties,

    the error name and an error message. Object literals will bediscussed in detail in later chapters. The effect of throwingthe error object when the functions are called from aspreadsheet will be seen in the examples. As a generalrule, all JavaScript functions should throw an error to thecaller if there is any doubt about the validity of any of thearguments.

    3.9 Encapsulating A ComplexCalculation

    The relative standard deviation ⁴ (RSD) is frequently usedin 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 standarddeviation divided by the sample mean multiplied by 100.Given the following values in cells A1 to A10: 19.81 18.2921.47 22.54 20.17 20.1 17.61 20.91 21.62 19.17 The RSDrounded to two decimal places can be calculated using this

    ⁴http://en.wikipedia.org/wiki/Relative_standard_deviation

    http://en.wikipedia.org/wiki/Relative_standard_deviationhttp://en.wikipedia.org/wiki/Relative_standard_deviation

  • 8/9/2019 Google Spgoogle spreadsheet programming

    34/95

    Chapter 3: User-Defined Functions 29

    spreadsheet formula:=ROUND(100*(STDEV(A1:A10)/AVERAGE(A1:A10)),2)

    The functionality expressed in this spreadsheet formula canbe encapsulated in a user-defined function as follows:

    1 // Given the standard deviation and the mean,2 // return the relative standard deviation.3 function RSD (stdev, mean) {4 if ( ! (typeof stdev === 'number' &&5 typeof mean === 'number')) { 6 throw {'name' : 'TypeError',7 'message' : 8 'Function "RSD()" requires ' + 9 'two numeric arguments'};

    10 }11 return ( 100 * (stdev / mean)).toFixed( 2) *1 ;12 }

    Code Notes:

    • Given the mean and standard deviation, return the

    Relative Standard Deviation expressed as a percent-age.• Check that two numeric arguments are provided,

    otherwise, throw an error.• Use thetoFixed() numeric method to round the result

    to two decimal places and multiply the result by 1to convert the string returned by toFixed() back to anumber.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    35/95

    Chapter 3: User-Defined Functions 30

    • Call example:=RSD(STDEV(A1:A10),AVERAGE(A1:A10))

    The above function can be pasted into the script editorand called as described in the documentation. So whatwas gained by writing a user-defined function when acombination of spreadsheet built-in functions can be usedand the user-defined version still uses the spreadsheet

    STDEV and AVERAGE built-ins? Firstly, the calculationnow has a meaningful name. Secondly, there is argumentchecking, an error is thrown if anything other than twonumeric values are passed to it. Lastly, the logic is capturedin one place and is documented. These are all good reasonsto consider replacing complex spreadsheet formulas withuser-defined functions.

    3.10 Numeric Calculations

    The following two examples take a single numeric argu-ment as degrees Centigrade or Fahrenheit and use thatargument to return the temperature in the other scale. Touse, paste the two functions into the Google Apps Scripteditor and then call them by name in a cell in the containingspreadsheet. For example, if cell A1 contains the value 0,then the formula =celsiusToFahrenheit(A1) in cell B1 willreturn the result 32 as expected.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    36/95

    Chapter 3: User-Defined Functions 31

    1 // Given a temperature value in Celsius2 // return the temperature in Fahrenheit.3 function celsiusToFahrenheit (celsius) {4 if (typeof celsius !== 'number') {5 throw { 6 'name' : 'TypeError',7 'message' : 'Function requires ' + 8 'a single number argument'}; 9 }

    10 return ((celsius * 9) / 5 ) + 32;11 }

    Code Notes:

    • Given a temperature in Celsius return its value inFahrenheit.• Throw an error if the given argument is non-numeric

    or omitted.

    1 // Given a temperature in Fahrenheit,

    2 // return the temperature in Celsius.3 function fahrenheitToCelsius(fahrenheit) {4 if (typeof fahrenheit !== 'number') {5 throw { 6 'name' : 'TypeError',7 'message' : 'Function requires ' + 8 ' a single number argument'}; 9 }

  • 8/9/2019 Google Spgoogle spreadsheet programming

    37/95

    Chapter 3: User-Defined Functions 32

    10 return ( fahrenheit - 32 ) * 5/9 ;11 }

    Code Notes:

    • Given a temperature in Fahrenheit, return its valuein Celsius.

    • Throw an error if the given argument is non-numericor omitted.

    The arithmetic is very simple here but the typeof checkis essential in both functions to avoid some erroneousinterpretation of spreadsheet input as will be describedbelow. Here is a screenshot showing some input values and

    the outputs after calling these two functions:

    Figure 3-3: Input and output for two user-defined functions cel- siusToFahrenheit() and fahrenheitToCelsius() .

  • 8/9/2019 Google Spgoogle spreadsheet programming

    38/95

    Chapter 3: User-Defined Functions 33

    Note how the thrown error is reported as a comment incells A5 to A7. Without the typeof check, the date value incell A5 would be interpreted as a number of seconds andwould return an unfeasibly large number. The outcome of evaluating the cell A7 is even more insidious where theblank is interpreted as zero and the function evaluatesto 32. Indeed, 0 Celsius is equal to 32 Fahrenheit but thisis highly misleading. Remove or comment out the typeof check and see the effect! The text value in cell A6 willthrow an error regardless of the typeof check, which is tobe expected. However, the default interpretation of datesas numbers and blank cells as zero is a serious trap forthe unwary. The same problem occurs in Excel VBA andis more difficult to guard against.

    These two examples of user-defined functions are verysimple but they highlight the need for rigorous checking of inputs. Verifying that arguments are within a valid rangemay also be required to avoid invalid return values. As anexample, the formula to calculate the area of a circle issimple: Π * radius 2 . The following function does this butit also checks that the given argument is both numeric andnot less than zero.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    39/95

    Chapter 3: User-Defined Functions 34

    1 // Given the radius, return the2 // area.3 // Throw an error if the radius is4 // negative.5 function areaOfCircle (radius) { 6 if (typeof radius !== 'number'){7 throw { 8 'name' : 'TypeError', 9 'message' : 'Function requires ' +

    10 'a single numeric argument'};11 }12 if (radius < 0) {13 throw {14 'name' : 'ValueError',15 'message' : 'Radius myst ' +16 ' be non - negative'};17 }18 return Math. PI * (radius * radius);19 }

    Code Notes:

    • Given a radius, calculate and return the area of acircle.• Throw a type error if the argument is non-numeric.• Since a negative radius value makes no sense, throw

    a value error if the argument is less than zero.

    The function checks that the given radius is numeric andthat the value is not less than zero. Both checks could

  • 8/9/2019 Google Spgoogle spreadsheet programming

    40/95

    Chapter 3: User-Defined Functions 35

    have been performed in a single if statement using the &&(and) operator but performing them separately allows morespecific errors to be thrown. This approach helps whenfunctions are part of larger applications.

    3.11 Date Functions

    Date manipulation in spreadsheets can be challenging butuser-defined functions can be used to do date manipula-tions and to encapsulate potentially complex spreadsheetmanipulations. For example, knowing the number of daysin the interval between two dates can be useful. A spread-sheet can actually do that without a user-defined function.Subtracting one date value from another returns the differ-ence in days. To demonstrate this in Google Spreadsheets,enter two date values in the format YYYY-MM-DD in twocells and, in a third cell, subtract one from the other to getthe time interval in days. To get an age in days one couldenter =(TODAY() – birth_date). There are a few reasonswhy this could be productively written as user-definedfunction:

    • The function has a name and can be documented andtested.

    • The input values can be checked and dealt with asappropriate.

    • The user-defined function can be re-used both inother Google Apps Script functions and more gen-

  • 8/9/2019 Google Spgoogle spreadsheet programming

    41/95

    Chapter 3: User-Defined Functions 36

    erally in client-side web applications or in Node.js scripts.

    Here is a function called intervalInDays() that takes twodate arguments and returns the interval between them indays.

    1 // Given two dates, return the interval in days2 // between them.3 function intervalInDays(date1, date2) {4 var millisecondsPerDay = 86400000 ;5 if ( ! (date1 instanceof Date && 6 date2 instanceof Date)) {7 throw { 8 'name' : 'TypeError', 9 'message' : 'Function requires ' +

    10 ' two Date type arguments'};11 }12 return (date1 - date2) / millisecondsPerDay;13 }

    Code Notes:

    • Declare a variable containing the number of millisec-onds in a day.

    • Check that the two given arguments are of type Date ,throw an error if they are not.

    • Subtract date2 from date1 to give the millisecondinterval.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    42/95

    Chapter 3: User-Defined Functions 37

    • Divide by the number of milliseconds in a day to getthe interval in days.

    • Return the interval in days.

    1 function test_intervalInDays() {2 var date1 = new Date (),

    3 date2 = new Date ( 1972 , 7, 17 );4 Logger.log(intervalInDays(date1, date2));5 }

    Code Notes:

    • Create two date objects, the current date (date1) andan arbitrary date in the past.

    • Call function intervalInDays() passing in these twodates as arguments.

    • Write the output to the logger.• Note: when creating a date object in JavaScript, the

    month is zero-based so 7 corresponds to August NOT July!

    The code above can be pasted in to the Google Apps Scripteditor. The second function named intervalInDays can becalled from a spreadsheet and returns the interval in daysbetween the first and second date arguments. The typeof operator is no use this time for type checking becauseit returns the generic ‘object’ for all non-primitive types

  • 8/9/2019 Google Spgoogle spreadsheet programming

    43/95

    Chapter 3: User-Defined Functions 38

    and that includes Date types. The instanceof operator canhowever determine if both arguments are of type Date .Conveniently, Google Apps Script correctly interprets cellinput formatted in the spreadsheet as Date . The testingfunction named test_intervalInDays demonstrates how toconstruct a Date object in JavaScript. The Date object isvery clearly described on the Mozilla Developer Networkwebsite⁵.

    3.12 Text Functions

    Google Spreadsheets text manipulation functions can alsobe complemented and enhanced by writing user-definedfunctions. JavaScript, like most programming languages,refers to the text type as “string”. Strings in JavaScriptare primitive types but they can be wrapped to behavelike objects. In the context of JavaScript, methods aresimply functions attached to objects. The wrapping of aprimitive so that it becomes an object is known as auto-boxing . Auto-boxing can also be applied to Boolean andNumber primitive types. Since JavaScript’s handling of

    this is transparent to the user/programmer, all that reallymatters is that strings have methods that can be used toextract information from them and to generate new strings.Strings can also be manipulated using JavaScript regularexpressions. Regular expressions are very powerful and

    ⁵https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

    https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Datehttps://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Datehttps://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Datehttps://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date

  • 8/9/2019 Google Spgoogle spreadsheet programming

    44/95

    Chapter 3: User-Defined Functions 39

    they are used in some examples in later chapters. Theirspecific use in spreadsheets as user-defined functions arecovered in an entry in the author’s blog⁶.

    To see all the String properties supported by Google AppsScript, paste the following code into the script editor andexecute it. An alphabetical list of string properties is sentto the logger.

    1 // Write String methods to the logger.2 function printStringMethods() {3 var strMethods =4 Object.getOwnPropertyNames(5 String.prototype); 6 Logger.log('String has ' +

    7 strMethods.length + 8 ' properties.'); 9 Logger.log(strMethods.sort(). join ( '\n' ));

    10 }

    The code above uses JavaScript’s very powerful introspec-tion capabilities to extract an array of all the property

    names defined for type String on what is known as its prototype . The logger output shows that there are 39 prop-erties. Most, but not all, of the properties are methods butthe important length property, for example, is not. Theexamples given here are meant to be short and illustrative.

    ⁶http://www.javascript-spreadsheet-programming.com/2013/09/regular-expressions.html

    http://www.javascript-spreadsheet-programming.com/2013/09/regular-expressions.htmlhttp://www.javascript-spreadsheet-programming.com/2013/09/regular-expressions.htmlhttp://www.javascript-spreadsheet-programming.com/2013/09/regular-expressions.html

  • 8/9/2019 Google Spgoogle spreadsheet programming

    45/95

    Chapter 3: User-Defined Functions 40

    As an example, here is a function that returns its stringargument with the characters reversed.

    1 // Reverse the alphabet.2 function test_reverseString () {3 var str = 'abcdefghijklmnopqrstuvwxyz';4 Logger.log(reverseString(str));5 } 6 // Return a string with the characters7 // of the input string reversed. 8 function reverseString (str) { 9 var strReversed = '',

    10 lastCharIndex = str.length - 1 ,11 i;12 if (typeof str !== ' string ') {

    13 throw {14 'name' : 'TypeError',15 'message' : 'Function requires a ' +16 ' single string argument.'};17 }18 for (i = lastCharIndex; i >= 0; i -= 1 ) {19 strReversed += str[i];

    20 }21 return strReversed;22 }

    Code Notes:

    • Function test_reverseString is called to test reverseS- tring() in Script editor.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    46/95

    Chapter 3: User-Defined Functions 41

    • Function reverseString() accepts a single string argu-ment and returns a string where the characters are inreverse order.

    • It checks that the given argument is a string, if notan exception is thrown.

    • Note on variable initialisation: Variable strReversed must be set to an empty string, otherwise ‘undefined’

    is prepended to the returned string.

    The example function uses a JavaScript for loop to extractthe string characters in reverse order and appends them toa new string that is built within the loop. The newly builtstring is returned upon completion of the loop. This func-tion highlights the importance of initialising the returned

    variable to an empty string. If this is not done, the variableis initially assigned undefined and when the first stringconcatenation operation takes place, the string representa-tion of undefined, which is ‘undefined’, is prepended to thereturned value.

    3.13 Using JavaScript LibraryMethods

    Checking both the number of arguments provided and theirtypes are necessary steps in developing robust and reli-able user-defined functions. JavaScript provides additionalfunctionality that can be used in user-defined functions.For example, the JavaScript Math library is available in

  • 8/9/2019 Google Spgoogle spreadsheet programming

    47/95

    Chapter 3: User-Defined Functions 42

    Google Apps Script and provides some useful methods.Simulation of a die throw can be easily implemented usingits methods:

    1 // Return a integer between2 // 1 and 6 inclusive.3 function throwDie () {

    4 return 1 + Math.floor(Math.random() * 6);5 }

    Code Notes:

    • Simulate a die throw by returning a random numberbetween and including 1 and 6.

    • Call: =throwDie()

    This function requires no inputs so there is no argumentchecking code. It uses two methods defined in the standard JavaScript Math library to simulate dice throwing. TheMath round() method could also be used here but, as isvery well described here⁷ , it leads to biased results. Thisbecomes apparent when the function is called hundreds of times. The important point to note is the need for testingand reading of documentation to avoid inadvertent errorsand biases.

    ⁷http://www.the-art-of-web.com/javascript/random/#.UPU8tKHC-nY

    http://www.the-art-of-web.com/javascript/random/#.UPU8tKHC-nYhttp://www.the-art-of-web.com/javascript/random/#.UPU8tKHC-nY

  • 8/9/2019 Google Spgoogle spreadsheet programming

    48/95

    Chapter 3: User-Defined Functions 43

    3.14 Using A Function CallbackThe object nature of JavaScript functions allows them to bepassed as arguments to other functions and, furthermore,to be returned by other functions. The following exampleprovides a taste of the power and flexibility that derivesfrom the fact that functions are objects. It also shows how

    easy it is to use a range of cells as an argument. The functionconcatenates an input range of cells using a delimiterargument. There is an in-built Google Spreadsheet functioncalled JOIN that performs this task but the user-definedversion below has one additional feature: It provides anoption to enclose each individual element in single quotes.Here is the code:

    1 // Concatenate cell values from2 // an input range.3 // Single quotes around concatenated4 // elements are optional.5 function concatRng(inputFromRng, concatStr, 6 addSingleQuotes) {7 var cellValues; 8 if (addSingleQuotes) { 9 cellValues =

    10 inputFromRng.map(11 function (element) {12 return "'" + element + "'" ;13 });14 return cellValues. join (concatStr);

  • 8/9/2019 Google Spgoogle spreadsheet programming

    49/95

    Chapter 3: User-Defined Functions 44

    15 }16 return inputFromRng. join (concatStr);17 }

    An example of a call to this function in the spreadsheetis =concatRng(A1:A5, “,” true) . This returns output like‘A’,’B’,’C’,’D’,’E’. There are two interesting aspects to thiscode:

    1. The range input is converted to a JavaScript array.In order to work correctly, all the input must befrom the same column. If the input range is two-dimensional or from multiple cells in the same row, itwill generate a JavaScript array-of-arrays. That pointis ignored here, but try giving it a two-dimensional

    range input or something like A1:C1” and observethe output!

    2. The more interesting point is the use of the arraymap() method. This method iterates the array andapplies its function argument to each element of the array and returns a new array. The functionused here is an anonymous function . It takes one

    argument, the array element, and returns it enclosedin single quotes. The anonymous function operatesas a callback. More examples of callbacks will begiven in later chapters. This example just hints at thepower of this approach.

    A version of this function was written in Excel VBA as aquick way of generating input for the IN clause in SQL.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    50/95

    Chapter 3: User-Defined Functions 45

    Lists of string values (VARCHARs in database terminology)would be provided in spreadsheets so an Excel user-definedfunction was written to allow the lists to be concatenatedin comma-separated strings with the constituent valuesenclosed in single quotes. There are better ways of runningsuch queries that will be discussed in the JDBC chapter butthis is an approach that can be useful.

    It is worth noting that built-in Google Spreadsheets canbe combined to get the same output: =CONCATENATE(“’”,JOIN(“’,’”, A1:A5), “’”) However, no introduction to JavaScriptfunctions would be complete without at least a brief men-tion of anonymous functions and callbacks.

    3.15 Extracting Useful InformationAbout The Spreadsheet

    All the user-defined functions discussed up to this pointwere written in host-independent JavaScript. They shouldall work in modern browsers or in Node.js scripts. The re-strictions on the actions of user-defined functions were also

    discussed. However, useful information about a spread-sheet can be returned to spreadsheet cells by means of user-defined functions. The examples given below are allfunctions that take no arguments and return some usefulinformation about the active spreadsheet. All can be calledas user-defined functions:

  • 8/9/2019 Google Spgoogle spreadsheet programming

    51/95

    Chapter 3: User-Defined Functions 46

    1 function spreadsheetId() {2 return SpreadsheetApp3 .getActiveSpreadsheet().getId();4 }5

    6 function spreadsheetUrl() {7 return SpreadsheetApp 8 .getActiveSpreadsheet().getUrl(); 9 }

    10

    11 function spreadsheetOwner() {12 return SpreadsheetApp13 .getActiveSpreadsheet().getOwner();14 }15

    16 function spreadsheetViewers() {17 var ss =18 SpreadsheetApp.getActiveSpreadsheet();19 return ss.getViewers().join( ', ' );20 }21

    22 function spreadsheetLocale() {

    23 var ss = SpreadsheetApp.getActiveSpreadsheet();24 return ss.getSpreadsheetLocale();25 }

    These examples use Google Apps Script host objects andmethods. The objects in the code examples are discussedextensively in the following two chapters, so read ahead if

  • 8/9/2019 Google Spgoogle spreadsheet programming

    52/95

    Chapter 3: User-Defined Functions 47

    you wish to understand them right now. The purpose hereis to just show how user-defined functions can be utilised toextract information about a spreadsheet using host objectmethods.

    All the functions given above can extract the requiredinformation and return it in a single statement. The func-tions spreadsheetViewers() and spreadsheetLocale() use a

    variable to reference the active spreadsheet and the valuereturned using a method call to the variable. The reason fordoing this here was simply to make the code more readableby avoiding a wrapped line in the book text.

    To see these functions in action, just paste the code aboveinto any Google Spreadsheet Script Editor and then in-voke each of them from the spreadsheet using the usual

    syntax, example: =spreadsheetId() . All of the examplesexcept spreadsheetViewers() use aSpreadsheet method thatreturns a primitive JavaScript value, namely a string. ThegetUsers() method however returns an array and the func-tion uses the Array type join() method to convert the arrayto a string. The join() call could be omitted and the functionwould still work. However, each user would be written to a

    separate cell. To experiment, remove the join() and call thefunction.

    3.16 Using Google Services

    Some of the Google Services can be used in user-definedfunctions. The following examples are taken from two such

  • 8/9/2019 Google Spgoogle spreadsheet programming

    53/95

    Chapter 3: User-Defined Functions 48

    services: Google Finance and Google Language.

    3.16.1 Financial Services

    The FinancialApp object provides share price informationon companies quoted on the New York Stock Exchange. ItsgetStockInfo() method takes a stock symbol as an argument

    and returns a JavaScript object. The following function printFinanceAppKeys() can be invoked from the ScriptEditor and writes its output to the log (Script Editor menu:View->Logs…->).

    1 // Print stockInfo object property2 // names to the logger.

    3 function printFinanceAppKeys() {4 stockSymbol = ' GOOG';5 Logger.log(Object.keys( 6 FinanceApp.getStockInfo(7 stockSymbol)) 8 .sort() 9 . join ( '\n' ));

    10 }

    For now just focus on the output in the log. The workingsof the code will be explained in a later chapter. The codeextracts the array of key names from the object returnedby the getStockInfo() method using a valid stock symbolas an argument, sorts them alphabetically, and then joinsthem all together with new lines. Two of the keys shown

  • 8/9/2019 Google Spgoogle spreadsheet programming

    54/95

    Chapter 3: User-Defined Functions 49

    above are used in the following user-defined functions toextract information of interest.

    1 // Given a stock symbol, return the2 // stock price (NYSE).3 function getStockPrice(stockSymbol) {4 return FinanceApp

    5 .getStockInfo(stockSymbol)['price']; 6 }7 // Given a stock symbol, return the 8 // full stock name. 9 function getStockName(stockSymbol) {

    10 return FinanceApp11 .getStockInfo(stockSymbol)['name'];12 }

    Example invocations of each: “=getStockPrice(“GOOG”)”and “=getStockName(“GOOG”)”.

    These two functions each use a key from the object re-turned by the method getStockInfo() and return the valueit maps to. Try experimenting with other keys to see the

    output. If you are interested in big American IT companies,try “GOOG”, “MSFT”, “AAPL”, “IBM” or “ORCL”. Thecompanies that these stock symbols refer to are easilyguessed.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    55/95

    Chapter 3: User-Defined Functions 50

    3.16.2 Language ServicesUser-defined functions can be used as a sort of dictionary totranslate word and phrases. The following three functionscan all be called from the spreadsheet to perform trans-lations from English to three other major West Europeanlanguages.

    1 function translateEnglishToGerman(input) {2 return LanguageApp3 .translate(input, 'en' , 'de' );4 }5

    6 function translateEnglishToFrench(input) {7 return LanguageApp 8 .translate(input, 'en' , 'fr' ); 9 }

    10

    11 function translateEnglishToSpanish(input) {12 return LanguageApp13 .translate(input, 'en' , 'es' );14 }

    Example invocation: =translateEnglishToFrench(“Try clos-ing the file!”) The output: “Essayez de fermer le fichier!”

    These functions appear to work well for single words andstraight-forward, non-idiomatic, phrases. However, only afluent speaker could comment on the translation quality.A good check is to re-translate back into the original

  • 8/9/2019 Google Spgoogle spreadsheet programming

    56/95

    Chapter 3: User-Defined Functions 51

    and see if it makes sense. I have tried some idiomaticinput such as “JavaScript rocks!” and “JavaScript sucks!”- translated into standard English as “JavaScript is reallygreat” and “JavaScript is very bad!”- and the translations,unsurprisingly, missed the point.

    3.17 Summary

    • Google Spreadsheets provides a large number of built-in functions.

    • User-defined functions can be written to comple-ment these functions and to provide new function-ality.

    • Before writing a user-defined function, ensure thatGoogle Spreadsheets does not already provide anequivalent.

    • User-defined functions cannot be used to set cellproperties or display dialogs.

    • User-defined functions are written in the GoogleApps Scripting version of JavaScript.

    • JavaScript functions are very powerful and veryflexible.

    • User-defined functions should be rigorously tested.• There should be code to check and verify the number

    and type of arguments that are passed when the user-defined function is called. The JavaScript typeof andinstanceof operators can be used for these purposes.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    57/95

    Chapter 3: User-Defined Functions 52

    • A variety of invalid data should be passed as ar-guments to ensure that the user-defined functionperforms as expected by throwing an error.

    • Use the throw statement with an object literal con-taining a name and message for the error.

    • Ensure that the user-defined function deals appro-priately with blank cells.

    • Ensure that user-defined functions expecting nu-meric arguments do not misinterpret date input.• Watch out for implicit JavaScript or spreadsheet type

    conversions.• When using JavaScript built-in functions or methods

    provided by the Math library for example, readthe documentation and test function output against

    expected results to avoid errors and biases.• The object nature of JavaScript functions allowsthem to be used as callbacks.

    • Useful information about a Google Spreadsheet doc-ument can be retrieved with user-defined functionsthat call methods of the SpreadsheetApp class.

    • User-defined functions can be used to query Google

    services such as FinancialApp and LanguageApp inorder to return useful information to a spreadsheet.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    58/95

  • 8/9/2019 Google Spgoogle spreadsheet programming

    59/95

    Appendix A: Excel VBA And Google Apps Script Comparison 54

    Script quite quickly. This appendix assumes knowledge of VBA and aims to facilitate the reader’s transition to theGoogle Apps Script environment.

    The examples below are given in pairs: First the VBAcode and then the functionally equivalent Google AppsScript version with some explanatory comments. The VBAis generally not commented because the examples assume

    VBA expertise. Comments are added, however, for trickierand longer examples or when the code examples in thetwo languages are very different due to inherent VBA/- JavaScript differences or divergent API approaches. Thecode examples should perform as described but in manyinstances alternative approaches can be used and the ex-amples may not be optimal.

    The VBA examples given generally write their output tothe Immediate Window while the Google Apps Scriptequivalents write to the Logger. Some examples write toor format spreadsheet cells.

    Google Apps Script Or JavaScript

    “JavaScript” is used here to refer to general JavaScript concepts such as arrays.

    Google Apps Script refers to the specific Googleimplementation as it applies to spreadsheetprogramming and Google App Script APIs.The context should make the usage clear.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    60/95

    Appendix A: Excel VBA And Google Apps Script Comparison 55

    Spreadsheets and SheetsSpreadsheets and sheets are handled similarly. One differ-ence of note is that Google Apps Script does not make adistinction between Sheets and Worksheets as VBA does.

    Active Spreadsheet

    Multiple spreadsheet files can be open at a given time butonly one is active .

    VBA

    1 Public Sub SpreadsheetInstance(()

    2 Dim ss As Workbook3 Set ss = Application.ActiveWorkbook4 Debug.Print ss.Name5 End Sub

    Google Apps Script

    1 function spreadsheetInstance() {2 var ss = SpreadsheetApp.getActiveSpreadsheet();3 Logger.log(ss.getName());4 }

    VBA uses the Name property while Google Apps Scriptuses the method getName() to return the value.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    61/95

    Appendix A: Excel VBA And Google Apps Script Comparison 56

    Sheet/WorksheetSpreadsheets contain sheets. In VBA these are stored ascollections and in Google Apps Script as JavaScript arraysof Sheet objects. The pairs of examples given here call someSheet methods and print the output.

    VBA1 Public Sub FirstSheetInfo()2 Dim sh1 As Worksheet3 Set sh1 = ActiveWorkbook.Worksheets( 1)4 Dim usedRng As Range5 Set usedRng = sh1.UsedRange 6 Debug.Print sh1.Name7 Debug.Print usedRng.Address 8 End Sub

    Google Apps Script

  • 8/9/2019 Google Spgoogle spreadsheet programming

    62/95

    Appendix A: Excel VBA And Google Apps Script Comparison 57

    1 function firstSheetInfo() {2 var ss = SpreadsheetApp.getActiveSpreadsheet(),3 sheets = ss.getSheets(),4 // getSheets() returns an array5 // JavaScript arrays are always zero-based 6 sh1 = sheets [ 0] ;7 Logger.log(sh1.getName()); 8 // getDataRange is analagous to UsedRange 9 //in VBA

    10 // getA1Notation() is functional equivalent to11 // Address in VBA12 Logger.log(sh1.getDataRange().getA1Notation());13 }

    Sheet CollectionsThe previous examples extracted a single Sheet object andcalled some of its methods. The example pairs here loopover the all the sheets of the active spreadsheet and printthe sheet names.

    VBA

  • 8/9/2019 Google Spgoogle spreadsheet programming

    63/95

    Appendix A: Excel VBA And Google Apps Script Comparison 58

    1 Public Sub PrintSheetNames()2 Dim sheets As Worksheets3 Dim sheet As Worksheet4 For Each sheet In ActiveWorkbook.Sheets5 Debug.Print sheet.Name 6 Next sheet7 End Sub

    Google Apps Script

    1 // Print the names of all sheets in the active2 // spreadsheet.3 function printSheetNames() {4 var ss = SpreadsheetApp.getActiveSpreadsheet(),5 sheets = ss.getSheets(), 6 i;7 for (i = 0; i < sheets.length; i += 1) { 8 Logger.log(sheets[i].getName()); 9 }

    10 }

    Adding And Removing SheetsSpreadsheet applications may need to add new sheets to anexisting spreadsheet file and then, after some processing,they may need to then remove one or more sheets. Bothtasks are easily achieved in both VBA and and Google AppsScript.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    64/95

  • 8/9/2019 Google Spgoogle spreadsheet programming

    65/95

  • 8/9/2019 Google Spgoogle spreadsheet programming

    66/95

    Appendix A: Excel VBA And Google Apps Script Comparison 61

    27 ss.getSheetByName( "AddedSheet" );28 sheetToRemove.activate();29 ss.deleteActiveSheet();30 Browser.msgBox( "SheetDeleted!" );31 }

    The code comments in both languages should adequately

    describe the actions and objects required to add and removesheets from both spreadsheet applications. The GoogleApps Script mechanism appears a little more complicatedthan its VBA equivalent. In order to remove a sheet, itfirst has to be activated so that the Spreadsheet instancemethod deleteActiveSheet() can be called. Otherwise, bothlanguages work quite similarly.

    Hiding And Unhiding Sheets

    Hiding sheets can help to keep a spreadsheet unclutteredand easy to use while also helping to prevent inadvertentchanges to important data. Lists of values that the appli-cation uses may not be important to the users so they canbe hidden from their view while still remaining availableto the application code. The VBA and Google Apps Scriptcode required to do the hiding, unhiding and listing of hidden sheets is very similar.

    Hiding a sheet identified by name.

    VBA

  • 8/9/2019 Google Spgoogle spreadsheet programming

    67/95

    Appendix A: Excel VBA And Google Apps Script Comparison 62

    1 Public Sub SheetHide()2 Dim sh As Worksheet3 Set sh = Worksheets.Item( "ToHide" )4 sh.Visible = False5 End Sub

    Google Apps Script

    1 // Hide a sheet specified by its name.2 function sheetHide() {3 var ss =4 SpreadsheetApp.getActiveSpreadsheet(),5 sh = ss.getSheetByName('ToHide'); 6 sh.hideSheet()7 }

    Listing hidden sheets

    VBA

  • 8/9/2019 Google Spgoogle spreadsheet programming

    68/95

    Appendix A: Excel VBA And Google Apps Script Comparison 63

    1 Public Sub ListHiddenSheetNames()2 Dim sheet As Worksheet3 For Each sheet In Worksheets4 If sheet.Visible = False Then5 Debug.Print sheet.Name 6 End If7 Next sheet 8 End Sub

    Google Apps Script

    1 // Write a list of hidden sheet names to log.2 function listHiddenSheetNames() {3 var ss =4 SpreadsheetApp.getActiveSpreadsheet(),5 sheets = ss.getSheets(); 6 sheets.forEach(7 function (sheet) { 8 if (sheet.isSheetHidden()) { 9 Logger.log(sheet.getName());

    10 }11 });

    12 }

    Unhiding hidden sheets

    VBA

  • 8/9/2019 Google Spgoogle spreadsheet programming

    69/95

    Appendix A: Excel VBA And Google Apps Script Comparison 64

    1 Public Sub SheetsUnhide()2 Dim sheet As Worksheet3 For Each sheet In Worksheets4 If sheet.Visible = False Then5 sheet.Visible = True 6 End If7 Next sheet 8 End Sub

    Google Apps Script

    1 // Unhide all hidden sheets.2 function sheetsUnhide() {3 var ss =4 SpreadsheetApp.getActiveSpreadsheet(),5 sheets = ss.getSheets(); 6 sheets.forEach(7 function (sheet) { 8 if (sheet.isSheetHidden()) { 9 sheet.showSheet();

    10 }11 });

    12 }

    The main difference in the approach taken by each lan-guage in these examples is how they iterate over the Work- sheets collection in VBA and the array of Sheet objects inGoogle Apps Script. Newer versions of JavaScript, includ-ing Google Apps Script, have added some very powerful

  • 8/9/2019 Google Spgoogle spreadsheet programming

    70/95

    Appendix A: Excel VBA And Google Apps Script Comparison 65

    methods to arrays. Included in these are methods that takea callback function as an argument that is invoked for eachelement in the array. The forEach() method above is anexample. It operates in a similar manner to the VBA For Each loop but unlike it, forEach() needs a function as anargument. In the examples above anonymous functionswere used. This type of approach where functions takeother functions as arguments is very powerful but may beunfamiliar to VBA programmers.

    Protecting Sheets

    Hiding sheets provides a type of “security through obscu-rity” but does not prevent deliberate tampering. Both VBA

    and Google Apps Script allow you to protect individualworksheets within a spreadsheet but they take very ap-proaches to this.

    VBA

  • 8/9/2019 Google Spgoogle spreadsheet programming

    71/95

    Appendix A: Excel VBA And Google Apps Script Comparison 66

    1 ' Password - protect rotect a sheet identified2 ' by name3 Public Sub SheetProtect()4 Dim sh As Worksheet5 Dim pwd As String : pwd = "secret" 6 Set sh = Worksheets.Item( "ToProtect" )7 sh.Protect pwd 8 End Sub

    Google Apps Script

    1 // Identify a sheet by name to protect2 // When this code runs, the lock icon3 // will appear on the sheet name.4 // Share the spreadsheet with another user

    5 // as an editor. That user can edit all 6 // sheets except the protected one. The user7 // can still edit the protected sheet. 8 function sheetProtect() { 9 var ss =

    10 SpreadsheetApp.getActiveSpreadsheet(),11 sh = ss.getSheetByName('ToProtect'),

    12 permissions = sh.getSheetProtection();13 ss.addEditor( < gmail address goes here >);14 permissions.setProtected(true);15 sh.setSheetProtection(permissions);16 }

    In VBA, a password is set and the protected is using theWorksheet Protect method passing it the password string

  • 8/9/2019 Google Spgoogle spreadsheet programming

    72/95

    Appendix A: Excel VBA And Google Apps Script Comparison 67

    as an argument. Once protected even the spreadsheet fileowner needs to know the password to do anything to thesheet. Google Apps Script takes a different approach. Bydefault, only the file creator can see or edit the spreadsheet.The owner can then add editors or viewers to the spread-sheet. A viewer can see all the sheets but not edit themwhile the editor can, as the name suggests, edit the sheetcontents. However, a single sheet can be protected so thatit can be viewed by a user granted editor privilege but isnot editable by them. The code example given above showshow this can be done. Unlike in VBA, however, the ownerof the spreadsheet will always have full edit permissionson all sheets. In other words, the owner cannot removepermissions from themselves.

    Ranges

    Spreadsheet programming is largely about manipulatingranges so this is a long section.

    Selection

    Requiring a user to select an input range is a commonfeature of spreadsheet applications. In order to process theselected cells, the application needs to determine:

    • The sheet containing the selection

  • 8/9/2019 Google Spgoogle spreadsheet programming

    73/95

    Appendix A: Excel VBA And Google Apps Script Comparison 68

    • The location of the selection within the sheet asgiven by its address

    • The dimensions of the selection, that is the numberof rows and columns in the selection

    This information is extracted and printed in the followingexamples

    VBA

    1 Public Sub PrintSelectionDetails()2 Debug.Print "Selected Range Details: "3 Debug.Print "-- Sheet: " & _4 Selection.Worksheet.Name

    5 Debug.Print "-- Address: " & _ 6 Selection.Address7 Debug.Print "-- Row Count: " & _ 8 Selection.Rows.Count 9 Debug.Print "'-- Column Count: " & _

    10 Selection.Columns.Count11 End Sub

    Google Apps Script

  • 8/9/2019 Google Spgoogle spreadsheet programming

    74/95

    Appendix A: Excel VBA And Google Apps Script Comparison 69

    1 // Prints details about selected range in2 // active spreadsheet3 // To run, paste code into script editor,4 // select some cells on any sheet,5 // execute code and 6 // check log to see details7 // Prints details about selected range 8 // in active spreadsheet 9 // To run, paste code into script editor,

    10 // select some cells on any sheet,11 // execute code and12 // check log to see details13 function printSelectionDetails() {14 var ss =15 SpreadsheetApp.getActiveSpreadsheet(),16 selectedRng = ss.getActiveRange();17 Logger.log('Selected Range Details: ');18 Logger.log(' -- Sheet: '19 + selectedRng20 .getSheet()21 .getSheetName());22 Logger.log(' -- Address: '

    23 + selectedRng.getA1Notation());24 Logger.log(' -- Row Count: '25 + ((selectedRng.getLastRow() + 1)26 - selectedRng.getRow()));27 Logger.log(' -- Column Count: '28 + ((selectedRng.getLastColumn() + 1)29 - selectedRng.getColumn()));

  • 8/9/2019 Google Spgoogle spreadsheet programming

    75/95

    Appendix A: Excel VBA And Google Apps Script Comparison 70

    30 }

    VBA provides the handy Selection object which is of typeRange and its methods can be used to extract the re-quired information. The Google Apps Script Spreadsheet object provides the getActiveSelection() method to returnthe Google Spreadsheets equivalent to the VBA Selection .

    Its getRow() and getColumn() methods return the rownumber of the first row and first column, respectively, forthe Range object on which they are invoked. The purposeof the getLastRow() and getLastColumn() Range methodsis clear from their names. By using a combination of these methods the VBA Selection.Rows.Count and Selec- tion.Columns.Count properties can be mimicked as was

    done above.

    Used Range

    To retrieve the very useful equivalent of the VBA Use- dRange object in Google Apps Script, use the Sheet get- DataRange() method. In both languages it is easy to trans-

    fer the cell contents of a range into an array. JavaScript ar-rays are a lot more flexible than those in VBA and they arealways zero-based. JavaScript’s dynamic typing also makesmatters more straightforward. VBA is a typed languagebut its Variant type negates the all the type-checking.However, it has to be used to receive the Range value property. Another fundamental language difference is that JavaScript does not distinguish functions and subroutines.

  • 8/9/2019 Google Spgoogle spreadsheet programming

    76/95

    Appendix A: Excel VBA And Google Apps Script Comparison 71

    Instead functions are always used and if there is no explicitreturn statement, undefined is the return value.

    VBA

    1 Public Function GetUsedRangeAsArray(sheetName _2 As String) As Variant3 Dim sh As Worksheet4 Set sh = _5 ActiveWorkbook.Worksheets(sheetName) 6 GetUsedRangeAsArray = sh.UsedRange.value7 End Function 8 Sub test_GetUsedRangeAsArray() 9 Dim sheetName As String

    10 Dim rngValues11 Dim firstRow As Variant12 sheetName = "Sheet1"13 rngValues = GetUsedRangeAsArray(sheetName)14 Debug.Print rngValues( 1, 1)15 Debug.Print UBound(rngValues)16 Debug.Print UBound(rngValues, 2)17 End Sub

    Google Apps Script

  • 8/9/2019 Google Spgoogle spreadsheet programming

    77/95

    Appendix A: Excel VBA And Google Apps Script Comparison 72

    1 function getUsedRangeAsArray(sheetName) {2 var ss =3 SpreadsheetApp.getActiveSpreadsheet(),4 sh = ss.getSheetByName(sheetName);5 // The getValues() method of the 6 // Range object returns an array of arrays7 return sh.getDataRange().getValues(); 8 } 9 // JavaScript does not distinguish between

    10 // subroutines and functions.11 // When the return statement is omitted,12 // functions return undefined.13 function test_getUsedRangeAsArray() {14 var ss = SpreadsheetApp.getActiveSpreadsheet(),15 sheetName = 'Sheet1' ,16 rngValues = getUsedRangeAsArray(sheetName);17 // Print the number of rows in the range18 // The toString() call to suppress the19 // decimal point so20 // that, for example, 10.0, is reported as 1021 Logger.log((rngValues.length).toString());22 // Print the number of columns

    23 // The column count will be the same24 // for all rows so only need the first row25 Logger.log((rngValues [ 0] .length).toString());26 // Print the value in the first cell27 Logger.log(rngValues [ 0][ 0] );28 }

  • 8/9/2019 Google Spgoogle spreadsheet programming

    78/95

    Appendix A: Excel VBA And Google Apps Script Comparison 73

    Add Colours To Range In First SheetCells and their contents can be programmatically format-ted just as easily in Google Spreadsheets as in Excel.

    VBA

    1 Sub AddColorsToRange()2 Dim sh1 As Worksheet3 Dim addr As String : addr = "A4:B10"4 Set sh1 = ActiveWorkbook.Worksheets( 1)5 sh1.Range(addr).Interior.ColorIndex = 3 6 sh1.Range(addr).Font.ColorIndex = 107 End Sub

    Google Apps Script

    1 // Select a block of cells in the first sheet.2 // Use Range methods to set both the font and3 // background colors.4 function addColorsToRange() {5 var ss =

    6 SpreadsheetApp.getActiveSpreadsheet(),7 sheets = ss.getSheets(), 8 sh1 = sheets[ 0], 9 addr = ' A4: B10',

    10 rng;11 // getRange is overloaded. This method can12 // also accept row and column integers13 rng = sh1.getRange(addr);

  • 8/9/2019 Google Spgoogle spreadsheet programming

    79/95

  • 8/9/2019 Google Spgoogle spreadsheet programming

    80/95

    Appendix A: Excel VBA And Google Apps Script Comparison 75

    16 End Sub

    Google Apps Script

    1 // The Spreadsheet method getSheets() returns2 // an array.3 // The code "ss.getSheets()[0]"

    4 // returns the first sheet and is equivalent to5 // "ActiveWorkbook.Worksheets(1)" in VBA. 6 // Note that the VBA version is 1-based!7 function offsetDemo() { 8 var ss = 9 SpreadsheetApp.getActiveSpreadsheet(),

    10 sh = ss.getSheets()[ 0],11 cell = sh.getRange(' B2');12 cell .setValue('Middle');13 cell .offset( -1 , -1 ).setValue('Top Left');14 cell .offset( 0, -1 ).setValue('Left');15 cell .offset( 1, -1 ).setValue('Bottom Left');16 cell .offset( -1 , 0).setValue('Top');17 cell .offset( 1, 0).setValue('Bottom');18 cell .offset( -1 , 1).setValue('Top Right');

    19 cell .offset( 0, 1).setValue('Right');20 cell .offset( 1, 1).setValue('Bottom Right');21 }

    Pasting and executing these code snippets in either spread-sheet application writes the location of cell B2’s neighboursrelative to its location. The Google Apps Script offset()

  • 8/9/2019 Google Spgoogle spreadsheet programming

    81/95

    Appendix A: Excel VBA And Google Apps Script Comparison 76

    method is, however, overloaded . This concept was dis-cussed in chapter 5 in relation to the Sheet getRange() method but it merits re-visiting here to show how the func-tionality of its overloaded versions can be implemented inVBA.

    VBA

    1 ' Mimicking Google Apps Script2 ' offset() method overloads.3 Public Sub OffsetOverloadDemo()4 Dim sh As Worksheet5 Dim cell As Range 6 Dim offsetRng2 As Range7 Dim offsetRng3 As Range 8 Set sh = ActiveWorkbook.Worksheets( 1) 9 Set cell = sh.Range( "A1" )

    10 ' Offset returns a Range so Offset11 ' can be called again12 ' on the returned Range from13 ' first Offset call.14 Set offsetRng2 = Range(cell.Offset( 1, 4), _

    15 cell.Offset( 1, 4).Offset( 1, 0\16 ))17 Set offsetRng3 = Range(cell.Offset( 10 , 4), _18 cell.Offset( 10 , 4).Offset( 3, \19 4))20 Debug.Print offsetRng2.Address21 Debug.Print offsetRng3.Address

  • 8/9/2019 Google Spgoogle spreadsheet programming

    82/95

    Appendix A: Excel VBA And Google Apps Script Comparison 77

    22 End Sub

    Google Apps Script

    1 // Demonstrating overloaded versions of offset()2 // Output:3 // Address of offset() overload 24 // (rowOffset, columnOffset, numRows) is: E2:E35 // Address of offset() overload 3 (rowOffset, 6 // columnOffset, numRows, numColumns)7 // is: E11:I14 8 function offsetOverloadDemo() { 9 var ss =

    10 SpreadsheetApp.getActiveSpreadsheet(),11 sh = ss.getSheets()[ 0],

    12 cell = sh.getRange(' A1'),13 offsetRng2 = cell .offset( 1, 4, 2),14 offsetRng3 = cell .offset( 10 , 4, 4, 5);15 Logger.log('Address of offset() overload 2 ' +16 '(rowOffset, columnOffset, numRows) is: \17 '18 + offsetRng2.getA1Notation());

    19 Logger.log('Address of offset() overload 3 ' +20 '(rowOffset, columnOffset, numRows, ' +21 'numColumns) is: '22 + offsetRng3.getA1Notation());23 }

    While the VBA version defines the same ranges as theGoogle Apps Script version, it is not exactly clear. The

  • 8/9/2019 Google Spgoogle spreadsheet programming

    83/95

    Appendix A: Excel VBA And Google Apps Script Comparison 78

    key point to realise is that the VBA Range Offset propertyreturns another Range so there is no reason why Offset cannot be invoked again on this returned Range . However,code like this VBA example should be avoided wherepossible and, if it cannot be avoided, it had better be wellcommented and documented! It was given here purely fordemonstration purposes.

    Named Ranges

    The advantages of using named ranges were outlined inchapter 5. Google Apps Script provides Spreadsheet meth-ods for setting named ranges and for retrieving the Range objects that the names refer to, see chapter 5 for a full

    discussion. However, there does not appear to be a way toimplement the following VBA functionality.

    VBA

    1 Public Sub PrintRangeNames()2 Dim namedRng As Name3 For Each namedRng In ActiveWorkbook.Names4 Debug.Print "The name of the range is: " & _5 namedRng.Name & _ 6 " It refers to this address: " & _7 namedRng.RefersTo 8 Next namedRng 9 End Sub

  • 8/9/2019 Google Spgoogle spreadsheet programming

    84/95

    Appendix A: Excel VBA And Google Apps Script Comparison 79

    This VBA code prints details for all named ranges in theactive Excel file. This functionality can be very useful butat the time of writing, I was