Want to access my latest Google Sheets course for free? Only a few coupons left to beta test my new course. Sign up now!

Want to Beta Test This Course For Free?


Click here!

Google Sheets: Learn the Essentials with 3 Detailed Projects

In this course, I want to take you on a journey from the bare-bones basics of using Google Sheets spreadsheets through to mastering the essential tools and formulas that you need to improve your efficiency in the workplace, impress your team and make your administrative life easier.

This course is about getting in there and completing real-life projects. Projects that you can take away with you and use in your own personal and business life.

If you are looking for a boring lecture-style course here, then this course isn’t for you.

The most interesting courses that I have ever taken are the ones where I can follow along and actively create something. You know, apply my skills immediately with a real context to what I am doing and the reward of accomplishing a task at the end.

I always learn the most from these courses.

In this course, we will go through 3 real-life projects that will take you from the very basics of how Google Sheets works all the way through to developing corporate-level dynamic Google Sheets for your workplace.

Not only will we cover how to use the tools, functions and formulas that Google Sheets provides, but we will look at spreadsheet design principles, workflow, develop our shortcut skills and collaborate with others.

The Projects

Budget Sheet

We will get a grasp of the basics of working in Google Sheets by creating a basic Budget. First I will show you around the Google Sheets User Interface (UI) and then dive into some of the fundamentals.

Project Management Sheet

In this project we will create a dynamic Project Management Monitoring Google Sheet, allowing your teams to track their progress and collaborate effectively with each other. We will also explore the benefits of templating data so you don’t have to reinvent the wheel each time you need to set up a project.

Gradebook Sheet

Here we dive into the academic world and create a Gradebook, specifically designed for reuse. We will explore how to analyse your dataset with dynamic dashboards. We’ll look at advanced formula construction, integrating live data from other Google Sheets, pivot tables, charts and much more.

What’s in the course

This course is a beast! You will get:

  • 45 videos covering all three projects.
  • Over 8 hours of video content.
  • Each video contains a takeaway summary of what you have covered.
  • Starting templates for each project.
  • Handy links to further reading or videos.
  • Staging templates as strategic points in the course so you can compare your progress.
  • A comments section for each video to get support.
  • Plus you will walk away with 3 reusable projects that you created.


Want to Beta Test This Course For Free?

I have 12 4 free coupons to give away for anyone interested in beta testing the course. Fill out the form if you are interested.


Why can’t I edit this Google Sheet that was shared with me??!!! 😠

You’ve probably come to this page feeling pretty frustrated that you’ve received a link to a Google Sheet, Google Slide or Google Doc in an email or found a link to one of these documents in a website or even one of my tutorials, but you just can’t edit it. You can’t update the text and even half of the menu bar is greyed out!


What’s going on?

It means that you have been given only View permissions to this document.


Generally, it’s because any changes in a Google Workspace Document, (Sheets, Slides, Docs) will be displayed for anyone who has access to the document. So if you add or delete something in a document, then other editors, commentators and people with view-only access will see the change in near real-time.

Google Sheets Beginners: Sharing your Sheet (20)

There are three main reasons why an owner of a document will provide View-only access to users:

1. It might have only been meant for you to read-only.

Maybe you get an email from another department from work with a new policy that they have. You don’t really need to make edits to this. You just need to read it, right?

If you think this might be the case, but you want to be able to access the document in your personal folder, you can go to File > Add a shortcut to Drive. This will save a short cut to the file in your own Google Drive to help you to better organise your documents.

You still won’t be able to edit the document, but you don’t need to.

Also, the owner or the editors of the documents can also make copies of the document after you have made the shortcut if they need to.

2. It might be an example document or template.

In my tutorials, I often provide links to templates or example documents. Here again, I only ever provide view access.

However, you can create your own copy of these documents easily, by going to File > Make a copy. You will then be prompted to move the copy into a desired folder in your Google Drive.  Once done, a new window will appear in your browser. You will then have your very own copy of the document that is owned by you. You can now edit it and it will not affect the original document, because they are two separate documents.

3. The owner may have forgot to make you an editor.

Maybe the owner of the document was meant to give you edit permission but may have forgot.

Now before you get too excited, there is one thing you might want to check to save yourself some embarrassment. Go up to the top of your sheet and check to see if you are using the correct account for this sheet. You can do that in the top-right corner of the document and confirm you are using the right avatar.

Perhaps the owner has given you edit permission to the document in another one of your accounts, like a work account.

If you are in the wrong account, simply change to your correct account and check to see if you have edit permission.

If you are in the correct account and you are certain you should have edit permission, then you can select the View Only button and then click Request view access. An email will be sent to the owner and they can decide if you need edit access.

Why so much build-up to this last option? Well, you can imagine that it can be a little frustrating to get a bunch of emails from people who don’t actually need edit access.

Fortunately, there is a workaround to receiving a bunch of emails requesting edit access unnecessarily. Check out the tutorial below:

How to stop getting Google document requests to edit from users outside your organisation from publicly viewable files.

Check out the video:

Did you enjoy the tutorial? Want 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


Help! My time triggers are not in sync! : How to update your Google Apps Script project time zone.

If you have made it to this post you are probably a little frustrates about why your Google Apps Script time triggers are not running on or around the times that you have designated. Of course, you could simply just be a well-oiled machine and want to know how to update the time zone of your project for your client.

To cut to the chase, the likely cause of clock triggers not running in the time range that you have selected is that the time zone in your Google Apps Script project is out.

How to check your Project’s Timezone

So, how do you check the time zone of your project?

If you need to do it programmatically you can use the Session class and the getScirptTimezone() method. Something like this will log your project’s timezone:

Alternatively, you can check out your project manifest file.

To do this in your Google Apps Script IDE, go to your sidebar and select the Project settings cog and then check the Show “appsscript.json” manifest file in editor checkbox under the general settings.

Google Apps Script manifest file
Click to Expand!

Go back to the editor and your “appscript.json” file will be visible. Select it and you will be able to see the current time zone for your project.

Google Apps Script time zone in manifest file
Click to Expand!

Changing the timezone

So, at the time of writing this, I found the information on the correct syntax for the time zone in the manifest in the docs either too simplified or when clicking the associated link, too convoluted for my poor goat brain to handle.

In short, you can add certain countries followed by their city. Like this:


Or in your code, like this:

Alternatively, you can use GMT time in this format:

“Etc/GMT-10” << For Sydney, Australia

The -10 can be changed to whatever GMT you need.


After a bit of testing and some searching, I came across these two resources to help you when entering in the correct time zone.

Alternatively, I have created a Google Sheet that contains:

  • A full timezone list with aliases
  • A full timezone list without aliases
  • A GMT only list

These might be useful for bookmarking or exporting certain Google Sheet tabs as CSVs.

Just go to File > Make a copy so you have your very own version of the document.

Finally, here is a list of all the GMT values:

Standard Offset GMT
-12:00:00 Etc/GMT+12
-11:00:00 Etc/GMT+11
-10:00:00 Etc/GMT+10
-09:00:00 Etc/GMT+9
-08:00:00 Etc/GMT+8
-07:00:00 Etc/GMT+7
-06:00:00 Etc/GMT+6
-05:00:00 Etc/GMT+5
-04:00:00 Etc/GMT+4
-03:00:00 Etc/GMT+3
-02:00:00 Etc/GMT+2
-01:00:00 Etc/GMT+1
+00:00:00 Etc/GMT-0
+01:00:00 Etc/GMT-1
+02:00:00 Etc/GMT-2
+03:00:00 Etc/GMT-3
+04:00:00 Etc/GMT-4
+05:00:00 Etc/GMT-5
+06:00:00 Etc/GMT-6
+07:00:00 Etc/GMT-7
+08:00:00 Etc/GMT-8
+09:00:00 Etc/GMT-9
+10:00:00 Etc/GMT-10
+11:00:00 Etc/GMT-11
+12:00:00 Etc/GMT-12
+13:00:00 Etc/GMT-13
+14:00:00 Etc/GMT-14

And a link to the GMT converter:

GMT Converter

I hope this saves you a little time.




Create custom prefilled Google Forms links in custom emails with Google Apps Script

Recently I raised a support ticket with a tech company I was subscribed to where we were trying to resolve an integration issue I had with their service. Once we had it all resolved they followed up with a feedback form. That feedback form just happened to be a Google Form.

Great, that’s cool. But that wasn’t what got me excited. They had exposed the raw URL link to the form in the email and I noticed that there were some references to my name, my support number and a few other things in the URL query parameters.

I clicked the link to the Google Form and, as expected, the Google Form appeared with these values prefilled into my form.

We this is a pretty cool convenience, I thought. How did they get all the query paths to each form item?

A couple of days passed and I had a chance to figure it all out.

In this tutorial, I’ll walk you through accessing the prefill tool in Google Forms. Then, if you are keen on doing some coding, we’ll create a little custom feedback form for unique users that we will deliver via email.

Let’s play!

Google Forms prefill tool

Accessing the Google Forms prefill tool

First, take a look at my example Google Form:

Go ahead and type forms.new in your Chrome browser address bar and create a few form items so you can play along.

Once you are done, got to the top right next to your avatar and you will see a vertical ellipsis. Give it a good old click.

A popup window will appear. Four items down and you will see the menu item, Get a pre-filled link. Go on, you know you want to click it. I won’t judge.

Google Forms menu buttons ot Get pre-filled link
Click to Expand!

A new window will appear in your browser with a sample of your form. Go ahead and fill out any part of the form that you want to have prefilled.

We’ll fill out the first three items in our form. Here, take a look:

Google Forms prefill screen
Click to Expand!

As you can see above I have added my name (Yagi the Goat), a ticket number (6047) and issue (Login – Passwords).

You might have noticed down the bottom left of the screen a grey box with the prompt, Prefill responses, and then ‘Get link’.

Go ahead and scroll down to the bottom of your form and click the Get link button (1).

Google Forms prefill get link & copy link
Click to Expand!

Then click the COPY LINK button in the grey bar (2).

Paste your link in a new browser tab and hit enter to check that the pre-fill is what you wanted.

If you are happy with the prefill results, then paste the pre-fill link somewhere safe for you to use later.

You should end up with a URL a little like this:


You should be able to see some of the pre-fill items in your URL that you added earlier. We’ll go onto this later if you are following along to the Google Apps Script portion of this tutorial.


Why would you use a pre-fill in a Google Form?

At first, I was a little lost at the usefulness of using a standard static pre-fill for your Google Form. Surely not all people on your form will need to choose the same thing. I mean, you may as well leave it out of the form, right.

However, after a bit of noggin scratching, I thought that maybe you could use a static prefill like this for a standard response to help most users skip filling in unnecessary parts of the form while still making it flexible enough for the user to change the form if they need to.

When it does become an awesome tool is when you can use the URL generated and update fields to customise it for each user.

In the next part of this tutorial, we will do just that with the help of some Google Apps Script and then add our form to a custom email.


Create a custom prefilled form link and email it

In this portion of the tutorial, we are going to create a custom pre-filled form link by altering our copied pre-filled form link and then send a custom email to a user with their name and their own unique Google Form link.

The example

Let’s assume we have our very own tech support team. After we complete each ticket, our team are eager (yeah right!) to find out how well they performed in their support of the client.

The team stores each completed ticket details in a Google Sheet like below:

Support ticket Google Sheets for Google Forms prefill V2
Click to Expand!

Looking at the image of the Google Sheet above, we only want to send an email to those clients whose checkbox in column I is unchecked – indicating that they haven’t received and email yet.

We then want to send an email to our users with a message and a link to our unique pre-filled Google form.

For example, our last user, Andrew Bynum, would get an email like this:

Custom feedback email with link to prefilled Google Form
Click to Expand!

Then when Andrew clicked on the form link he would be navigated to his own pre-filled Google Form with the first 3 items filled in like below :

Custom Google Form pre-fill for specific user
Click to Expand!

The anatomy of the pre-fill URL bar

That was generated with this bespoke URL:


If you look carefully, you will see some of the input we put in our form when we were using the Google Forms pre-fill tool.


This portion of the URL directs the user to the Google Form, with the ID of the form in blue above between the last two forward slashes.


Next, you can see 3 occurrences of entry followed by a number (in red) then equals to the pre-fill input we added (in green). Note that if a prefill item has a space, it is replaced with a plus (+) symbol.

We start to write out our code we can replace these pre-filled inputs with a variable that can update for each user we send our form to.

Time to check out the code to see how we do this.

The Code

This is a pretty basic procedural code so we will simply pack it into one function. No need to go crazy here:

Main variables

Variables to update

We need to first set up some main variables that we will reference in our project. First, we will get access to the Google Sheet that contains the ticket data for our clients – the Tickets file we mentioned earlier – using the SpreadsheetApp class.

We then call the openById() method which takes one argument, the file id. This can be found in the URL and should look similar to the one in the example. This is then put in the SS variable. Line 10

Next, we need to get to the sheet tab our data is in. For us, this is Ticket. So we reference this sheet tab name with our getSheetByName() method and store it in our SHEET variable. Line 11

We will want to indicate what row our user data starts because we don’t want to include our headers. Here we set our ROW_START variable to 2 because our first user is in row 2.

Getting data range and values

Our next task is to get the range of all the data we need to add our pre-fill values, emails and client name data along with our checkbox to see if we need to email that user. We may as well select all the columns and grab the last row.

To grab the full range of our data we use the getRange() method. Which can take many types of arguments, but for us, we want to give it 4 number values:

  • Row start
  • Column start
  • Number of rows
  • Number of columns

We’ll add our ROW_START in our…um…row start argument. Our column start in the first column. Then we grab the last row, which will likely change often by using the getLastRow(). This will update as new entries come in.  We then subtract this by the row start and add 1 to exclude the header. Line 13

To then get the values of the range we use our new range variable and call the getValues() method. This will produce a 2d array of all the data on our sheet. Line 14

Keeping track of emails sent.

Our checkboxes in column keeps track of who we have sent our feedback form to. We will update the checkbox with a tick if we have sent the form using some code.

Before we jump into our loop through each ticket we need to keep track of where the boxes are unticked and where the row of unticked boxes finish. We do this by setting up an object to store untick start and end rows that we will preset as false and update as we loop through the rows.

If you wanted to speed things up in a bigger Google Sheet you could store the start row in a Properties Service like in the post below, but that’s beyond the scope of this tutorial.

How to Automatically Navigate to the First Empty Row in a Google Sheet using Google Apps Script

Looping through our data and setting up our column variables

Now that we have the values of our Google Sheet in our VALUES variable, we want to loop through the 2d array and set some variables to each column of data we want to use in our script. We use the forEach method for our loop here with the first argument being the array containing all the cell data in the row and the second one, the row index:

Next, we need to assign some variables to each relevant row item that we will use in either our email or our pre-fill. To do this we will use some destructuring to cleanly build our variables:

The columns in our sheet contain the following:

  • Date
  • Name
  • Email
  • Ticket #
  • Issue
  • Details
  • Response
  • Status
  • Feedback Sent

The bolded items are the only columns we want to use. In our destructured variable assignment, we create an array of all the variables we want to use and put a blank comma space between the variables we don’t want to use.

Creating the first name variable

It’s kinda weird these days to address someone by their first and last name in an email greeting. Some people even find it a little insincere or annoying. So we might want to just stick to the more popular informal first name.

To get our first name, or fname, we use the Javascript substring method to just get the first part of our string up to just before the first space. The substring method takes 2 arguments. The start position and end position. We find out the end position by using the indexof method that searches a string of text and if it finds the corresponding value, it will report the position of the value, but if the value does not exist it will report -1.

The resulting code would look like this:

Now, we are not certain if our users have put in a second name, or even have one for that matter. So if we just created our fname varaiable with this code we would get a weird error if we had a single name.

To fix that, we are going to use a ternary operator that we will first use to check if the name variable is a single name or not. Here again, we use the indexof method to check if there is a positive number. If so we will use the code above to generate our name. Otherwise, we will use just the name. Check out the full line of code:

Swapping spaces between words for “+”

When we create our custom pre-fills we noticed that spaces were repaced with plus symbols “+” in the URL. We want to keep the full name and the issues in our prefill and we know that both items potentially contain spaces in the text. To change the spaces to plus symbols, we will use the Javascript replace method with the help of a little bit of regular expressions.

The replace method takes two arguments, the item to search for and the item you want to replace it with. Because the item we are searching for is a space it’s good practice to use a regular expression rather that ” ” to be certain you catch it. Our regular expression looks like this:

The \s is the symbol for spaces. The two / mean anything between. The g is the symbol for global. So essentially this expression is saying that is is looking for any occurrence of a space all over (globally) in the string.

We’ll update the two original variables (which will upset the functional programming purists, but hey, it’s only a small bit of code) so our two lines will look like this:

Sending off our email

In the next section of our function (Lines 33-46), we check to see if we need to send an email, and if we do, we send it away with our pre-filled link to our form.

First, we use an if statement to check if the current feedback cell is false, then we are good to send the email.


Next, we invoke the GmailApp Google Apps Script class and then use the sendEmail method. The sendEmail() method can take a few different argument structures, but I like to use the full method approach that takes the following:

  1. Recipient: The email of the person you are sending your email to.
  2. Subject: What your email is about.
  3. Body: We’ll put in a placeholder here, “see HTML body” because we want to use HTML to make our email look fancy.
  4. Options: The are a lot of options you can put inside the curly braces {} of this object, but for us, we just want to add htmlBody. Which allows us to add HTML to our email.

Let’s have a look at the sendEmail() method so far:

The HMTL Email

We will use template literals to create our string of HTML text. Template literals start and end with backticks (`). If you want to add a variable into the string all you need to do is add ${your variable}. The other bonus is that you can happily put your string on new lines of your code without having to close and concatenate your string each time.

Let’s take a look at our htmlBody value:

You can see that it all looks like pretty standard HTML text separated by paragraph tags <p> and breaks </br>. We’ve added in the first name (fname) in the greeting at the start and then created a link to our pre-filled form that we have customised with our variables.

Here is what each entry looks like:

  • entry.1046214884=${name}
  • entry.2009896212=${ticket}
  • entry.415477766=${issue}

Once this part is complete the emails are all sent off. Time to update our Google Sheet to show we have done this job.

Updating the checkboxes

The checkbox process occurs at the end in two stages here. First as we are iterating through our forEach loop we need to keep a record of the first unchecked box and the last one.

Remember earlier that we had set up the variable, uncheckedBoxRange, before we started the loop. Now we want to check if this is the first time we have found an unchecked box. If it is we want to update uncheckedBoxRange.start with the current index plus the ROW_START value to get the row number and also update the uncheckedBoxRange.end.

If we have already found the first occurrence of an unchecked box, we skip updating the start value and just update the end value.

Outside our loop, we then need to use our uncheckedBoxRange object values to update our checkbox columns in our Google Sheet.

First, we need to get the total number of emails we sent. We do this by subtracting the uncheckedBoxRange.end from the start and add 1.

We then want to create a string of true values equal to the uncheckedCount. This can be done fairly cleanly by the new Array constructor that can take an argument to generate amount of values in an array.

Next, we use the fill method to identify what we want to fill each array value with. For us, this is a child array with the value true in each. Why a new array inside our main array? Because each row of a sheet is its own array.

We then use the Google Apps Script getRange() method again to select our range referencing our start row of unchecked boxes, column nine, the total number of unchecked boxes. We don’t have any other columns to worry about so we don’t need a fourth argument.

Finally, we use the setValues() method inserting our newly created array of true (or ticks) into our checkboxes.


To run your code from the Google Apps Script IDE simply click on run and follow the prompts:

Alternatively, you could set a time trigger to run your code daily or weekly or when the Google Sheet changes, or have a button or menu item that you click in your sheet to run the code.

Here are a few tutorials on the topic:

So what do you think? Would you use pre-fill in your own project? I would love to hear how you applied custom pre-fill. It’s always interesting to see what creative things people develop.

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? Fiverr’s your best bet to find a skilled Google Apps Script professional to solve your problem quickly and cheaply. *

*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.

Google Sheets Beginners: Cutting, Copying and Pasting ( + bonus complete guide) (35)

Just when you thought that copy and paste was a no-brainer you start working in Google Sheets spreadsheets and find that there is a little more here than meets the eye.

The good news is that Google  Sheets has some great pasting types to help you copy or cut your data and put it in the cells or ranges exactly how you want it.

This tutorial takes you through a simple beginners tutorial on copying and pasting in Google Sheets to rapidly get you underway and then we dive into a Complete Guide to cut, copy, all the various paste types and possible gotchas you might face.

Cut, Copy & Paste Basics

The most important takeaway from this tutorial are the shortcuts that are going to be vital for you to boost your efficiency:

  • Cut : PC –  ctrl + X, Mac –  ⌘ + X
  • Copy : PC –  ctrl + C, Mac –  ⌘ + C
  • Paste : PC –  ctrl + V, Mac –  ⌘ + V
  • Paste just the values  : PC –  ctrl + shift + V, Mac –  ⌘  + shift + V

Cut, Copy & Paste Complete Guide

Here we dig into the weeds of all the capabilities that Google Sheets has with Cut, Copy and Paste.

In this tutorial, I’ll cover,

  1. 00:00 Intro
  2. 00:30 The basic copy and paste function and it’s shortcuts.
  3. 01:59 Copy and pasting basic formatting.
  4. 02:38 Differences with formulas with copy and paste.
  5. 04:01 Copy and pasting – across select ranges in the same Sheet.
  6. 04:43 Copy and pasting – from one Google Sheet to another.
  7. 05:38 Copy and pasting – from a different Google Sheet to another.
  8. 06:19 Copy and pasting – from other document types like Text, Excel, or a Webpage.
  9. 10:15 Copy and pasting – same values or a range of values multiple times.
  10. 11:57 Copy and pasting – formatting only.
  11. 13:12 How copying the formatting also copies conditional formatting.
  12. 13:55 Copy and pasting – excluding borders.
  13. 14:36 Copy and pasting – column widths only.
  14. 15:40 Copy and pasting – formulas only.
  15. 16:44 Copy and pasting – data validation
  16. 17:27 Copy and pasting – conditional formatting only.
  17. 18:40 Copy and pasting – transposed ( changing rows to columns and columns to rows)


So did anyone get the Tribble easter egg? Anyone…? 👓🐐

Spend some time masting the shortcuts for cut, copy and paste. Most of them will apply for all sorts of software (not just Google Products). So it is well worth knowing.

If you enjoy the video and want to learn more about how to use Google Sheets, check out the Youtube Playlist:

Google Sheets Shorts: Beginners

Did you enjoy the tutorial? Want 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