Help your cat with his fitness goals using a custom function in a Google Sheet
By: Yeti Detective
Tags: Google Sheets, Cats

This story begins with a chumby buddy named Charles Chakita, The Fashion Cat.

The Man Himself

This ends up at spreadsheets very quickly. Trust me. I’m a nerd.

Charles weighs almost 15 pounds (6.8 kilos if you’re free from The Empire’s standard units). His veterinarian wants him down to 11 pounds/5 kilos. UGH! FINE!

So I started restricting his diet, which he does not love, and I started tracking his weight each morning, which he tolerates because it means he’s about to get his crunchy breakfast. How am I tracking this data? Well, as stated, I am a nerd, so I’m tracking it on a spreadsheet.

Computers should do arithmetic. Humans should pet cats.

The first two data points are fairly obvious. They just come from a scale and a calendar. The third data point isn’t that hard to figure out either, but the way I obtain it will give you a special insight into exactly the kind of nerd I am.

(Hint: not the kind who is too proud to end the previous sentence with a preposition.)

I could have just done the calculation “by hand” every day. It would only take a few seconds to sum column A, divide it by the count of items and then type that number into column C. However, the kind of nerd I am is Computer. That means that when I see an opportunity to spend several minutes one time to save myself a few seconds every day, I pounce on it like a Charles.

The real problem I want to solve is for each cell in column C to contain the average of the values in column A where its adjacent date in column B is equal to or less than the column C cell’s own adjacent date. Can this be accomplished with native spreadsheet functions? Probably, if I want to nest a bunch of IF statements and VLOOKUPs, which I do NOT. Can I compose a function that solves the problem I stated? Yes, because any problem you can state in language can be solved with code WHEN YOU’RE A NERD! 🤓💻💪

So, how do you write your own function in a Google spreadsheet?

It turns out it’s easy. Open your spreadsheet, click the Tools menu, and select `Script editor`

This will open a tab with some kind of code editor and some example code that looks like this:

That yellow message is telling us we are going to write some code for the Apps Script runtime (a runtime is just a program that executes the code you write) which is powered by Chrome V8. Our nerd instincts tell us that Chrome V8 executes JavaScript. That example code looks like JavasScript. Could we be writing JavaScript here? Let’s not assume.

You can click around in the help menu, or just Google it (or use Duck Duck Go if you care about your privacy) until you find the documentation for what we’re trying to do. We can see from here that we’re writing JavaScript. Wonderful. Everyone knows JavaScript, and if you don’t know JavaScript, you can go to Mozilla’s page and learn how to do what you want pretty easily.

The documentation we found tells us that the script we are making is only scoped to one spreadsheet, so feel free to name your Untitled Project the same thing you named your spreadsheet.

Writing the function

The answer to our question, “What is the average value from column A on the date in column B,” is going to be different for each date in column B, so we know we want a date input. The documentation suggests that we can get the values from a sheet using the Apps Script API, but we’re responsible programmers who use functional programming principles when we can, so the data from columns A and B will also be an input to our function.

An input range looks like an N-dimensional JavaScript Array where N is the number of columns in the range. Which means this:

The “A:B” argument at the top of that image says “Everything in columns A and B”, which you can visualize as [ [ 14.6, 12/7/2020 ], [ 14.6, 12/8/2020 ], ...[ 14.2, 12/20/2020] ]

If the argument had been “A:C” (everything in columns A, B, and C) then the inner square brackets would each include 3 values. If the argument had been “A:A” (everything in column A) then there would not be inner square brackets at all. Only [ 14.6, 14.6, …14.2 ]

You might have figured out from my screenshot that I named my custom function, AVERAGE_ON_DAY . I only used all caps because spreadsheet functions are traditionally in all caps. It is a choice, not a requirement. Let’s look at the code.

So you should be able to see that I am looping through the data from columns A:B on line 4. On line 5 I am checking if the date from the range is less than or equal to the date we are passing on each cell of column C. On the next two lines I am accumulating the sum of the values that pass the check, and incrementing a counter. Then on line 10 I am doing a fancy move to return the result of the sum over the count unless the count is still 0 (don’t divide by 0) in which case we just return the 0.

Cool, but it doesn’t do the neat-o “autocomplete” thing that all the built-in functions do on the spreadsheet.

That bothered me too. Don’t you love this?

If you want your custom function to share this feature (you do) it is as simple as ABC: Always Be Cwritingdocstrings

Learn to write a JSDoc string.

Here is what mine looks like (lines 1–10):

And here is what my autocomplete looks like now:

And now we all have the power of Custom Functions in Google Sheets! Thanks to Charles Chakita, the Fashion Cat who says he could not have done it without the support of his loving mother.