How to target multiple specific days in this Google Apps Script - google-apps-script

I have this script, it sends an email when the spreadsheet hasn't been modified by a specific time on set of days:
function checkWriting() {
const emailAddress = "your#email.com";
var now = new Date();
var day = now.getDay();
var hours = now.getHours();
//Set the days and between which hours to check
//Sun=0 Mon=1 Tue=2 Wed=3 Thu=4 Fri=5 Sat=6
if ((day >= 3) && (day <= 5) && (hours >= 18) && (hours <= 19)) {
// Get the dates
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var formatDate = sheet.getRange(lastRow, 1).getValue().replace("at", "").replace("AM", "").replace("PM","") + " GMT+0100";
var lastWrite = new Date(formatDate);
var lastWriteDate = lastWrite.getFullYear() + "-" + lastWrite.getMonth() + "-" + lastWrite.getDate();
var nowDate = now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate();
if (nowDate > lastWriteDate) {
// Send an email out
MailApp.sendEmail(emailAddress, "You didn’t write today.", "Get on that.");
}
}
}
Right now I have it set to run between Wednesday and Friday.
My question is how do I target lets say Monday, Wednesday, Friday?
Would I write it so I just have multiple separate functions? For example
function checkWritingMonday() {
const emailAddress = "your#email.com";
var now = new Date();
var day = now.getDay();
var hours = now.getHours();
//Set the days and between which hours to check
//Sun=0 Mon=1 Tue=2 Wed=3 Thu=4 Fri=5 Sat=6
if ((day = 1) && (hours >= 18) && (hours <= 19)) {
I realize I can probably also just have my trigger run only on Monday, Wed, or Friday. That's what I'm going to do in the interim.
I am just looking for a way to do it in the script.

You could simply create a more complex if, like this:
//Sun=0 Mon=1 Tue=2 Wed=3 Thu=4 Fri=5 Sat=6
if ((day == 1 || day == 3 || day == 5) && (hours >= 18) && (hours <= 19)) {

Related

Change the value of a cell if another cell has a date that falls within the current week - apps script

In google sheets I have a task table. Included in the table is a column that has a timeline dropdown and a column that includes a do date. I am trying to change the value of the timeline column if the do date falls within the current week.
For example, using my screenshot below:
Today is 2/7/2023 - I would like to see if the do date falls within this current week (2/5/2023-2/11/2023). Because the do date falls within this week (2/10/2023) I would like the Timeline to change to "This Week"
Here is the code I have tried. I was thinking I could get the first day and last day of the current week, and then compare those two dates to the date listed in the do date column.
function onEdit(event){
var colK = 11; // Column Number of "K"
var changedRange = event.source.getActiveRange();
if (changedRange.getColumn() == colK) {
// An edit has occurred in Column K
//Get this week
var curr = new Date; // get current date
var first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
var last = first + 6; // last day is the first day + 6
var firstday = new Date(curr.setDate(first)).toUTCString();
var lastday = new Date(curr.setDate(last)).toUTCString();
var doDateTW = new Date(changedRange.getValue.setDate()).toUTCString();
//Set value to dropdown
var group = event.source.getActiveSheet().getRange(changedRange.getRow(), colK - 5);
if (doDateTW >= firstday && doDateTW <= lastday) {
group.setValue("This Week");
}
}
}
In your situation, how about the following modification?
Modified script:
function onEdit(event) {
var { range, source } = event;
var colK = 11;
var changedRange = source.getActiveRange();
if (changedRange.getColumn() == colK) {
var curr = new Date();
var year = curr.getFullYear();
var month = curr.getMonth();
var first = curr.getDate() - curr.getDay();
var last = first + 6;
var firstday = new Date(year, month, first).getTime();
var lastday = new Date(year, month, last).getTime();
var doDateTW = range.getValue().getTime();
var group = source.getActiveSheet().getRange(changedRange.getRow(), colK - 5);
if (doDateTW >= firstday && doDateTW <= lastday) {
group.setValue("This Week");
} else {
group.setValue(null);
}
}
}
When you put a date value to the column "K", when the inputted date value is in this week, "This Week" is put into column "F". When the inputted date value is not in this week, the cell of column "F" is cleared.
In this modification, I used your script of var first = curr.getDate() - curr.getDay(); and var last = first + 6;.

Google Sheets getDay() Shows an Incorrect Value

Date() shows the correct date while getDay() shows an incorrect value.
function Test()
{
const date = new Date();
const dateToday = Utilities.formatDate(new Date(), "GMT+8", "MM/dd/YYYY");
const dateYesterday = Utilities.formatDate(new Date(new Date().setDate(date.getDate() - 1)), "GMT+8", "MM/dd/YYYY");
var day = date.getDay();
var a = SpreadsheetApp.getActiveSheet().getRange(3, 2);
switch (day)
{
case 1:
day = "Sunday";
break;
case 2:
day = "Monday";
break;
case 3:
day = "Tuesday";
break;
case 4:
day = "Wednesday";
break;
case 5:
day = "Thursday";
break;
case 6:
day = "Friday";
break;
case 7:
day = "Saturday";
}
a.setValue("Today is " + day + " " + dateToday + ". Yesterday was " + dateYesterday);
}
When this code was executed in Google Sheet, it will output below:
Today is Tuesday 04/21/2022. Yesterday was 04/20/2022
The dates are correct while the day shows Tuesday which is incorrect. It's Thursday right now.
As another approach, in your situation, how about the following modification?
Modified script:
function sample() {
const date = new Date();
const dateToday = Utilities.formatDate(new Date(), "GMT+8", "MM/dd/YYYY");
const dateYesterday = Utilities.formatDate(new Date(new Date().setDate(date.getDate() - 1)), "GMT+8", "MM/dd/YYYY");
const day = Utilities.formatDate(new Date(), "GMT+8", "EEEE"); // Added
const a = SpreadsheetApp.getActiveSheet().getRange(3, 2);
a.setValue("Today is " + day + " " + dateToday + ". Yesterday was " + dateYesterday);
}
In this modification, the day name is retrieved using Utilities.formatDate like Utilities.formatDate(new Date(), "GMT+8", "EEEE").
Reference:
formatDate(date, timeZone, format)
The getDay() method returns the day of the week for the specified date according to local time, where 0 represents Sunday.
Sunday is 0, Monday is 1, etc.
docs
And example with a less length implementation:
const getDayofWeek = x => x === 0 ? 'Sunday' : x === 1 ? 'Monday' : x === 2 ? 'Tuesday' : x === 3 ? 'Wednesday' : x === 4 ? 'Thursday' : x === 5 ? 'Friday' : x === 6 ? 'Saturday' : "Invalid Day";
for (i = 0; i < 8; i++) {
console.log(getDayofWeek(i))
}
Try
function test() {
const dayOfTheWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
const date = new Date();
console.log(dayOfTheWeek[date.getDay()])
}
const dayOfTheWeek = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]
const date = new Date();
console.log(dayOfTheWeek[date.getDay()])
The most important thing is to check your timezone in your script editor : go to your script editor, ckick on the gear on the left hand side, check the third box, go back to script editor and review in appsscript.json, hange timezone according to your locale
Try it this way:
function Test() {
const dt = new Date();
const dateToday = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy");
const dateYesterday = Utilities.formatDate(new Date(dt.getFullYear(), dt.getMonth(), dt.getDate() - 1), Session.getScriptTimeZone(), "MM/dd/yyyy");
var d = dt.getDay();
var a = SpreadsheetApp.getActiveSheet().getRange(3, 2);
var day;
switch (d) {
case 0:
day = "Sunday";
break;
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
}
Logger.log("Today is " + day + " " + dateToday + ". Yesterday was " + dateYesterday)
a.setValue("Today is " + day + " " + dateToday + ". Yesterday was " + dateYesterday);
}

Gmail auto reply script - how to set conditional time and stop multiple replies?

I have adapted a Gmail auto reply script to send emails to people who message me on my non-working days. I would like the script to begin sending replies on a Friday from 16:30, but I'm not sure if my code is correct.
My script did not appear to be sending any replies this past Friday when tested, but was working fine on Saturday, Sunday and Monday.
function autoReply() {
var interval = 5;
var date = new Date();
var day = date.getDay();
var hour = date.getHours();
var minute = date.getMinutes();
if ([1,6,0].indexOf(day) > -1 || (day == 1 && hour < 8) || (day == 5 && hour == 16 && minute >= 30)) {
var timeFrom = Math.floor(date.valueOf()/1000) - 60 * interval;
var threads = GmailApp.search('is:inbox after:' + timeFrom);
for (var i = 0; i < threads.length; i++) {
if (threads[i].isUnread()){
threads[i].reply("Hi," + "\n\n Thanks for your email. My working days are Tuesday to Friday, so I won't pick up your message until Tuesday morning.");
threads[i].markRead();
threads[i].star();
}
}
}
}
Additionally, is there any way to adapt my script so that it won't send the auto reply message to senders that have already received it (as with Gmail's standard auto reply feature). I have searched Stack Overflow for this solution, using terms such as 'conditional replies', but to no avail. (I appreciate I may be using the wrong terms entirely!)
Any help would be greatly appreciated!
You need to complement your if statement by the condition (day == 5 && hour >= 17)
To verify either an email has been sent to certain senders already, you can use PropertiesService. This allows you to save the senders in cache and to compare for every new email either its sender is already contained in the properties:
function autoReply() {
var interval = 5;
var date = new Date();
var day = date.getDay();
var hour = date.getHours();
var minute = date.getMinutes();
if ([1,6,0].indexOf(day) > -1 || (day == 1 && hour < 8) || (day == 5 && hour == 16 && minute >= 30)|| (day == 5 && hour >= 17)){
var timeFrom = Math.floor(date.valueOf()/1000) - 60 * interval;
var threads = GmailApp.search('is:inbox after:' + timeFrom);
for (var i = 0; i < threads.length; i++) {
if (threads[i].isUnread()){
var sender=threads[i].getMessages()[0].getFrom();
if(PropertiesService.getScriptProperties().getKeys().length==0){
PropertiesService.getScriptProperties().setProperty('from', '');
}
var scriptProperties = PropertiesService.getScriptProperties().getProperty('fromArray');
if(scriptProperties.indexOf(sender)==-1){
threads[i].reply("Hi," + "\n\n Thanks for your email. My working days are Tuesday to Friday, so I won't pick up your message until Tuesday morning.")
threads[i].markRead();
threads[i].star();
scriptProperties=scriptProperties+sender;
PropertiesService.getScriptProperties().setProperty('from', scriptProperties);
}
}
}
}
}

How to correct this script to don't run triggers on specific dates

Im currently using this script
function shouldRunTrigger() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var fiestas = ss.getSheetByName("x");
var data = fiestas.getRange(2,1,fiestas.getLastRow()-1,4).getValues();
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var date = new Date();
var day = days[date.getDay()];
var hours = date.getHours();
var FiestaEmpieza = date
var FiestaAcaba = date
for (var row in data){
FiestaEmpieza = data[row][2] ;
}
for (var row in data){
FiestaAcaba = data[row][3] ;
}
// Don't run from Friday 6pm until Saturday 10Pm
if ((day === "Fri" && hours >= 18) || (day === "Sat" && hours <= 21)){
return false;
}
// Dont turn from specific dates from Tab "x" from 6pm until 10pm
else if (date >= FiestaEmpieza && hours >= 18 && date <= FiestaAcaba && hours <= 21){
return false;
}
else {
return true;
}
}
The purpose of the script: I have to run some triggers every 5 mins, but if the day is between Friday 6pm and Saturday 10pm the trigger doesn't run This part is working.
I need also this to don't run in specific dates (line 31 of the script)
which takes dates from my spreadsheet Tab "x" , the Start date is Column C and the End date is Column D, and the data looks like this:
The problem I believe is the line 31 of the script
else if (date >= FiestaEmpieza && hours >= 18 && date <= FiestaAcaba && hours <= 21){
Which is not detecting the Dates and Hrs correctly , I'm not sure if the && are correct.
Any help on how to solve this please ?
I think this might work. If I can have access to your spreadsheet so that I can just copy the data then I would test it.
function shouldRunTrigger() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sh=ss.getSheetByName("x");
var vA=sh.getRange(2,1,sh.getLastRow()-1,4).getValues();
var days=["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var today=new Date();
var day=days[today.getDay()];
var hours=today.getHours();
if((day=="Fri" && hours>=18) || (day=="Sat" && hours<=22)){return false;}
for(var i=0;i<vA.length;i++){
var dt1=new Date(vA[row][2]).valueOf();
var dt2=new Date(vA[row][3]).valueOf();
if(today.valueOf()>=dt1 && hours >=18 && today.valueOf() <= dt2 && hours <= 21){
return false;
}
}
return true;
}
FiestaEmpeiza y FiestaAcaba will always be the last row because you loop through the date values and assign, but then don't perform any of your conditional checks. You need to consolidate the loops into one, and then move your if statements into the loop.
I recommend changing some of the variable names to be more descriptive and pass the trigger time to your function so that you can more easily test it.
Also, make sure that you maintain consistency with your date checks–date objects include time. The way you had it written, you were comparing dates objects, meaning that "April 1 # 4pm" is earlier than "April 1 # 4:01pm". So your condition could fail depending on the value you had defined in date. You can fix this simply by setting hours. (Be careful with time zone issues.)
function test_shouldRunTrigger() {
var triggerTime = new Date("Fri Apr 19 17:00:00 GMT+08:00 2019"); // Change the date to test
Logger.log(shouldRunTrigger(triggerTime));
}
function shouldRunTrigger(triggerTime) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("x");
var fiestas = sheet.getRange(2,1,sheet.getLastRow()-1,4).getValues();
var days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var triggerDay = days[triggerTime.getDay()]; // Day of the week
var triggerHour = triggerTime.getHours(); // Hour of the trigger
var triggerDate = new Date(triggerTime.setHours(0, 0, 0, 0)); // Set time to 00:00:00
Logger.log(fiestas)
for (var row in fiestas) {
var fiestaEmpieza = new Date(fiestas[row][2].setHours(0, 0, 0, 0)); // Set time to 00:00:00
var fiestaAcaba = new Date(fiestas[row][3].setHours(0, 0, 0, 0)); // Set time to 00:00:00
// Don't run from Friday 6pm until Saturday 10pm
if ((triggerDay === "Fri" && triggerHour >= 18) || (triggerDay === "Sat" && triggerHour <= 21)) {
return false;
} else if ( // Dont run from specific dates from Tab "x" from 6pm until 10pm
triggerDate >= fiestaEmpieza && // Compares dates and we know the times are all 00:00:00
triggerHour >= 18 &&
triggerDate <= fiestaAcaba && // Compares dates and we know the times are all 00:00:00
triggerHour <= 21
) {
return false;
} else {
return true;
}
}
}

Can't Add More Than One New Trigger to Script Function

I am trying to make both of these new triggers a part of my existing function. I at one time got one to work, and when I added the second, both triggers would not be created at the same time. Help please.
// Trigger every 15 Minutes
ScriptApp.newTrigger('copyPriceData')
.timeBased()
.everyMinutes(2)
.create();
//Delete Trigger after Market Closes
ScriptApp.newTrigger("delete_Triggers")
.timeBased()
.after(6 * 60 * 1000)
.create();
Existing code is:
function CopyLive1() {
var date = new Date();
var day = date.getDay();
var hrs = date.getHours();
var min = date.getMinutes();
if ((hrs >= 15) && (hrs <= 15) && (min >= 46) && (min <= 46)) {
var sheet = SpreadsheetApp.getActiveSheet();
// Get more recent closing prices
var closePriceRange = sheet.getRange("F4");
var prevClosePriceRange = sheet.getRange("F5");
var closePrice = closePriceRange.getValue();
var prevClosePrice = prevClosePriceRange.getValue();
// Check if price data has updated. If so create new row and copy price data.
if (closePrice != prevClosePrice)
{sheet.insertRowsAfter(4, 1);
var rangeToCopy = sheet.getRange("B4:G4");
rangeToCopy.copyTo(sheet.getRange("B5:G5"), {contentsOnly:true});
}
sheet.deleteRow(1825);
}
}