Finding out how frequently something occurs compared to the rest of the data in a range is a pretty common task in Google Sheets. You will use it to find the frequency of grades in a grade book, the number of sales of an item compared to your total sales or the frequency of choices of a particular item in a survey.
In this tutorial, we will cover how to find the occurrence of a value in a range as a percentage in Google Sheets. I then show you how to do this quickly for all your values in a range as a set of formulas and as a pivot table.
Let’s get started…
Table of Contents
The Example
In our example, we have a survey item asking quite humbly and without any leading statements 🐐😇:
How awesome are goats?
A: Great
B: Good
C: Okay
D: Meh
E: Jealousy is a curse
Then in column A, we have a list of respondents and, in column B, we have a list of responses or choices.
Here is a link to the raw Google Sheet data I am using in the example so that you can play along.
Just go to File > Make a copy. Then you have your own version to edit.
Get the Occurrence as a Percentage of a Single Value
To get the number of times a value occurs as a percentage of all the values in a list we will need to:
Get the count of the times the value appears in the range.
Get the total count of all the values in the range.
Divide the value count by the total count.
Change the result to be displayed as a percentage.
In our example, we want to humbly look for all the A’s, because it is pretty clear that the survey is a shallow ruse to fish for compliments.
Our range of choices is from B3:B20.
Let’s break our formula down into manageable chunks.
Get the total count of all A’s
To get the total count of all the A’s in our range we can use the COUNTIF function. This function allows us to get the count of something based on a value.
It doesn’t have to be just A though. You could use this function to get the count of, say, the number of students who got higher than a grade in a particular test.
It’s a really useful function.
COUNTIF takes two arguments:
The range you want to find your values in.
The criterion you want to find to count.
=COUNTIF(Range to search, Criterion)
In our example, the range is column B and the criterion is A.
=COUNTIF(B3:B20,“A”)
For our example, this will return a value of 7.
Get the total count of all values in the range
Next, we need to get the total count of all the values in a range. We can’t use the traditional COUNT function here because COUNT only deals with numbers. Instead, we need to use COUNTA that counts any value that isn’t blank.
COUNTA can take a single range or multiple ranges. However, we only want to count our range of choices. Here is what it would look like:
=COUNTA(B3:B20)
Which will return a value of 18.
Dividing the value count by the range count
Next, we need to divide the value count by the range count.
=COUNTIF(B3:B20,“A”)/COUNTA(B3:B20)
This will return a decimal value: 0.3888888889.
We can change this in our submenu by clicking the Percentage format symbol:
This will result in 38.89%. Much lower than what is conscionably right and true. 🐐
Get the Percentage of Occurrences of Each Value in the Range with Formulas
Get the percentage of one value occurring in our range is fine, but often we need to get the percentage of all the values in a range.
I try and keep my data as dynamic as possible. This means that I want to create formulas that can update easily if changes are made to the data. So that the next time I have to do a similar task, I already have a working template ready to copy and paste into.
In this example, I will show you how to create a summary chart of all the values as a percentage. Here is what our end result will look like:
If you are playing along, go to the next Google Sheets tab in the sample sheet named Range (formulas).
Titles and subtitles
First, in column F3, paste in the header: Occurrence of Choices as a percentage of all data. Format to taste.
Then in F4 and G4 add the sub-headers: Choice and Choice as % respectively.
Get a dynamic list of values
We could just list our values by hand but that doesn’t make a very good template. We can get a unique list of all of our choices by using the UNIQUE function in Google Sheets. UNIQUE takes a range of values.
=UNIQUE(B3:B20)
This won’t sort your choices alphabetically though. So let’s put our UNIQUE function inside a SORT function. The SORT function first takes the range you want to sort and then can take a number of optional arguments that we won’t use here.
Here is what our example will look like:
=SORT(UNIQUE(B3:B20))
Now we have a dynamic list of choices that will change automatically if our data changes. Sweet!
Getting the percentage of occurrences for each value
Now we can use our original formula to get the frequency of occurrence of each value in our Google Sheet. This time around I have made a few minor changes to the formula that you might miss at first glance:
=COUNTIF($B$3:$B$20,F5)/COUNTA($B$3:$B$20)
First of all, I have referenced the corresponding value cell on the left. In our first row, this is F5 or the value “A”. Next, I have added dollar signs to my range to lock it in or make it absolute. Otherwise, the cell range would have moved down as I dragged my formula down each cell in the column causing and error in our count.
You can find out more about absolute and relative references in my post here:
Once you have dragged down your formula to accommodate all your values you should get something that looks a little like this:
Finishing up
Finally, we can add the total to the bottom, just in case someone doesn’t know that everything should equal 100%. Oh, and to check that we didn’t mess up.
You can simply do this with the SUM function. That will take the range or all the calculated percentages. If you are lucky, when you put in the equals sign, Google Sheets will suggest the calculation for you.
=SUM(G5:G9)
Add in the Total as a side header and get it to stand out to make it look pretty.
Next, we will look at another way of achieving this that you might find easier or quicker.
Get the Percentage of Occurrences of Each Value in the Range with a Pivot Table
In this example, we are going to grab our occurrence percentages for each value using a pivot table. This can be a much quicker approach. Plus it has the added benefit of adjusting to the remaining values in a filter or a slicer.
Let’s get cracking!
If you are playing along, go to the next sheet tab named, Range (Pivot Table).
Pivot tables in Google Sheets allow you to analyse and transform data into interesting charts that allow you to quickly summarise your data.
Creating the pivot table
First, we will select our column of Choices. This time around, we will include the header:
B2:B20
Next, access the Pivot table by going to Insert > Pivot Tables. A popup window will appear containing:
The data range you selected.
A choice of where to insert your data.
Select > Existing Sheet.
A line with an example will appear.
Select the grid symbol on the far right.
Another pop-up window will appear. Here you can choose what cell you want to start your Pivot Table.
Select cell E3 and then hit, Okay. ( You can drag the pop-up to a different location if it is in the way)
Back in the original popup and click Okay.
Creating your pivot table data
Once you hit okay, a Pivot Table editor in the sidebar would have appeared on the right. And a small template would have appeared starting in your selected cell.
Take a look at the Pivot Table editor. Look at the Rows item, select Add and then selectChoice.
You will get a little box with your Choice data.
Next, move down to Values and select Add. Again, select Choice. If you are lucky, Google Sheets would have added a count of all the values in the range. If not select the Summarized by dropdown and choose COUNTA.
At this stage, things should look like this:
We’re almost there.
Next, under Values, select the Show as dropdown and select % of column.
Bang! We did it! Go ahead and close the Pivot Table editor.
Now, to tidy up let’s change that verbose subheader with the COUNTA of blah…blah…
Click on cell F3,and enter “Choice as %”.
This is what it should look like now?
That’s it you are all done. The great news is that the pivot table will change as you change your data too.
Conclusion
We’ve covered how to get the frequency of a value occurring in a range by creating our custom formula. Then we have looked at how to make a dynamic summary of all the values as a percentage using formulas first and then as a pivot table.
So which one did you like the most the pivot table or the formulas to build the summary? Let me know in the comments below. I’d be interested to hear your thoughts.
In these video tutorials, we will cover the Filter tool in Google sheets.
Filter
You can set up a specialised view of your Google Sheet data that will let you sort, or filter out unwanted data in any column with the Filter tool.
This tool can pack a punch. You can sort different columns alphabetically, numerically, suing custom rules or even background colours. You can then use the filter part of the tool to remove unwanted parts of your data.
Don’t worry though, the filter will not affect your original. All you have to do is remove the filter and your data is back to normal.
In this video tutorial, we will go into the details on how to use the Filter tool. We will also cover some common gotchas, that beginners stumble on when trying to use Filter for the first time.
00:00 Intro
00:26 Accessing the Filter tool
01:14 About column headers and Filter
01:26 Fixing up hidden headers
01:39 A basic sort
01:46 Sorting A-Z & Z-A
02:00 Sorting with numbers
02:28 Sort by a background colour
03:09 Sort by order then colour
03:34 Sort by multiple columns (gotchas!)
04:23 Sort by grades
05:25 Filtering
05:34 Filter by values
07:46 Filter by colour
08:27 Filter by condition
Filter Views
You can create a variety of different filtered views without code or changing your data with Google Sheets Filtered Views. These views can be really handy for quickly presenting your data to your team or clients.
Filter views also have the benefit of being viewable only to the user who created them. This means that you will not annoy other users with your view when you selected one of your filtered views.
00:00 Intro
00:17 How to create a Filter View
00:44 Filter view layout
01:03 Create your first Filter View
01:32 Updating the range
02:48 Accessing & hiding Filter Views
03:07 Create another Filter View
04:13 Duplicating a Filter View
05:57 View a list of Filter Views
06:21 Remove a Filter View
06:41 Educating your team
If you enjoy the videoes and want to learn more about how to use Google Sheets, check out the Youtube Playlist:
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!
Table of Contents
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. Three 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.
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:
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).
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 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.
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:
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:
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 :
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:
sendFeedbackEmail()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/**
* Create an email with a prefill link to a Google Form
*/
functionsendFeedbackEmail(){
/** #############################################
* Globals
* ##############################################
*/
constSS=SpreadsheetApp.openById("1Jbgl82JbVVRhWWUs7JSVaDh2ai52DGD5Vs7XKF5Qq8s");//Update for your workbook
constSHEET=SS.getSheetByName("Ticket");// Update to your Google Sheet Tab
constROW_START=2;//After your header, where does your row start?
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 I 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.
1
let uncheckedBoxRange={start:false,end:false};
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.
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 forEachmethod 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:
1
VALUES.forEach((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:
1
let[,name,email,ticket,issue,,,,emailSent]=row;
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 Javascriptsubstringmethod 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 theindexofmethod 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:
1
name.substring(0,name.indexOf(" "))
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:
1
let fname=(name.indexOf(" ")!==-1)?name.substring(0,name.indexOf(" ")):name;
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:
1
/\s/g
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:
1
2
name=name.replace(/\s/g,"+");
issue=issue.replace(/\s/g,"+");
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.
Sendemail()
Next, we invoke the GmailApp Google Apps Script class and then use the sendEmailmethod. The sendEmail() method can take a few different argument structures, but I like to use the full method approach that takes the following:
Recipient: The email of the person you are sending your email to.
Subject: What your email is about.
Body: We’ll put in a placeholder here, “see HTML body” because we want to use HTML to make our email look fancy.
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:
1
2
GmailApp.sendEmail(email,"Support Feedback","see HTML body",{
htmlBody:
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:
1
2
3
4
5
6
7
8
9
10
11
`
<p>Hi${fname},</p>
</br>
<p>We are constantly trying toimprove our ability toprovide fast andhelpful support foryou.</p>
<p>Please takeamoment tofill out the Feedback Form below on how we did with your recent ticket:</p>
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.
1
2
3
4
5
6
7
//Update your checkbox range.
if(!uncheckedBoxRange.start){
uncheckedBoxRange.start=index+ROW_START;
uncheckedBoxRange.end=index+ROW_START;
}else{
uncheckedBoxRange.end=index+ROW_START;
}
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.
1
let uncheckedCount=1+uncheckedBoxRange.end-uncheckedBoxRange.start;
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 n amount of values in an array.
Next, we use thefillmethod 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.
1
let ticks=newArray(uncheckedCount).fill([true]);
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.
Conclusion
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.
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.
Need help with Google Workspace development?
My team of experts can help you with all of your needs, from custom app development to integrations and security. We have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.
When your Google Sheet spreadsheet starts to grow in complexity it is often a good idea to group similar parts of your data so you can easily collapse and expand them as you need them. Fortunately, Google Sheets has your back with the Grouping tool.
In this tutorial, we will look at how to group rows and columns in Google Sheets. We’ll also look at a few advanced capabilities and show you how to avoid some common traps.
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.
00:30 The basic copy and paste function and it’s shortcuts.
01:59 Copy and pasting basic formatting.
02:38 Differences with formulas with copy and paste.
04:01 Copy and pasting – across select ranges in the same Sheet.
04:43 Copy and pasting – from one Google Sheet to another.
05:38 Copy and pasting – from a different Google Sheet to another.
06:19 Copy and pasting – from other document types like Text, Excel, or a Webpage.
10:15 Copy and pasting – same values or a range of values multiple times.
11:57 Copy and pasting – formatting only.
13:12 How copying the formatting also copies conditional formatting.
13:55 Copy and pasting – excluding borders.
14:36 Copy and pasting – column widths only.
15:40 Copy and pasting – formulas only.
16:44 Copy and pasting – data validation
17:27 Copy and pasting – conditional formatting only.
18:40 Copy and pasting – transposed ( changing rows to columns and columns to rows)
Conclusion
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: