Get Hidden or Visible Google Sheet Tabs with Google Apps Script

Based on a viewer’s recent question, here is how you can get a list of all hidden or visible Google Sheet tabs with Google Apps Script.

You can integrate these scripts into your own projects.

The Video

Continue reading “Get Hidden or Visible Google Sheet Tabs with Google Apps Script”

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

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

 

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

If you’ve landed on this page you’re probably wondering why your hyperlinks are not working in your Google Workspace dialogue (dialog for my U.S. friends) box or sidebar.

This affects all locations where you can build a sidebar or dialogue with Google Apps Scripts, Sheets, Docs, Slides and Forms.

You might even hit F12 in your browser to inspect the code and found this dreaded error:

Unsafe attempt to initiate navigation for frame with origin ‘https://docs.google.com’ from frame with URL ‘https://n-yyi3lctp…<<fileID>>…-0lu-script.googleusercontent.com/userCodeAppPanel’. The frame attempting navigation of the top-level window is sandboxed, but the flag of ‘allow-top-navigation’ or ‘allow-top-navigation-by-user-activation’ is not set.

linking from a Google Workspace sidebar or dialog error Unsafe attempt to initiate navigation for frame

Why your Links aren’t working in your Google Workspace Dialogs and Sidebars

So what’s going on?

Dialogues and sidebars in Google Workspace are set in iframes. Essentially, this is a nested webpage on your main page. Take a look at the examples, below. I’m in Chrome here and I have selected the Developer Tools Element Selector (Ctrl + Shift + C for PC) and clicked on the Sidebar and Dialogue box respectively.

For the Sidebar.

Google Workspace Sidebars are in iframes

And for the dialogue box.

Google Workspace Dialogs are in iframes

When you create a simple HTML hyperlink in your anchor tag like this:

<a href="https://yagisanatode.com">Website</a>
You are asking the iframe to open a URL in its parent window, your Sheet, Doc, Slide or Form, and browsers generally don’t like to let you do this.

The Solution

The solution is really easy. Simply add target="_blank" to your anchor element:

<a href="https://yagisanatode.com" target="_blank">Website</a>
The target ‘_blank’  attribute will generally open the link in a new tab for most browsers. Note that a user may change their settings to open in a new window instead of a new tab.
Target ‘_blank’ implicitly adds the rel="noopener" behaviour on most browsers to prevent the destination link from tampering with the original source.

The video

Example Implementation

If you want to see an example implementation you can get your own copy of the sample Sheet with bound Apps Script from the link below:
Easter eggs, a bonus Google Sheet formula for linking images in a cell and a fun way to call object methods from a Ui method are all in the example sheet.
Once you made a copy of the Sheet, click on the ‘More’ custom menu item and select from the Sidebar or Dialogue box implementation to see it in action. You will have to Authorise the scopes the first time though.
To look at the code, go to Extensions > Apps Script.
Have fun!

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

One Approach to Encourage Users to Run Google Sheet-Bound Apps Script When They First Make a Copy of the File

I quite often get called upon by clients to create Google Sheet templates that have Google Apps Script Automations bound to them. Sometimes these Google Sheets require an automated setup process to run things like gathering initial data, setting up time triggers, approving scopes connected to onEdit() or onOpen() triggers or renaming connected forms and their contents.

One of the challenges is getting new owners of the duplicated template Google Sheet to run the bound script before they dive into working on the Google Sheet (Often, only to discover that things aren’t working how they want them to). It can be a frustrating step for both the user and the developer.

Another issue that also arises is when a user runs a script for the first time. The user will need to give permission to the scopes that will be used to run the bound script. After authorising the script to run, the script will not continue to run and will require the script to be run a second time to execute the process.

After quite a lot of trial and error, I have devised a pretty solid approach that seems to have the most success in getting users to run through the authorisation of scopes and then run the startup script.

Here are the basic steps:

  1. User makes a copy of the Google Sheet template
  2. User only sees a ‘Setup’ sheet tab containing two buttons and instructions. All other tabs are hidden for now.

    Run Script before exposing the rest of a template Google Sheet
    Click to Expand!
  3. User clicks the first button to ‘Authorise’ the script scopes.
  4. User clicks the second button to run the startup script.
  5. The ‘Setup’ tab will be deleted and all selected sheet tabs will be displayed.

The Setup Google Sheet Tab

You don’t have to reinvent the wheel. You can grab a copy of the ‘Setup’ Google Sheet tab mentioned above and insert it into your own project. I’ll explain why its features seem to make it so effective in a moment.

Alternative you can make your own version based on the discussion about its features below.

Here is the link to the sheet:

Setup Google Sheet

To add the Sheet Tab to your own Google Sheets template:

  1. Select the ‘Template Setup’ sheet tab dropdown (dropup? 🤔) menu.
  2. Select ‘Copy to’.
  3. Select ‘Existing spreadsheet’.
  4. A dialogue box will appear.
  5. Select the file you want to add the sheet tab to.
  6. Note! The Sheet tab name will have ‘Copy’ added to it in your target Google Sheet. Simply double click the sheet tab name to rename it.

Runs Script before exposing the rest of a template Google Sheet_copy setup sheet tab to another sheet

Setup Sheet Tab Features

Whether you are creating your own ‘Setup’ sheet tab or reviewing the one provided to make your own, here are some of the features that make it successful.

Runs Script before exposing the rest of a template Google Sheet_breakdown

  1. Clear title: Users might be surprised that they are not seeing the full spreadsheet they intend to work in. So a clear title explaining what is going on is a must.
  2. Brief explanation: A brief explanation that the Sheet the user made a copy of contains scripts that will need to be run before the Sheet will work as expected along with instructions that it will take two steps to complete the process.
  3. Clearly identify the steps: Both in the basic instructions and then reinforced in bold on lines 7 and 23 for step one (authorisation) and step 2 (running the script)
  4. Keep it lean and viewable without scrolling: People don’t like to read. Yeah, yeah, I know, ironic coming from the guy who writes the wordy tutorials. But when it comes to these types of tutorials keeping it lean is key. If a user has gone through this type of process before, then they don’t need a full walkthrough of what to expect and can just quickly follow the basic instructions and get on with it, but…
  5. Also, provide noob instructions: Not everyone is a pro, so it is good to provide more details. The best compromise here, I found was to add further details in a Group that is hidden with a ‘+’ button. Here is what they look like expanded.
    1. Authorisation
      Runs Script before exposing the rest of a template Google Sheet_authorisation detailed instructions

      1. Link to video tutorial: There is a link to a quick explainer video about authorising scripts for the user to come to grips with giving permissions to script scopes.
      2. Step-by-step instructions: that the user can follow to give them confidence that they are following the process correctly.
    2. Run Startup Script: This one is pretty basic and instructions seem to be enough for anyone who is met with this startup page for the first time. You could add more detailed instructions here for your specific needs.
      Runs Script before exposing the rest of a template Google Sheet_script run detailed instructions

The Code

The code for the setup page is run when the first button is clicked.

Copy and paste the runScriptBeforeReveal() function below into your project.

Rows to update

Line 7. Add your own start-up function here.  You can see my example myStarterFunction as a guide.

Line 10. Add your list of sheets to reveal. These are all the Google Sheet tabs that you want to be displayed after the startup process is complete. You could also change this to the sheets to be kept hidden and change line 27 to if(!sheetsToKeptHidden.includes(sheet.getName())){ .

Lines 14 & 15. This is the location you want to show your user once the setup is complete. Provide the sheet name and the cell location.

Line 20. Setup sheet name. If you change the setup sheet tab name to something other than the one provided in the example, please update this line.

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.

What’s going on?

Both buttons in the template setup reference the function runScriptBeforeReveal().

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

When the first button is clicked, Google Sheets will prompt the user to run through giving permission to the scopes needed to run the script. When the second button is clicked the actual script is run to complete the setup process using your setup function then:

  1. All sheets that you want to be displayed are unhidden.
  2. The setup sheet tab is deleted.
  3. The user is sent to your selected sheet at your desired cell.

But wait a second, Yagi. Aren’t both buttons referencing the same function? Can’t someone just click the first or second button to run authorisation and then click the same button again to run the script?

Yeah, yeah, I know. There is a bit of subterfuge going on here. To be honest it won’t matter what button the user clicks so long as they do it twice.

So why the two buttons? 

I tried it with one button to ask users to click it twice and then trialled it with two buttons. The success rate with two buttons was much higher. Two buttons just seem to be a better psychological tool to get the user to complete the process.

Limitations

You might have a nagging feeling that this is not going to be a 100% accurate way to ensure that the user completes authentication and runs our startup code, and you would be correct. We are still putting our trust in the hands of the user. However, in circumstances where we have templates like these that a user makes a copy of, then I have found that this is the best possible process.

Another limitation is that if users who are not the owner of the Googe Sheet need to run code, then they will still need to run the Authorisation process. In this case, they would not need to be activating startup scripts but just scripts that would help them complete their workflow in the Google Sheet. It might be a good idea here to have an ‘Instructions’ sheet tab for these users with their own button that would prompt them to run the authorisation process should it be required.

In the end, the best approach would be to transform your templates into Google Workspace Add-ons that can enforce the authorisation process and run setup code more fluidly, but that can be quite an unnecessarily daunting process.

The Video Tutorial

Conclusion

I’ve used this template without alteration on dozens of template sheets now and it seems to be the most successful. However, there is always room for improvement. How would you tweak the setup sheet tab? Do you have another alternative that you like to use? I would love to hear in the comments below.

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

How to remove a Google Sheets button (drawings) or images connected to a Google Apps Script after the script has been run

There have been a few instances in my work where I need to remove a button (more accurately, a button drawing) or and image from a Google Sheets tab once the associated script has been run.

Perhaps we just want the user to run a process on a Google Sheet workbook, just once but not more times. This would be a good case for removing the button or drawing after use.

Note: This tutorial expects that you know how to create a drawing or a button from the Google Sheets drawing tool. 

Google Apps Script: How to Connect a Button to a Function in Google Sheets

Continue reading “How to remove a Google Sheets button (drawings) or images connected to a Google Apps Script after the script has been run”

%d bloggers like this: