Duplicate Filter Views in Selected Google Sheet Tabs with Google Apps Script

Last Updated on 2022-08-19 by Yagi

While there is not way to directly duplicate Filter Views into other sheet tabs in Google Sheets we can do this with a little bit of Google Apps Script magic.

In this tutorial, we will walk through how to duplicate all filter views from a source Google Sheets tab and duplicate them into selected sheets tab.

We’ll start off with an example sheet to better understand what we are going to achieve and then share the code along with a quick-use guide for those of you who want to to just get in and use the script in your own project.

Next we will provide a video tutorial walking through how I built the script and wrap everything up with some bonus scripts to extract different parts of the code. If you get to this stage you should have a better understanding on how to work with Filter Views programmatically.

Let’s dive in!

The Example Google Sheet

The best way of following how the code works is with an example.

In our example sheet we have 6 different stores in six different Google Sheets tabs. Each store contains the same headers; Date, Company, Name, Notes, Type/Specialty, Quoted, Actual.

We also have a NOTES sheet tab that provides instructions for the sheet.

If you want to play along, you can grab the example sheet from the link below:

Duplicate Filter View – Google Sheet Starter

Aim

We want to create a set of matching Filter Views for each of our stores without having to manually duplicate each one by hand in the sheet tab.

We have five filter views that we want to include in each of our company sheet tabs.

List of filter views in a Google Sheet tab

Of course, we don’t want to add filter views to our NOTES sheet tab.

The Problem

While we can create individual filter views inside a tab, we can’t migrate those filter views over to existing sheet tabs. So the only Google Sheets alternative is to manually update each sheet tab with our list of filter views that we want to add.

Another problem then arises when we need to make a modification to one or more of our filter views. All tabs have to be then modified by hand, increasing the chance of mistakes and significantly increase a big old case of boring.

Imagine if you had 50 different sheet tabs for 50 different businesses. That would be a nightmare to create and update.

The Solution

We will only create and update filter views in our first business sheet tab that we have called ‘MAIN’ in our example. Then we will use some Google Apps Script to update all the other business sheet tabs with the filter views.

One thing that is important to keep in mind when the script is being built is to ensure that the filter view length changes for each sheet tab to accommodate the length of rows in each business sheet tab as they change.

If we need to make adjustments to our filter views and then update all business sheet tabs, we will first need to remove the existing filter views in all but the origin sheet tab that have the same name as the origin filter views (for us, “MAIN” tab views) before updating them. Otherwise we will generate an increasingly long list of filter views that all have the same view name.

Also, we probably don’t want other users to be able to ‘accidentally’ edit our Apps Script Code for the Google Sheet, so we will store the scrip unbound in a separate Apps Script file.

Here’s the code.

The Duplicate Filter Views Code

To keep things neat and tidy we will keep our duplicate filter view code in a new Google Script (*.gs) file. In our main Code.gs file I’ll add some sample code to add in all of our information needed to run the script.

Keep in mind that you could call the duplicate filter views script on its own like I have below or part of a larger process in your own project.

For your own project, you will need to create the duplicateFilterViews.gs file and copy and paste in the script. Optionally you can add the Code.gs file to run the script like I have or build your own.

Note! Unless your Google Sheets project is exclusively for you or a highly trusted team, I would recommend creating a separate Google Apps Script Project. 

Code.gs

Quick Use Guide

Add the Google Sheets Advance Service

You will need to access the Advanced Google Sheets Service for Apps Script before continuing. To do this select the Add a service plus button from the Services menu then scroll through the list of services until you find the Google Sheets serivce. Select it and click Add.

selecting Google Sheets Advance Services in Google Apps Script

Setting up your reference data

The runsies_duplicateFilterView() function for our example contains all of the data we need to run our script.

