Skip to content

Instantly share code, notes, and snippets.

@brainysmurf
Last active September 24, 2023 11:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brainysmurf/4f0c5943e1963e1668e13f2e3c64aab2 to your computer and use it in GitHub Desktop.
Save brainysmurf/4f0c5943e1963e1668e13f2e3c64aab2 to your computer and use it in GitHub Desktop.
Learning V8 by re-solving old problems

Learning V8 by re-solving old problems

Here, I'll document some code I found to be much easier or better to do in an appscripts context with modern Javascript.

Breaking A1Notation into constituent parts

You have a string that represents a range speciation using a1Notation. You need to get the starting row number. Or you need to get the last column. Or you need to get all of those things. You'd like to do it in a way that can be reused. And you wonder if some of the new syntax features makes this interesting.

Let's go over the skeleton of the function first:

function rangeBreak (range) {
  const [sheet, cells] = range.split('!');
  const regexp = /(^[A-Z]+)|([0-9]+$)/g;
  ...
  return [sheet, row1, col1, row2, col2];
}

We're going to return an array of all the things broken up, and at the start we see how it's going to be split up. In our example we'll use value "Sheet!A1:A10" for range.

Take the range.split('!') line. Since we know that the string will definitely have an exclamation mark and will demarcate the sheet name from the rest of it, we'll do that first. We make two variables, sheet and cells, which in our example will have the values "Sheet" and "A1:A10", respectively.

What's going on with this regular expression? It's going to be used to divide cells into its parts, so let's take a look at it: /(^[A-Z]+)|([0-9]+$)/g.

But didn't I get ahead of myself? Don't we have to split the cells by the ":" first? Yeah, but you know what, not all ranges will necessarily have a colon in there, so we'll pin that for the moment.

Back to the regular expression. It'll define how we can split between the "A" and "1" of a range like "A1". It relies on the fact that an a1 notation always begins ^ with at least one or more + of some capital alpha characters [A-Z], and ends with at least one + numeric digits [0-9] and the end of the string $. The | means "altercation" which I don't think is actually an "OR" operation (as is usually explained it to be), but will ensure that instead of getting one big match, we get two.

That was a dense paragraph! If you need help with learning and unpacking regular expressions, I find tools like Regexr invaluable. If you don't need such tools, what are you doing messing with Javascript shoudn't you be flexing your super human ability in some other more productive way?

Okay, so we're going to use that fabulous regular expression to divide the cells, so let's finally get to the middle part of the code:

function rangeBreak (range) {
  ...
  const [first, second] = (_ => {
    if (!cells.includes(':')) return [cells, ''];
    return cells.split(':');    
  })();
  
  let match = first.match(regexp);
  const [col1, row1] = match;
  
  match = second.length === 0 ? [null, null] : second.match(regexp);
  const [col2, row2] = match
  return [sheet, row1, col1, row2, col2];
}

We want to make two variables first and second and fill them in with the stuff between the ":". But not all ranges have a colon! So the mini-function inside the body does a different thing depending on whether a ":" is present or not.

(The String.includes is a far better than using String.indexOf don't you think!?)

See [first, second], where I define variable values depending on the return values of a function inline like that? I use an an anonymous function call to determine whether or not second should be empty string or not. To me, this pattern works, as long as the body of the function is short and sweet, and readable.

So then I take first and use the regular expression above to split it into column and row values, A and 1, respectively. Repeat the process for second, but wait! I have to account for the case where second is an empty string. So I use an if statement in the form of ternary operator to unpack that the right way.

Finally, I return the values in the order I wish to, and voila.

Turning an array of values into an object with headers as keys

This method will use classes to make this. To be written.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment