Google Script Trigger Every 30 Days - google-apps-script

I'm interested in having my functions be triggered every 30 days. The closest I can find within Google is the once a month option, but that'll vary away from 30 days due to February and the months with 31 days.
Does anyone have any advice on how I could get this to work?
Thanks!

Trigger this every day. It will run the first time then eventually run 30 days later etc.
// trigger this function every day
function myFunction() {
var lastRunDate = new Date(PropertiesService.getScriptProperties().getProperty("lastRunDate"));
var thirtyDaysAgo = new Date(new Date().setDate(new Date().getDate()-30));
if (lastRunDate > thirtyDaysAgo) {
return; //exit because it's not yet been 30 days since last run
} else {
PropertiesService.getScriptProperties().setProperty("lastRunDate", new Date());
}
// do you work here
}

Related

Google Script All Day Calendar Event with Notification On The Day

I have a script working fine however, I cannot work out how to add a popup reminder for after an all day event as started.... example:
All day even is midnight to midnight, I want a notification at 9am that day.
my script uses event.addPopupReminder but this seems like it only works for before the event.
When I manually look, you have the option to add a reminder "On the day at 9am" but how do I code this? using -900 within the code does not work
On the day at 9am
(I've snipped the code)
By default, if the cell is blank, it'll add a notification at 9am the day before, which I want to change to 9am on the day
if (C2 == "") {C2 = '900'}
event.addPopupReminder(C2)
On the spreadsheet, I've entered -900 (for 9am on the day) and -1000 (for 10am on the day), neither have worked.
The function you are asking doesn't exist, but there is a way to do it anyway. You just have to calcul the minutes between 9am and the start of your event manually.
You haven't put a lot of code, so I wrote something that probably need to be adapted to your case.
What the following function do :
Get all events of the day and for each :
Define the minutes between 9am and the start time
Add a reminder
function setReminderTodayEvents() {
var today = new Date();
today.setHours(9);
today.setMinutes(0);
today.setSeconds(0);
var events = CalendarApp.getDefaultCalendar()
.getEventsForDay(today);
for (var x = 0; x < events.length; x++) {
var date_start = events[x].getStartTime();
var delta = (date_start - today) / 1000 / 60; //ms to minute
events[x].addPopupReminder(delta);
}
}
Suggestion : add a trigger to execute that function every day between 7 and 8
References:
getEventsForDay()
getStartTime()
addPopupReminder()

Is there a way to write an app script that will automatically hide rows in multiple tabs (3) based on a date?

I am a teacher and I need to figure out how to autohide a row/rows that are 12 days old from from the current date. The "6 Incident", "7 Incident", and "8 Incident" tabs are all mirrors of each other. Meaning, the columns replicate each other, they are just used in different grades. So, Column D in "6 Homework" is the same as Column D in "7 Homework".
The reason this script would be so helpful is it will allow us to see the up-to-date incidents and "recycle" by hiding the out of date incidents.
Ultimately, I'd love for the script to automatically hide the rows when the date an interaction is posted (Column D) is 12 days old. This could be time-based, so at 2 a.m. each morning, the script could run and automatically hide any older incident in all three tabs.
The tabs are formatted to turn white once an incident is older than 12 days. So any white rows would automatically be hidden so the spreadsheet isn't ever 100s of rows down, and current information can be found quicker.
Hopefully all this makes sense. I really appreciate anyone who can help. This would help many teachers out for this upcoming school year.
Josh
Link to spreadsheet:
https://docs.google.com/spreadsheets/d/1f66nEFl0xhIEVumiwx1Dsjv0gbLIy1SnR-h64tKpQtk/edit?usp=sharing
Here is an example of how to hide the rows older than 12 days.
Code.gs
function timerHideRows() {
try {
// Install the timer to run every day at 2:00 AM
let sheets = ["6 Incident","7 Incident","8 Incident"];
let spread = SpreadsheetApp.getActiveSpreadsheet();
let today = new Date();
today = new Date(today.getFullYear(),today.getMonth(),today.getDate()-12);
sheets.forEach( name => {
let sheet = spread.getSheetByName(name);
let dates = sheet.getRange(3,4,sheet.getLastRow()-2,1).getValues();
dates.some( (value,index) => {
let day = value[0];
if( day == "" ) return true;
day = new Date(day.getFullYear(),day.getMonth(),day.getDate());
if( day.valueOf() < today.valueOf() ) {
if( !sheet.isRowHiddenByUser(index+3)) {
sheet.hideRow(sheet.getRange(index+3,1));
}
return false;
}
}
);
}
);
}
catch(err) {
Logger.log(err);
}
}
References
SpreadsheetApp.getActiveSpreadsheet()
Spreadsheet.getSheetByName()
Sheet.getRange()
Sheet.isRowHiddenByUser()
Sheet.hideRow()
Date Object
Array.forEach()
Array.some()

Google Apps Script - Custom Triggers - Just Month + Day - No Year

In short, I have code that I would like to trigger on the first day of a specific month. So, for example, I want to run X-script on Jan 1, but not Feb 1st, March 1st etc. Based on my testing, it seems the atDate function requires the year variable and I'd like the trigger to fire every year on Jan 1, rather than just x year.
This is the version of the timed trigger function I've been working with.
function createTrigger() {
ScriptApp.newTrigger("moveNumbersDecember")
.timeBased()
.atDate(xxxx, 1, 1)
.create();
}
Is there any other function I could use, or workaround for atDate()? My other attempts have been with making the A1 cell on a sheet a clock using today(), then trying to make an if function where if A1 = January 1, then run X script. But I'm very new to coding and haven't been able to make it work.
Any ideas/help extremely appreciated.
GAS do not have yearly trigger, but try this workaround. Create a trigger that runs every month. This runs every month BUT only call the function you want to do if January 1 comes via checking the month of current date.
function createMonthlyTrigger() {
// every month, the trigger created will run checkIfJan1()
ScriptApp.newTrigger("checkIfJan1")
.timeBased()
.onMonthDay(1)
.atHour(0)
.create();
}
function checkIfJan1() {
var date = new Date();
// if jan 1, then run moveNumbersDecember()
if (date.getMonth() === 0) {
moveNumbersDecember();
}
}

Alternatives to google finance stock prices

I'm trying to make a Stock portfolio tracker for my investments. I already understand how to use google finance but the 20 min delay on prices is a drag. I've updated the recalculation for my sheets to on change and every minute but the delay will still happen. So my real question is if and how could I pull a stock price from the Nasdaq into google sheets for a more real time feel.
What you can try is having script and have it triggered every minute.
I tried fetching from NASDAQ but it takes too long. I used WSJ instead but the issue is it randomly errors out due to something I was never able to point out. Thus I added a column to identify when the data was last updated. Don't worry though, it will be updated within the next run.
Code:
function getPrice() {
var sheet = SpreadsheetApp.getActiveSheet();
// tickers will be checked on column A starting 2nd row
var values = sheet.getRange("A2:A" + sheet.getLastRow()).getValues().flat();
sheet.getRange("A1:C1").setValues([["Tickers", "Price", "Last Updated"]]);
values.forEach(function (ticker, index){
var url = "https://www.wsj.com/market-data/quotes/" + ticker;
Utilities.sleep(2000);
var html = UrlFetchApp.fetch(url).getContentText();
Utilities.sleep(2000);
var price = html.match(/quote_val">([\d ,.]+)/);
// since it randomly errors out on [1], check if price is null
// add date and time too on column C to confirm when was the data last updated
if(price){
sheet.getRange(index + 2, 2).setValue(price[1].trim());
sheet.getRange(index + 2, 3).setValue(new Date());
}
});
// call to remove existing triggers and create another one
createTrigger();
}
function createTrigger(){
// Delete all existing triggers before creating one
// Ensuring none will exist before creating trigger.
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach(function (trigger){
ScriptApp.deleteTrigger(trigger);
});
// Create trigger after every run which is per minute
ScriptApp.newTrigger('getPrice')
.timeBased()
.after(60 * 1000)
.create();
}
Sample Output:
Note:
There are 1440 minutes in a day, and quota for Url Fetch calls is 20000 a day, so you must only have at most 13 tickers as when you reach the quota, it will not behave as expected. If you want more tickers, you need to adjust the frequency. (e.g. update every 2 minutes will allow you to have at most 27 tickers)
Resource:
Quota
GOOGLEFINANCE recalculation is set to 20 minutes and cant be re-set
you will need to either scrape it from somewhere (yahoo finance, coinmarketcap) or like MK mentioned you will need to pay for (API) it because free plans may not be enough for you. see: https://coinmarketcap.com/api/pricing/

Google Spreadsheet Triggers

I'm trying to create a trigger that activates on weekdays only and at a specific time, but I don't know what I'm doing wrong. Here is my code.
function createTriggers() {
var days = [ScriptApp.WeekDay.MONDAY, ScriptApp.WeekDay.TUESDAY,
ScriptApp.WeekDay.WEDNESDAY, ScriptApp.WeekDay.THURSDAY,
ScriptApp.WeekDay.FRIDAY];
var d = new Date();
var time = d.toLocaleTimeString();
if (time == '3:05:00 PM EDT') {
for (var i = 0; i < days.length; i++) {
ScriptApp.newTrigger(Lunch1)
.timeBased().onWeekDay(days[i])
.everyMinutes().create();
}
}
}
I'm guessing that you mean you want to make it so a function is triggered (runs) every weekday at a certain time of the day. Here's what I would do.
First, in the Script Editor:
Go to Resources - Current Project's Triggers
Click Add a new trigger
Select the function that you want to be triggered
Change the next box to "Time-driven"
Change the next box to "Hour timer"
Then change the last box to "every hour"
Then at the very beginning of your function, add this code:
var d = new Date();
if (d.getDay() == 6 || d.getDay() == 0) return;
// more info here: http://www.w3schools.com/jsref/jsref_getday.asp
That will stop the rest of the script from running if it's a Saturday or Sunday.
Then, say you want the script to only run at one specific time each weekday, you could set the time-driven trigger to "Every minute" and then add another if statement after the one above:
if (d.getHours() != 15 && d.getMinutes() != 5) return;
That will stop the rest of the script from running if it's not exactly 15:05 (3:05 PM).
This is definitely not the most efficient way to do this, but it works.
Also, this is worth mentioning: I'm not sure if there's anything that would prevent you from triggering the script every minute. Google does impose quotas for what your scripts can do, but I didn't see anything about how many times a script can be triggered in a day. Here's the chart: https://developers.google.com/apps-script/guides/services/quotas
You should do something like this:
function createTriggers(func, hour) {
var weekdays = [ScriptApp.WeekDay.MONDAY, ScriptApp.WeekDay.TUESDAY,
ScriptApp.WeekDay.WEDNESDAY, ScriptApp.WeekDay.THURSDAY,
ScriptApp.WeekDay.FRIDAY];
for (var dayIndex in weekdays) {
var day = weekdays[dayIndex];
ScriptApp.newTrigger(func).timeBased()
.onWeekDay(day).atHour(hour).create();
}
}
This code creates a trigger for weekdays in a specific time calling the func function.