We first list all of our variables:

  • ssID (string) – The Spreadsheet ID for the Google Sheet you are working on found in the URL of the document.

    URL for duplicate filter views Google Sheet
    click to Expand!
  • sourceSheetName (string) – The name of the Google Sheet tab that contains the Filter Views that you want to duplicate. For our example this is the “MAIN” sheet tab.
    Main source Sheet tab for duplicate filter views Google Sheet
  • destinationTabList (Object) – this Object contains two properties:
    • areExcludedTabs (boolean) – Are you providing a list of all sheet tabs you want to exclude from duplicating the filter views? If so, mark true. This is probably the most common case. Otherwise mark it false if you are providing a list of all sheet tabs that you want to include. If so, mark false.
      We chose true in our example so we only have to add one item (excluding the ‘NOTES’ tab)…cause we lazy.
    • tabNames (array) – An array of all the sheet tab included or excluded depending on your choice in areExcludedTabs. Don’t add the source sheet tab to this list.
      • E.g. of included list:["Sheet 2", "Sheet 3", "Sheet 4", "Sheet 5", "Sheet 6"]
        Inclusion destination Sheet tabs for duplicate filter views Google Sheet
      • E.g. of excluded list: ["Notes"]

Finally we run the duplicateFilterViews(ssID, sourceSheetName, destinationTabList). Note that we have included the three constant variables as our arguments for the function.

Paste in the duplicateFilterViews.gs code and run

After you have updated your Code.gs file and added the script to your newly created duplicateFilterView.gs file (script below). Save the file and select run from the menu bar.

Once the script has run, you can check our Google Sheet tabs to see that all filter views have been duplicated successfully.

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro.

Got a more specific problem you need help with, but don’t have the time to develop the skills? Make an enquiry on my 'Hire me!' page. I occasionally pick up projects. Alternatively, Fiverr’s your best bet to find a skilled Google Apps Script developer to solve your problem quickly and professionally. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

duplicateFilterViews.gs

Copy and paste the script below into your own project. I recommend adding it to a separate duplicateFilterViews.gs file for easier management.

Using the Google Sheets Advanced Service for Filter Views

We need to approach the Google Sheets Advance Service API quite differently to how we use the SpreadsheetApp class. The advance service requires us to retrieve and update an object or array-object to carry out our processes.

This means that we need to test the object directory path so we can see where locations are for us to find or update what we need. I’ve left this testing phase out of this tutorial, but this is something you will need to do.

For our project we need to use the Sheet.Spreadsheet resource. From here we will either get our Filter View data for the spreadsheet or send a batch update to make bulk changes to the sheet.

Get our Filter View Data

We retrieve our list of all filter views only one time in our getAllFilterViews() function.

Now we can simply get a list of all the date in the entire spreadsheet by using the get method and apply the selected spreadsheet ID like this:

Sheets.Spreadsheets.get(ssID)

Get just filter view field data

However, this is pretty wasteful and generates a bulky data set. Instead we can narrow in on the spreadsheets list of filter views by adding some some optional arguments to our get request.

Here, we use the “fields” property to tell the API what fields that we only want to retrieve. For us, this is our filter views. Our filter views are applied to each of the sheets in our spreadsheet so we must create the path “sheets/filterViews”. Our code then looks like this:

This will return our data containing all the filter views.

Once retrieved we can follow the property tree or iterate through the sheets, and filter view arrays. In the code above we immediately reduce our data down to just the array of all of our sheets.

Batch update our Filter View Data

We update our filter view data on two occasions in our script. First when we delete all the duplicates in our destination sheet tabs and then to add our new duplicate filter data to our destination sheet tabs.

To do this we use the batchUpdate method. This method takes two parameters:

  1. The resource containing the requests from us to update the filter views on the spreadsheet.
    1. requests – this is our list of requests to update our data. It will contain an array of objects where each object contains the data that we wish to update.
      1. Instruction – Each update object starts off with an instruction that is known as a ‘request’. You can find a list of all available requests here.
  2. The spreadsheet ID.

Delete a filter view

To delete a filter view we use the deleteFilterView request. This requests is pretty simple all it requires is for us to provide the filter id of the item we want to delete. You can see it in use in lines 133-136 of the DuplicateFilterView.gs file code above.

Add a Filter View

Adding a filter view is much more complicated. Well… it would be if we were not just using an existing filter view and making a few modifications to it.

To add a filter view we use the the addFilterView request. This requests sets the filter and then an object containing all the data we need to build the object.

{ 'addFilterView': { filter: Object of filter view data } }

You can see how we added this on line 175 of our duplicateFilterViews.gs file.

For our tutorial we didn’t need to build the view in its entirety, we just needed to:

  • remove the existing id of the view (You shouldn’t have one, because it will be added for you)
  • update the range > sheet ID to the new destination id
  • update the end row to match the current depth of the data in the destination sheet

Lines 177-187 of DuplicateFilterView.gs

The Video Tutorial

Here’s the link to the Starter Sheet for you to follow along:

Duplicate Filter View – Google Sheet Starter

 

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

Bonus Functions

Maybe you only want to get a list of all of your filter views in a spreadsheet or all the filter views for a selected sheet tab. Perhaps you just want to delete all the non-source tab filter views you created.

Check out the following three functions to give you some ideas on how you might use the duplicateFilterViews.gs file to achieve this.

I have appended each function name with runsies_ but you can rename and rebuild them how you want.

If you have been playing along, you can add them to the Code.gs file to run them.

runsies_showAllFilterViews()

This function takes your spreadsheet ID and runs the showAllFilterViews() function. The function returns a full list of all the filter views in all of your sheet tabs for your selected Google Sheet spreadsheet.

We then log the results, but you may wish to use them in other ways.

Keep in mind that the results will most likely be larger than what the console will contain, but logging the result will give you a good idea on how the Array of filter view objects for each tab is stored.

runsies_selectedSheetFilterViews()

This function gets all the filter views from all sheets and then returns just the data for the selected source sheet. In our case, this in ‘MAIN’, but you can change this to what ever sheet tab you are looking for.

The results are then logged. The filterViews property will give you an array of all of the views in the selected tab.

runsies_deleteAllCopiedFilterViews()

If you no longer wish to have the duplicates of the source filter views in your destination sheet tabs, you can use this function to remove them.

You should put in all the same arguments in this function that you had for your runsies_duplicateFilterViews() function.

 

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

Happy Coding!

 

~Yagi

 

Adding Links to Images and Buttons in Google Sheets

Last Updated on 2022-08-10 by Yagi

Have you ever tried to add a link or URL to an image in Google Sheets only to discover it is deleted and replaced by just the URL? It’s a pain.

In this tutorial, we will cover a few simple approaches to adding links to images in Google Sheets.

First, we will cover an approach using formulas and then we will use a sneaky approach using a bit of cell and image manipulation.

If you have come to this tutorial looking for a Google Apps Script solution, well… 1) I would discourage it, but 2) if you really must, check out the link to this tutorial for a hacky workaround.

On with the show!

The Formula Approach

In this example, we will use the IMAGE and HYPERLINK Google Sheets functions.

If you want to play along here is a link to the Starter Google Sheet:

Addling links to images in Google Sheets – Starter

(Select both the image and the Google Sheet, right-click and select ‘Make a copy’)

The basic pattern is as follows:

=HYPERLINK("URL - Link",IMAGE("URL to your image"))

Working from the inside out, the IMAGE function requires a link to the image that is being used. There are a number of ways of getting this link that I will cover in a  moment.

The HYPERLINK Google Sheets function takes the destination link as its first argument and then and then a link label as its second argument. Generally, this argument is text, but we can coerce this label into an image by replacing it with our IMAGE function.

But how do we get the image URL?

Image from an external website

If you store your images on a personal website or from some online photo hosting sites you can get the link to the image.

In the example below, I have a link from my website to my image. I want to use that image as my URL label. This is what my image link would look like:

=HYPERLINK("https://yagisanatode.com",IMAGE("https://yagisanatode.com/wp-content/uploads/2022/05/yagisanatodeSiteBanner_titleOnly-500-width.jpg"))

This will result in this image link:

Adding a link to an image in Google Sheets_image url is external
Click to Expand!

Image from Google Drive

Unfortunately, we can’t just go to Insert > Image > Insert image in cell for this. Nor can we go to our Google drive, select the image share it and get the URL from the share.

It won’t work.

There are a couple of workarounds for this, but probably the easiest approach is to open the image in a drawing.

Here is how we do it:

    1. Navigate to the Google Drive folder where your image is saved.
    2. In a blank space in the folder right-click > More… > Google Drawings

      Creating a Google Drawing File in Google Drive
      Click to Expand!
    3. Inside Google Drawings select Insert > Image > Drive.
      Insert an image into Google Drawings
    4. A sidebar will appear. Navigate to your image and double-click it. It will load into your drawing.
      Insert an image into Google Drawings select from drive
    5. Holding the left mouse button down, drag the image up to the top-left corner of the drawing.
    6. You will notice a checkered grey and white area in the background, this is the page area. We want the page area to be equal to the image. In the bottom right of the page area, there is a little move triangle-shaped button click and drag it up to match the size of the image.

      Resizing the Google Drawing page
      Click to expand
    7. In the top right of the Drawing app, rename it by clicking on the top-left text where it says “Untitled”. Make sure it is something meaningful for your task.
    8. Now we get the URL for the image. Select File > Publish to the web. 
    9. A dialogue box will appear. Make sure Link is selected, choose your preferred size and then select Publish.
      Google Drawing Publish to the web as a link
    10. You will get an alert that comes down from the top of the page making sure you want to publish this image. Select Ok.
    11. You will now have a Google Drawing URL. Hit Ctrl + C  (⌘ + C) to copy it.
    12. Head back to your Google Sheet and insert it into IMAGE function. It should look similar to this:

=HYPERLINK("https://yagisanatode.com",IMAGE("https://docs.google.com/drawings/d/e/2PACX-1vR2MqTAC_SBvvoWlAwLL_Pk5gHbLzOb0CJAOvbxitdNvstsX477fX8xRqvvQDOohuF83Ie4UQS4AQvk/pub?w=502&h=503"))

Adding a link to an image in Google Sheets_Google Drawing URL

You can also do the same thing with custom drawings and buttons using Google Drawing. Check out the video below for a demonstration of this.

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

The video

The sneaky approach to adding  Links to images.

Another approach to adding links to images in Google Sheets that you may want to consider is to add a URL to a cell that you want to use for your image and then insert an image over cells. Then move that image so that it fits inside the cell with the URL.

When a user clicks or hovers over the cell and image the link will appear.

Here are the detailed steps:

  1. Select a cell. If you want something larger, you may have to merge cells together to make it just right.
  2. Add your URL to the selected cell.
  3. Change the text colour of the cell to match the background colour. This will hide the URL just in case you didn’t fit your image in perfectly.
    Adding a link to a cell in google sheets
  4. Now go to Insert > Image > Insert image in cell
    Insert image over cells in Google Sheets
  5. Select your image from your desired location.
  6. One the image appears in the Sheet, move the image to the cell with the link and resize it so that it fits just inside the cell. Note! You should leave a tiny bit of space from the edges of the cell so that the URL is picked up.

The end result should look a little like this:

Sneaky image with URL in Google Sheets

That’s all there is to it.

The Video

Did you enjoy the tutorial? Want to upskill and get a solid step-by-step course to become a pro at Google Sheets? Check out my course, Google Sheets: Learn the Essentials with Three Detailed Projects. Sign up today.

 
Google Sheets Shortcuts Mousepad
Google Sheets Shortcuts Mousepad
Want a fast track to boost your Spreadsheet efficiency? Grab one of these handy Google Sheets Shortcuts mousepads that I created from my store.
Google Sheets Shortcuts Mousepad Gel
Google Sheets Shortcuts Mousepad Ge

~Yagi

Creating Links from Custom Menus and Buttons in Google Sheets with Google Apps Script

Last Updated on 2022-08-10 by Yagi

This article should have been titled “Creating Links from Custom Menus and Buttons in Google Sheets with Google Apps Script: And Why it’s probably not a good idea”, but you know, I got to appease the SEO gods.

There is no natural or “out-of-the-box” way to create hyperlinks for custom menu items and buttons in Google Sheets. The solution I am providing below is a somewhat hacky approach, that I am not fond of and I will suggest some better alternatives in my summary.

However, there are a few occasions where you may feel forced into a corner as a developer to provide direct links from custom menus, buttons and images in Google Sheets. With this in mind, let’s get cracking.

The Example and Starter Sheet

In the example, I will provide custom links to my homepage and YouTube channel via a custom menu. I will also add an image link and button (Drawing) link.

Adding links to buttons drawings and menu items in Google Sheets with Google Apps Script

You can find a link to the starter sheet below:

The Starter Sheet

The Code

To attempt to transform a menu item or button into a link we use a Google Apps Script modal dialogue box as an intermediary. We can use HTML, JavaScript and CSS in these dialogues in the same way we would in a website.

This means that we can run the JavaScript window.open() command globally as soon as the dialogue opens which will open the link in a new tab (On most occasions) IF the user has given permission to unblock pop-ups for Google Sheets in their browser.

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

onOpen()

The onOpen() function is a built-in simple trigger in Google Apps Script that can run scripts when the Google Sheet (Or Google Doc, Slide or Form) opens.

In our example, we are using onOpen() to create our custom menu “Links”. We do this by using the SpreadsheetApp class’ getUi() instance class that allows us to build on the existing user interface. The UI class contains the Google Apps Script createMenu() builder which has its own set of methods to construct a custom menu.  The builder takes a menu name as an argument, which we have defined as “Links”.

We then use the addItem() method to build two sub-menus, ‘Yagisanatode.com’ and ‘YouTube’. This method takes a title that will appear in the menu and a function name that will be executed when the menu item is clicked.

The menu then needs to be built using the addToUi() method.

You can get a better understanding of menus in this beginner’s tutorial.

openYagi() openYT()

 

Each sub-menu directs to its own function. Both of these functions are identical and simply add the relevant URL for each button and then calls the openUrl() function.

These functions also have a secondary purpose for us. We can attach these function names to each of our buttons.

You can change out these functions to your own URL and names, just make sure you update the addItem methods in the create menu builder.

You can learn a lot more about how to run script from buttons, diagrams and images in Google Sheets with Apps Script in this tutorial:

Google Apps Script: How to Connect a Button to a Function in Google Sheets [Updated 08 Apr 2022]

However, the basics are:

  1. Right-click the image.
  2. Select the vertical ellipses from the top right of the image.
  3. Select ‘Assign Script’.
  4. Paste in your function (without the braces () ).
  5. Select ‘Ok’.

openUrl(url)

The openUrl() function contains the selected URL as a parameter.

The is the function that gets all of our work done.

blob(The HTML)

blob gif for the chapter on html blob content for dialog boxes in apps script

Our blob text is basically our HTML page that will make up our modal dialogue box. The constant variable blob looks like this:

Keep in mind that the above HTML is encapsulated in template literals (backticks (`)).

I’ve set the stylesheet to use Google’s recommend CSS package for Add-on, sidebars and dialogues for ease and consistency. Line 5

The Script tags

Let’s skip the div for now and head down to the content in the script tags. Lines 16-25

First, we set a variable named, urlLinked to window.open("${url}"). This is a JavaScript DOM method that opens a URL when called. In our case, we have added our selected URL as a template literal tag. Line 18

If the URL is able to be opened in a new tab urlLinked will return an object or for our purpose a “truthy’ result so we know everything worked and we can close the dialogue automatically with google.script.host.close()Lines 19-20

If the URL could not be opened in a new tab (likely a result of your browser’s pop-up blocker) then urlLinked will return nullWe then need to select our HTML div with an id of “blocked” and unhide it. Line 21-22

The “blocked” div

Our “blocked” HTML div is unhidden when the browser prevents the script from automatically opening the new window.

The first thing we need to do is give the user a link to the URL they were looking for. You will notice that we use window.open() again instead of the URL directly. This is because dialogues and sidebars in Google Sheets are embedded iframes. You can learn more about this here:

Using Hyperlinks in Dialogs and Sidebars to open a URL in a new Tab with Google Apps Script

Next, we provide a message explaining what is going on and how they might want to fix it in future.

Finally, we provide a close button for them to exit from the dialogue box should they have an aversion to clicking the “x” in the top right of the box.

Backup dialog box if url did not automatically open google apps script

Why directly linking from Menu items images and buttons is not a great approach.

The user still needs to authorise the script

This might be fine if you have some links say to an external help page as a part of a larger project, but it is probably not a sound idea to create a simple project that just produces links from menus or buttons. The user is already going to be annoyed that they have to go through the Google Apps Script permission process.

Perhaps if you are publishing an add-on this might be okay, because the permission process is a lot smoother.

It doesn’t always work

As you can see in the script above, we have included a failsafe if a pop-up blocker is enabled. More often than not this will be the result of running the script unless the user specifically unblocks popups in their browser for Google Sheets.

It’s hacky – Google is probably not amused

There are always a few bugs and better implementations that arise in large software projects like Google Sheets. However, in this case, I get the feeling that Google has a very good reason for you to not directly link from menu bars and buttons in this way.

If you disagree:

  1. Let me know in the comments below. It’s always good to get alternate perspectives.
  2. You could always make a feature request on Google’s Issue Tracker (feel free to link your issue in the comments below).

Workarounds and alternatives

Simulated mouse clicking

simulated mouse clicking in demolition man
Simulated mouse event first seen in Demolition Man

There is a clever bit of code by Stephen M Harris that used the same modal dialogue event but first sets a timeout on the dialogue to close. The script then generates an anchor element followed by a scripted mouse click event which is a common workaround to prevent pop-up blockers from running.

Stephen also handles for Firefox’s idiosyncracies with his script too.

Personally, I think this is a little too forced for my liking, but many devs would disagree and I have seen a number of Google Workspace Marketplace apps using Stephen’s code. So, what do I know? 🤷‍♂️

You can find a link to the solution here on StackOverflow. If anything, give him some upvote love for the clever workaround.

External link dialogue warning

As you’ve traversed the Internet, have you ever seen a dialogue that warns you that you are about to navigate to an external link?

Yeah, this is one extra step for the user and that is a definite downside, but I also think that it better conforms with how Google intended links to be accessed from the UI.

This alternative is probably better suited to menu items rather than buttons and images.

Let’s go ahead and update the blob constant variable.

External link warning dialog Google Apps Script

Add a links page as a dialogue or sidebar

Another really useful approach is to create a separate links page as a dialogue or sidebar. This keeps all of your links in one location and out of your main document.

This is probably my main go-to and my clients tend to learn quickly how to get to these links to find resources and more instructions that complement the document or sheet that they are working in.

You can see some examples of this in this tutorial:

Using Hyperlinks in Dialogs and Sidebars to open a URL in a new Tab with Google Apps Script

Add a links sheet tab

If you are working in Google Sheets and you want to get something out quickly, why not just make a “Links” sheet tab for users to access? You can always protect the sheet tab, users will still be able to access the link without editing the page.

Button and Images can be linked without code

In a previous tutorial, I cover a few approaches on how to apply hyperlinks to images in cells in Google Sheets. This way when the user hovers over the link, they will see the link (with preview) that they can click on.

Adding links to images in Google Sheets

Conclusion

Well, this was probably not the satisfying answer you were, hoping for, sorry. But we have covered a number of ways for you to provide links to users from the somewhat ethically dubious to some good alternatives.

I would love to hear what your solutions were in the comments below and how you went about implementing them. Not only does it interest me, but others may find your perspectives and use cases helpful for your own projects.

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro.

Got a more specific problem you need help with, but don’t have the time to develop the skills? Make an enquiry on my 'Hire me!' page. I occasionally pick up projects. Alternatively, Fiverr’s your best bet to find a skilled Google Apps Script developer to solve your problem quickly and professionally. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

~Yagi

Find the item with the highest order of importance and store it with JavaScript

Last Updated on 2022-08-02 by Yagi

I recently came across (yet another) situation where I needed to work with a text-based ranking system. You know, when some gem decided to create a ranking system like good, great, awesome, spectacular and then we need to store each user’s highest level of achievement over a period.

This occurs with surprising regularity in my work, most often when needing to work with spreadsheet data that a user has created. We can’t really change the data on the spreadsheet so we need to handle this with some code instead.

Not ideal, I know. We could complain about it ad nauseam or simply live with it and deal with it using some JavaScript magic.

In this tutorial, we will cover two approaches to this. Both approaches have their own uses. We will go over a few use cases so you get an idea of when these sorts of things come up.

Let’s get cracking.

Note: Sometimes it takes a couple of examples to figure out a concept. Other times, you can figure it out in an instant. Feel free to read as much as you need to understand the concept. 

 

Storing the most important text value with JavaScript

Example 1: Recording the best poker hand

Let’s say I am having a poker night with some friends and want to only record my best hand for the night, you know, to brag later.

First, we should list all the poker hands from best to worst:

  1. Royal flush
  2. Straight flush
  3. Four of a kind
  4. Full house
  5. Flush
  6. Straight
  7. Three of a kind
  8. Two pairs
  9. Pair
  10. High Card

As the night starts, my first hand was a ‘three of a kind’. So I make a note. Then, I only get a ‘pair’ for my next hand. I’m not writing that down. It’s worse. Next, I get a ‘flush’. Awesome, a ‘flush’ is better than a ‘three of a kind’, so I will store that one and put a line through my previous record.

Do you get the picture?

Cool. Let’s write some code.

We will need to store our list of poker hands in order and also create a variable to store the best hand we get during the game. We have two choices here. I will go through both and then discuss performance.

Storing data as an array

So what’s going on?

First, we store our list of all possible poker hands in an array called ‘poker’. Starting with the lowest hand on the left and finishing with the best hand on the right (bottom of the array). Lines 1-12

Arrays in JavaScript maintain their order so we know that “High Card” will always be in position poker[0] and “Royal Flush” will be in position poker[9]. We will be using the array’s order in a minute to check if we should be storing our next hand or not.

Next, we need a place to store our highest hand for the night. We set the variable bestHand for this, using JavaScript ‘let’ variable declaration to allow us to change the variable as we update it with a better hand. Line 14

setMostImportant_Array()

We now create the function setMostImportant_Array(). This function takes 3 arguments:

  1. The array or list to reference
  2. The stored item, in our case, bestHand.
  3. The new contender item, which may or may not, be better than the stored one.

The function returns the most important item. This is done with a simple ternary operator, which is a kind of simplified ‘if’ statement.

On line 5, we compare the position of our stored bestHand value in its position in the poker array list against the new hand. We do this by using the indexOf method which returns the first occurrence of the matching item in an array as an index of that array. If the current bestHand is greater than or equal to the new hand then we return the current bestHand. Otherwise, we return the new hand.

Testing the results.

After we have set up our function we can now run it. Our second hand of the night was a ‘pair’ so we updated our best hand to our function adding in, poker as our array list, bestHand as our stored item, and “Pair” as our new item.

bestHand = setMostImportant_Array(poker, bestHand, "Pair");

Because a pair is not as important as a ‘three of a kind’ we kept the current value.

On the next hand, we got a ‘Flush’ which is more valuable than a ‘Three of a kind’ so using our function again we see that bestHand now stores the ‘Flush’ as the most important value.

Storing Data as an object

We can achieve the same outcome by storing data as an object. Let’s take a look at the code.

In our poker object, we store the names of each hand as a property string and then each property’s value is its position or order of importance in the group of data. Lines 1-12

Our setMostImportant_Object() function is a lot simpler than the array function above. Here we will use our ternary operator, but this time we simply are checking to see if the bestHand property value stored in our poker object is greater than the new hand property value. Line 14-24

Our function takes on arguments in the same way as the array function and will store the new property in the bestHand variable if the hand is better than the one stored.

Which is better? The array or object approach?

The most predictable and irritating answer first. It depends.

Running a benchmark test on the two they are fairly comparable, but over larger sets of stored ranked text, the object approach would perform better.

However, my preference would slant to the array approach if my ranking is not static. This is probably a rare case, but imagine if your text-based ranking system changes regularly and you need to update the order of you ranking system.

Moving your data around an array and cutting it out of one position and putting it in another is fairly simple with an array. With an object, however, we need to update the current value of the property that is going to change and then move all the other properties around than need to change. This would definitely be more memory intensive and harder to code.

Here is an example.

Example 2: Getting the best commodity in a fluctuating market

Imagine that we are investing in a fictional commodity market. As supply and demand fluctuate, a commodities value may move to become greater or lesser than other commodities in the same market.

Our goal in this scenario is to keep the best value commodity available to us. If the commodity’s value position compared to other commodities shifts, then we need to ensure that we always keep the best commodity available to us.

Let’s use this fictional list of commodities as our example:

  1. tryzatium << currently lowest value.
  2. ocoumbre
  3. malcatite
  4. enzome
  5. parl
  6. obvoster << currently highest value

We are first presented with the opportunity to buy ocoumbre. Having no investments in the market, we make the purchase.

Our next opportunity is to purchase tryzatium. Currently, this item is less valuable than ocoumbre so we won’t buy it.

Enzome comes up next. Being of higher value, we purchase it and sell off our ocoumbre. 

Then the next day the market changes.  A new large deposit of enzome is found and floods the market, reducing its value to below tryzatium. So when we get an offer to buy malacite we jump at it.

Let’s write some simple code to simulate this.

storing data in a fluctuating ranking system

The results of which should appear like this:

Just like in the first example, when a better commodity is presented to us we replace it with our current commodity. When there is a change to the order of the market, then we also see a change in how we prioritise what we keep.

moveItem()

The moveItem() function allows us to change the order of priority of our list of commodities.

The function takes 3 arguments as parameters:

  1. list – the array of ordered items. In the example, this is our commoditiyByVal array.
  2. item – This is the item in the list that needs to change position.
  3. newIdx – The new index or place in the list that the item needs to move to.

In the first task of the function, we need to get the current index of the item. We do this by finding its index in the array with the indexOf method. Line 8

Next, we use the JavaScript splice method to cut the item out of the array (The inner splice) and then add it back into the array at the desired location (The outer splice). Line 9

The outer splice takes 3 arguments:

splice(start index, deleteCount, item to add)

  1. start index – our new index for the position of the item.
  2. delete count – the number of items to delete. For us, this is zero. We only want to add an item.
  3. item to add – This will be the item that we splice out. Not only does splice update an existing array, but it can also return the items that have been removed as an array. This is handy for us because we will use them in this last argument. This inner splice takes two arguments:
    1. start index – the current index of our selected item.
    2. delete count – one, the current item we need to move from the existing position.

Why I recently needed to store the most important item in a list in JavaScript?

Example 3: Time Trigger (Cron Job) efficiency

So the thing that actually compelled me to write about this was a part of a Google Apps Script project – Google Apps Script is built on Google’s V8 engine for EcmaScript  JavaScript.

I was fetching requests from an external API that requested that an event be triggered at a particular interval. We use Clock Triggers in Google Apps Script but you might know them as Cron Jobs.

The API contained a list of text-based triggers that looked a little like this:

  1. “daily”,
  2. “6 hours”,
  3. “1 hour”,
  4. “30 minutes”,
  5. “1 minute”

Anyway, we have limitations and quotas to how many clock triggers we have running in one account at one time so I always try and limit these. So if I can set a daily trigger for a user I will prefer it over a 1-minute trigger so that they don’t get any quota errors or issues.

In my example, when a user requires a trigger to be set for a project at a certain interval, the code will check against the current setting of all existing triggers for the project and update the trigger accordingly.

So for example, if a user sets their first project item to run every six hours, then the trigger will only run every six hours. If they add another item that needs to be run daily then that item will be initiated every fourth time the trigger is run ( 4 x 6 = 24 hours).

However, if they create a third item that requires it to be run every 30 minutes then we need the change the frequency that the trigger is called to 30-minute intervals. This means that the first item needs to be invoked every 12th occasion the 30-minute trigger is run (6 x 2 = 12). Likewise, the daily trigger needs to be invoked every 48th time the trigger is run (24 hrs x 2).

Let’s see how this looks in the code:

The code

Conclusion

I’d love to hear if you have some examples of when you might need to handle text-based ordering systems and what approach you took. Feel free to add them in the comments below.

If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro.

Got a more specific problem you need help with, but don’t have the time to develop the skills? Make an enquiry on my 'Hire me!' page. I occasionally pick up projects. Alternatively, Fiverr’s your best bet to find a skilled Google Apps Script developer to solve your problem quickly and professionally. *

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

 

~Yagi

 

%d bloggers like this: