Google Apps Script to count number of emails received yesterday, that has certain label, then save # daily to spreadsheet - google-apps-script

Basically what the title says, but I want to:
1) Automatically count the number of emails received to my gmail account, that has a certain label on it
2) Count once everyday, even if zero
3) And report daily to a Google Spreasheet
4) So I can make a monthly report like such:
Date / #
Date / #
Date / #
.
.
.
Total for October / #
Average per day / #
I'm sure this is piece of cake using Google Script for script gurus, but I have no clue. Please teach me!

Open a new Untitled spreadsheet and go to Tools -> open Script editor and paste the code given below.
function CountEmail()
{
var label = GmailApp.getUserLabelByName("LabelName");
var labelname = label.getName();
var mails = label.getThreads();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var date = new Date();
sheet.appendRow([labelname,date,mails.length]);
}
To run the script daily you will need to set a project trigger in the app script.For that follow the steps given below:
Resources -> Current Project's Trigger -> Add trigger -> Time driven -> Hour timer -> select the time when you want the script to run.
The total number of emails and the average emails/day can be calculated in the spreadsheet itself by just using the Sum() function.

Referencing the code Suyash Gandhi has posted (citing it here in case it gets removed so there is no confusion).
NOTE: not my code!!! Credit to Suyash Gandhi
function CountEmail()
{
var label = GmailApp.getUserLabelByName("LabelName");
var labelname = label.getName();
var mails = label.getThreads();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var date = new Date();
sheet.appendRow([labelname,date,mails.length]);
}
NOTE: not my code!!! Credit to Suyash Gandhi
See the picture below
What you see here are 2 threads, 1 email in the bottom one, 3 emails in the top one and 1 draft in the top one. That given code will return a 2 here. If you wish to count all 4 (or 5 if you want the draft) you will need to use Gmail API (see reference here).
I have a script that gets all emails (every message) for a specific time period and outputs the receive date, sender, recipient and title to a spreadsheet. This is the code that actually fetches the emails. The rest of the code is mostly creating files, generating the query string and reset the script if it runs too close to 6 minutes.
queriedMessages =
Gmail.Users.Messages.list(userInfo.mail,
{
'q': queryString,
'pageToken': execProperties.nextPageId
});
userInfo.mail is the email address you are fetching the emails from. This is simply written like this because the script can be run with any account
queryString is a string that is used to search for emails and is exactly the same as you use in the gmail search box. So you would have label:labelname
pageToken is a code of the page of the search (basically what is needed when you click the next page button in gmail). It is returned as part of this function so you would be able to access it from queriedMessages.nextPageToken. So if you get more than 1 page, then you will need it to access the rest of the messages.
Also, keep in mind that you are getting all the messages fitting the query, so if you do this daily, you may want to include a trigger. Also, keep in mind that functions firing from triggers ignore your timezone (known bug), but you can figure out how to create a query that works for only 1 day fairly easily. Personally I just grab +1 day on the beginning and the end and just filter those messages out.

Related

How do you track automated data inputs in Google Sheets over time?

I have a google sheet that runs a report on data that is automatically updated. What I would like to do is compare the new inputs with the old inputs to determine if the changes were positive or negative. How would you go about automating a sheet to track these changes?
Changes happen monthly
there would be a score 1-100; 100 being the best
would like to store this data over time for a historical view
Any advice would surely be appreciated
The numbers in each criteria change every month producing a score at the end of the table called Current Score
This score is then pulled into the historical tab as the "Current Score"
What I would like to see happen is that the Current score be saved every month and processed with a percentage change month over month
So I would need a function that stores a copy of the results before they change, processes a new score, and then calculates the difference between the two. Example here is the Dec score (stored values) compared to the most recent score.
Here is a link to the working example
https://docs.google.com/spreadsheets/d/1ImbRhWqGjvIx2CFRKapZ2wmxC9qpSKxxCbHr5tPOBOs/edit#gid=0
Solution
You can automate this process by using Google Apps Script. Open the script editor by clicking on Tools > Script Editor. It is based on JavaScript and allows you to create, access and modify Google Sheets files with a service called Spreadsheet Service.
In addition, you can use Time-driven triggers to run the script automatically once a month. To set it up, click Triggers in the left bar, then Add Trigger and select Time-driven in Select event source. You can now specify the month timer and the exact day and hour you want the script to run. However, I recommend that you do some testing before setting up the trigger to check that you get the desired results. You can test the code by clicking Run in the Editor.
Explanation of the code
There are three functions in the code. The main function is called updateScores and it does what you described in the question. It takes the current score, stores it in a new column and calculates the difference from the last month. Try this function and if you like the result, you can put the trigger in the main function. This way, the trigger calls main which its only responsibility is to call the other two functions. The first is updateScores, which I have already explained, and the second is clearScores, which clears all the values of Reports so you don't have to do it manually and you can start writing the new values for the new month.
I have added some comments so you can understand what each line does.
var lr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('report').getLastRow()
function updateScores() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Historical')
var currentValues = ss.getRange('B2:B'+lr).getDisplayValues() // get current score
ss.insertColumnsAfter(2,2) // insert two new columns (current score and percent difference)
ss.getRange('D2:D'+lr).setValues(currentValues) // paste stored score
ss.getRange('C2:C'+lr).setFormula('=if(D2=0,"N/A",B2/D2-1)') // apply formula for last stored scores
ss.getRange('E2:E'+lr).setFormula('=if(F2=0,"N/A",D2/F2-1)') // correct formula reference
ss.getRange('E2:E'+lr).copyFormatToRange(ss,3,3,2,lr) // copy format percent
ss.getRange('F2:F'+lr).copyFormatToRange(ss,4,4,2,lr) // copy format scores
var month = new Date().toString().split(' ')[1] // get current month
ss.getRange('D1').setValue(month + ' score') // write current month on last stored scores
var diff = ss.getRange('E1').getDisplayValue() // get diff symbol
ss.getRange('C1').setValue(diff) // write diff
}
function clearScores(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('report')
ss.getRange('B2:G'+lr).clear()
}
function main(){
updateScores()
clearScores()
}

Trigger for Google Sheets

I have a Google Spreadsheet that will send me an email once a figure in a cell reaches a certain number. I tried setting up triggers, but it doesn't work for what I need.
I need some code to open up the spreadsheet every 2 hours and then check the cell. If the number is greater than what I want, then it emails me.
Does anyone have their own code that I can add to my email function that will do this?
Any help would be appreciated.
The following code will check the value inside a cell and if the number inside the cell is greater than your specified limit, it will send an alert to the given email address.
function sendEmail() {
// get the number in the specified cell. Here I used the cell B2 for reference
var sheet = SpreadsheetApp.getActiveSheet();
var rowNum = sheet.getRange('B2').getValue(); //take the value to rowNum
if(rowNum > your_number_limit ){
var message = 'This is your Alert email!'; // Second column
var subject = 'Your Google Spreadsheet Alert';
MailApp.sendEmail("youremailaddress", subject, message);
}
// Send Alert Email.
}
To check the value every 2 hours do the following
From the Script Editor,
choose Resources > Current project's triggers. You see a panel with the message No triggers set up. Click here to add one now.
Click the link that says No triggers set up. Click here to add one now.
Under Run, select the function you want executed on schedule.
Under Events, select Time-driven.
On the first drop-down list that appears, select Hour timer
set interval of hours for 2 hours.
Click Save.
To ensure that the script runs at the correct time for a particular time zone, click File > Properties, select a time zone and click Save.

Why does the script run 2 times?

I need to know the holidays of a team. For this, everyone receives by mail a form with 4 questions:
- Mail address
- Name
- Beginning of the leave period
- End of the leave period
Typically, responses are sent in a spreadsheet.
The idea is to fill a calendar shared with the whole team so that everyone knows the periods of leave.
For this, here is the script to link to this worksheet:
function AjouteConge() {
var fichier = SpreadsheetApp.getActiveSpreadsheet();
var feuille = fichier.getActiveSheet();
var Ligne = fichier.getLastRow();
var RefCellule = "B"+Ligne+":E"+Ligne;
var Datas = fichier.getRange(RefCellule).getValues();
var Agenda = CalendarApp.getCalendarById('abcdefghijklmnopqrstuvwxyz123456789#group.calendar.google.com').createAllDayEvent(Datas[0][0], new Date(Datas[0][1]),new Date(Datas[0][2]));
}
I notice that my script runs 2 times when the form is completed.
So, I have 2 identical events in the agenda.
This is not (necessarily) the case when testing the script from the editor (not always anyway).
An idea ? Why is this script run 2 times?
Thank you for your clarifications
Can you check if multiple users have the same submit trigger set up on the Google Form? If yes, then you should delete the trigger from other accounts and leave only one.

Google Form Limit to Number of Dropdown Options

Previously, I was using Google Apps Script to populate the choices for a dropdown list question in Google Forms on a weekly basis. One question had as many as 3600 choices at one time. This week, when running the same script with a reduced number of choices (approx. 2000), I receive the following error via script.google.com: "Failed to set choices. You exceeded the maximum number of choices." Is there a new limit to number of choices that can be added? I cannot find one listed anywhere on the web.
Code snippet to reproduce the issue:
var sheetUrl = 'https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxx/edit';
var sheet = SpreadsheetApp.openByUrl(sheetUrl).getSheetByName("Form Responses 1");
var data = sheet.getDataRange().getValues();
var formExample = FormApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxx');
var listOfCustomers= formExample.getItemById(1234567890);
var customerChoices = [];
for (var i = 0; i < data.length; i+=1){
customerChoices.push(listOfCustomers.asListItem().createChoice(data[i][0]));
}
listOfCustomers.asListItem().setChoices(customerChoices);
https://issuetracker.google.com/issues/63395462
mc...#google.com #4 Jul 18, 2017 01:55PM
Status: Won't Fix (Intended Behavior)
Since June, we've imposed a limit on the number of options that can be added to a Forms dropdown in Apps Script. The limit is currently 1,000 but is subject to change. If you need to provide more options, consider a free-form text field, multiple dropdowns, or a custom web form.
While this solution doesn't address the limit imposed on scripts (as of 2022/9/8 it's still 1000) it does provide a manual work-around for someone who doesn't need to automate the process.
Using manual copy-and-paste I have successfully created dropdowns with more than 1000 entries.
Steps:
Copy (ctrl + c) a list of more than 1000 items (from Google Sheets, for example)
Create an empty dropdown in a Google Form
Paste (ctrl + v) the list of items
I created a dropdown with 1690 entries that way.
Credit for this solution goes to TC.

How to make google spreadsheet refresh itself every 1 minute?

My google spreadsheet is using GOOGLEFINANCE('symbol','price) function to retrieve stock prices of my portfolio. Unfortunately, I have to refresh manually now. How can I make the spreadsheet refresh itself every 1 minute?
Thank you for your help.
If you're on the New Google Sheets, this is all you need to do, according to the docs:
change your recalculation setting to "On change and every minute" in your spreadsheet at File > Spreadsheet settings.
This will make the entire sheet update itself every minute, on the server side, regardless of whether you have the spreadsheet up in your browser or not.
If you're on the old Google Sheets, you'll want to add a cell with this formula to achieve the same functionality:
=GoogleClock()
EDIT to include old and new Google Sheets and change to =GoogleClock().
If you are only looking for a refresh rate for the GOOGLEFINANCE function, keep in mind that data delays can be up to 20 minutes (per Google Finance Disclaimer).
Single-symbol refresh rate (using GoogleClock)
Here is a modified version of the refresh action, taking the data delay into consideration, to save on unproductive refresh cycles.
=GoogleClock(GOOGLEFINANCE(symbol,"datadelay"))
For example, with:
SYMBOL: GOOG
DATA DELAY: 15 (minutes)
then
=GoogleClock(GOOGLEFINANCE("GOOG","datadelay"))
Results in a dynamic data-based refresh rate of:
=GoogleClock(15)
Multi-symbol refresh rate (using GoogleClock)
If your sheet contains a number of rows of symbols, you could add a datadelay column for each symbol and use the lowest value, for example:
=GoogleClock(MIN(dataDelayValuesNamedRange))
Where dataDelayValuesNamedRange is the absolute reference or named reference of the range of cells that contain the data delay values for each symbol (assuming these values are different).
Without GoogleClock()
The GoogleClock() function was removed in 2014 and replaced with settings setup for refreshing sheets. At present, I have confirmed that replacement settings is only on available in Sheets from when accessed from a desktop browser, not the mobile app (I'm using Google's mobile Sheets app updated 2016-03-14).
(This part of the answer is based on, and portions copied from, Google Docs Help)
To change how often "some" Google Sheets functions update:
Open a spreadsheet. Click File > Spreadsheet settings.
In the RECALCULATION section, choose a setting from the drop-down menu.
Setting options are:
On change
On change and every minute
On change and every hour
Click SAVE SETTINGS.
NOTE External data functions recalculate at the following intervals:
ImportRange: 30 minutes
ImportHtml, ImportFeed, ImportData, ImportXml: 1 hour
GoogleFinance: 2 minutes
The references in earlier sections to the display and use of the datadelay attribute still apply, as well as the concepts for more efficient coding of sheets.
On a positive note, the new refresh option continues to be refreshed by Google servers regardless of whether you have the sheet loaded or not. That's a positive for shared sheets for sure; even more so for Google Apps Scripts (GAS), where GAS is used in workflow code or referenced data is used as a trigger for an event.
[*] in my understanding so far (I am currently testing this)
GOOGLEFINANCE can have a 20 minutes delay, so refreshing every minute would not really help.
Instead of GOOGLEFINANCE you can use different source. I'm using RealTime stock prices(I tried a couple but this is the easiest by-far to implement. They have API that return JSON { Name: CurrentPrice }
Here's a little script you can use in Google Sheets(Tools->Script Editor)
function GetStocksPrice() {
var url = 'https://financialmodelingprep.com/api/v3/stock/real-time-
price/AVP,BAC,CHK,CY,GE,GPRO,HIMX,IMGN,MFG,NIO,NMR,SSSS,UCTT,UMC,ZNGA';
var response = UrlFetchApp.fetch(url);
// convert json string to json object
var jsonSignal = JSON.parse(response);
// define an array of all the object keys
var headerRow = Object.keys(jsonSignal);
// define an array of all the object values
var values = headerRow.map(function(key){ return jsonSignal[key]});
var data = values[0];
// get sheet by ID -
// you can get the sheet unqiue ID from the your current sheet url
var jsonSheet = SpreadsheetApp.openById("Your Sheet UniqueID");
//var name = jsonSheet.getName();
var sheet = jsonSheet.getSheetByName('Sheet1');
// the column to put the data in -> Y
var letter = "F";
// start from line
var index = 4;
data.forEach(function( row, index2 ) {
var keys = Object.keys(row);
var value2 = row[keys[1]];
// set value loction
var cellXY = letter + index;
sheet.getRange(cellXY).setValue(value2);
index = index + 1;
});
}
Now you need to add a trigger that will execute every minute.
Go to Project Triggers -> click on the Watch icon next to the Save icon
Add Trigger
In -> Choose which function to run -> GetStocksPrice
In -> Select event source -> Time-driven
In -> Select type of time based trigger -> Minutes timer
In -> Select minute interval -> Every minute
And your set :)
I had a similar problem with crypto updates. A kludgy hack that gets around this is to include a '+ now() - now()' stunt at the end of the cell formula, with the setting as above to recalculate every minute. This worked for my price updates, but, definitely an ugly hack.
use now() in any cell. then use that cell as a "dummy" parameter in a function.
when now() changes every minute the formula recalculates.
example:
someFunction(a1,b1,c1) * (cell with now() / cell with now())