Deleting a row based on date - Date values - date

My query relates to this Google Form responses spreadsheet. I'm trying to adapt the script I got from here.
function cleanup() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var InAYear = (Date.now()/86400000 + 25569) + 365;
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][5] >= InAYear) {
sheet.deleteRow(i+1);
}
}
}
I'm trying to get this to compare the date in the Start Date column of the sheet with the date in a year from now and delete the row if the column entry is greater than this (ie. if the date on the sheet is more than a year in advance). However, I obviously don't understand how to get the two different dates in the same format because examining variable values when debugging shows wildly different values.

Try the following script code:
function cleanup() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var today = Utilities.formatDate(new Date(), ss.getSpreadsheetTimeZone(), 'MM/dd/yyyy')
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][4] != '' && dateDiffInDays(values[i][4],today) > 365 ) {
sheet.deleteRow(i+1);
}
}
};
function dateDiffInDays(d1,d2) {
var date1 = new Date(d1);
var date2 = new Date(d2);
var timeDiff = date1.getTime() - date2.getTime();
return Math.ceil(timeDiff / (1000 * 3600 * 24));
};

It looks like I have it working, and sending me an email.
function cleanup(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Form responses 1');
var values = sheet.getDataRange().getValues();
var today = new Date();
var InAYear = new Date();
InAYear.setFullYear( today.getFullYear()+1 );
var emailaddress = "****";
var subject = "Annual Leave Request";
var message = "Annual Leave has been requested as follows:" + "\n\n";
for (var i = values.length - 1; i >= 0; i--) {
if ( values[i][4] > InAYear ) {
sheet.deleteRow(i+1);
subject = "Annual Leave Request - Rejected";
message = "The following annual leave request was rejected due to being more than one year in advance:" + "\n\n";
}
}
for(var field in e.namedValues) {
message += field + ':'
+ "\n" + e.namedValues[field].toString() + "\n\n";
}
MailApp.sendEmail(emailaddress, subject, message);
}
Thank you to Kishan, without who's help I would not have been able to get to this stage.

Related

Calculate the difference of dates in days

I need to calculate the difference in days between two dates in two differente occasions
Occasion 1 - There's a start and an end date
Occasion 2 - There's a start date and a "IN PROGRESS" where the end date should be
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daTa = ss.getSheetByName("Data");
var daysColumn = daTa.getRange('C2:C' + daTa.getLastRow()).getValues();
var startDate = daTa.getRange('C2:C'+ daTa.getLastRow()).getValues().flat();
var endDate = daTa.getRange('A2:A'+ daTa.getLastRow()).getValues().flat();
var today = new Date().valueOf();
endDate.forEach((finaldate,row) => {
if(finaldate == "IN PROGRESS") {
daysColumn[row][0] = (parseInt(startDate,10)-today);
} else {
daysColumn[row][0] = (parseInt(startDate,10)-parseInt(finaldate,10));
}})
daTa.getRange(2,4,daysColumn.length, 1).setValues(daysColumn)
}
Right now i got this bit of code, and it know what needs to be done, but it returns only "#NUM!" values on the column, where it should print the numbers.
Probably you want this:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daTa = ss.getSheetByName("Data");
var daysColumn = daTa.getRange('C2:C' + daTa.getLastRow()).getValues();
var startDate = daTa.getRange('C2:C' + daTa.getLastRow()).getValues().flat()
.map(x => new Date(x).valueOf()); // get milliseconds of the dates
var endDate = daTa.getRange('A2:A' + daTa.getLastRow()).getValues().flat()
.map(x => new Date(x).valueOf()); // get milliseconds of the dates
var today = new Date().valueOf();
var day = 1000 * 60 * 60 * 24; // milliseconds in a day
endDate.forEach((finaldate, row) => {
if (finaldate == "IN PROGRESS") {
daysColumn[row][0] = (startDate[row] - today) / day;
} else {
daysColumn[row][0] = (startDate[row] - finaldate) / day;
}
})
daTa.getRange(2, 4, daysColumn.length, 1).setValues(daysColumn)
}
function DiffInDays(Day1,Day2) {
if(Day1 && Day2 && (Object.prototype.toString.call(Day1) === '[object Date]') && (Object.prototype.toString.call(Day2) === '[object Date]')) {
var day=86400000;
var t1=new Date(Day1).valueOf();
var t2=new Date(Day2).valueOf();
var d=Math.abs(t2-t1);
var days=Math.floor(d/day);
//Logger.log(days);
return days;
} else {
throw 'Invalid Inputs';
}
}

Creating calendar syncronised to spreadsheet but all events are created onn 1 Jan 1970 at 03:00. What did I miss?

I am following the conversation and tutorial in post Create Google Calendar Events from Spreadsheet but prevent duplicates
But I cannot get the final solution to work. It fills my calendar but all dates are 1/1/1970 at 3 am.
The code is as follows:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name: "Export Events",
functionName: "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
function parseDate(s) {
var months = {
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5, jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11
};
var p = s.replace(".", "").split('-');
return new Date(p[2], p[1], p[0]);
}
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getDisplayValues();
var calId = "the calendar"; // PRODUCTION
//var calId = "the calendar; // TEST
var cal = CalendarApp.getCalendarById(calId);
//Logger.log(cal);
//Logger.log(data.length);
for (i = 0; i<data.length; i++) {
if (i<headerRows) continue; // Skip header row(s)
if (data[i][0].length<1) continue; // Skip if no content.
var row = data[i];
Logger.log(row);
var date = parseDate(row[0]); // First column
//Logger.log(date);
var title = row[1]; // Second column
var tstart = new Date();
var s = row[2].split(":");
tstart.setHours(s[0]);
tstart.setMinutes(s[1]);
tstart.setSeconds(s[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date();
var e = row[3].split(":");
tstop.setHours(e[0]);
tstop.setMinutes(e[1]);
tstop.setSeconds(e[2]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var id = row[6]; // Sixth column == eventId
// Check if event already exists, update it if it does
var event = null;
if (id.length > 0) {
try {
event = cal.getEventSeriesById(id);
} catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {
description: desc, location: loc
}).getId();
var r = i + 1;
var cell = sheet.getRange("G" + r);
cell.setValue(newEvent);
} else {
Logger.log(event);
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
}
I think I must be making an obvious rookie mistake but cannot figure it out. Any chance of some help?
BTW: my dates are formatted: 12/01/2019 and times formatted: 18:00:00.

Google apps script, forward all emails except one

I have a script that forwards all of my emails that come in during specific times to email#domain.com.
The problem I am having, is that sometimes email#domain.com sends me an email during that time.
Can anyone suggest a way to add a rule that it should forward to all addresses except forwarding address?
function forwardEmails() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var settings = ss.getSheetByName('Settings').getDataRange().getValues();
if (settings[1][1] == 'No')
return;
if (settings[2][1] == "")
throw new Error('Please set Forward Email!');
var email = PropertiesService.getScriptProperties().getProperty('email');
if (!email)
throw new Error('First authorize script by clicking on menu: Email Forwarder >> Authorize Script');
var today = (new Date());
var applicableRules = validRules(today);
if (applicableRules) {
var unread = GmailApp.getInboxUnreadCount();
if (!unread)
return;
var threads = GmailApp.getInboxThreads(0, unread>100?100:unread);
var cutOff = today.getTime() - (MINUTES*60*1000 + 100); // 10 mins + 100 ms
for (var i=0; i<threads.length; i++) {
var msgs = threads[i].getMessages();
for (var j=0; j<msgs.length; j++) {
var from = msgs[j].getFrom();
var msgDate = msgs[j].getDate();
var msgTime = (new Date(msgDate)).getTime();
var diff1 = msgTime - cutOff;
if (diff1 > 0 && from.indexOf(email) == -1) {
var to = msgs[j].getTo();
var subject = msgs[j].getSubject();
var attach = msgs[j].getAttachments();
var body = msgs[j].getBody();
var plainBody = msgs[j].getPlainBody();
var replyTo = msgs[j].getReplyTo();
var options = {replyTo: from};
if (attach.length > 0)
options.attachment = attach;
GmailApp.sendEmail(settings[2][1], subject, plainBody, options );
}
}
}
}
} catch (error) {
var html = '<p>'+ error + '</p><br><br>Email Forwarder Rules & Settings<p>Line: '+ error.lineNumber + ', Filename: ' + error.fileName + '</p>';
if (!email)
email = Session.getActiveUser().getEmail();
MailApp.sendEmail(email, 'Email Forwarder Script Failed!', error + '\n\nEmail Forwarder Rules & Settings URL: ' + ss.getUrl(), {htmlBody: html});
}
}
Instead of using getInboxThreads() use search().
getInboxThreads() will return threads in your inbox while search() will return those that meet the search query. The following query will include include messages in your inbox but exclude those from email#domain.com
in:inbox -from:email#domain.com
You could add a check in the second loop of the "forwardEmails" function. The code below would skip any unread emails which have arrived from the forwarding address (I'm assuming the forwarding email is referenced in "settings[2][1]".
for (var i=0; i<threads.length; i++) {
var msgs = threads[i].getMessages();
for (var j=0; j<msgs.length; j++) {
var from = msgs[j].getFrom();
var msgDate = msgs[j].getDate();
var msgTime = (new Date(msgDate)).getTime();
var diff1 = msgTime - cutOff;
// New code
if (from === settings[2][1]) {
continue;
}

Calling a function from onEdit() trigger doesn't work

I want to run a function that updates some values when I edit one cell of a column. This line of the trigger works well: dataCell0.setValue(today_date(new Date())[2]);. But this other line updatePercent(); doesn't. But if I call this updatePercent() function from a time based trigger (in Resources), it works well. What is going wrong with this updatePercent() call?
function onEdit(){
var s = SpreadsheetApp.getActiveSheet();
if( ( s.getName() == "mySheet1" ) || (s.getName() == "mySheet2") ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( s.getRange(1, r.getColumn()).getValue() == "PORCENT_TIME") { // If you type a porcent, it adds its date.
var dataCell0 = r.offset(0, 1);
dataCell0.setValue(today_date(new Date())[2]);
updatePercent();
}
}
}
Here the updatePercent function code:
/**
* A function to update percent values accoding to input date.
**/
function updatePercent() {
var sheet = SpreadsheetApp.getActiveSheet();
var column = getColumnNrByName(sheet, "PORCENT_TIME");
var input = sheet.getRange(2, column+1, sheet.getLastRow(), 4).getValues();
var output = [];
for (var i = 0; i < input.length; i++) {
var fulfilledPercent = input[i][0];
Logger.log("fulfilledPercent = " + fulfilledPercent);
var finalDate = input[i][3];
Logger.log("finalDate = " + input[i][3]);
if ( (typeof fulfilledPercent == "number") && (finalDate instanceof Date) ) {
var inputDate = input[i][1]; // Date when input was added.
var restPorcentPen = 100 - fulfilledPercent;
var restantDays = dataDiff(inputDate, finalDate);
var percentDay = restPorcentPen/restantDays;
Logger.log("percentDay = " + percentDay);
var passedTime = dataDiff(inputDate, new Date());
Logger.log("passedTime = " + passedTime);
var passedPorcent = passedTime * percentDay; // How much percent this passed time is?
Logger.log("passedPorcent = " + passedPorcent);
var newPorcent = (fulfilledPercent + passedPorcent);
newPorcent = Math.round(newPorcent * 100) / 100;
Logger.log("newPorcent = " + newPorcent);
var newInputDate = hoje_data(new Date())[2]; // Now update the new input date
// newPorcent = newPorcent.toFixed(2);
output.push([newPorcent, newInputDate]);
sheet.getRange(2, column+1, output.length, 2).setValues(output);
Logger.log(" ");
var column25Dec = getColumnNrByName(sheet, "PORCENT_25DEZ");
var passedTimeSince25Dec = dataDiff(new Date(2013,11,25), new Date()); // Months: January is 0;
var decPercent = (newPorcent - (passedTimeSince25Dec * percentDay)); // .toFixed(2).replace(".", ",");
decPercent = Math.round(decPercent * 100) / 100;
// if (sheet.getRange(output.length+1, column25Dec+1).getValues() == ''){
sheet.getRange(output.length+1, column25Dec+1).setValue(decPercent );
// }
var remainingYears = dataDiffYears(new Date(), finalDate);
sheet.getRange(output.length+1, column).setValue(remainingYears);
}
else {
newPorcent = "Put a final date"
output.push([newPorcent, inputDate]);
sheet.getRange(2, column+1, output.length, 2).setValues(output);
}
if (finalDate instanceof Date){
var remainingYears = dataDiffYears(new Date(), finalDate);
// Logger.log("remainingYears = " + remainingYears);
}
else {
remainingYears = "insert a valid date";
}
sheet.getRange(output.length+1, column).setValue(remainingYears);
}
}
I will guess you're using the new gSheets. Check if it will work in the old-style sheets. The new sheets' onEdit trigger has problems, particularly with getActive.
My problem was in the updatePercent() funciton. Thank you, guys!

How to automatically delete rows that contain a date with more than 3 days offset to the past from now?

I am trying to get a script going that will automatically delete rows with a date over 3 days old (4 days on)
I found this script that I was hoping to be able to adapt:
function DeleteOldEntries() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//give your sheet name below instead of Sheet1
var sheet = ss.getSheetByName("Foglio1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i = lastrow; i >= 2; i--) {
var tempdate = sheet.getRange(i, 1).getValue();
if (tempdate < oneweekago) {
sheet.deleteRow(i);
}
}
}
But there seems to be an error in the script itself that I need to figure out before adapting it to 4 days instead of 7 (that part is easy)
My sheet has 3 columns with the date in column C if that info is helpful
"date in column C, if that info is helpful"
It is indeed ! instead of trying to get a date in column A as it it done in this line :
var tempdate = sheet.getRange(i, 1).getValue();
you should look at the value in column C like this :
var tempdate = sheet.getRange(i, 3).getValue();
but to be more efficient you should do these comparisons at array level, try it like below and it will run much faster ...
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Foglio1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][2];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < oneweekago)
{
sheet.deleteRow(i);
}
}
}
It will be much much faster if your rows are in order of date, newest at the top and you delete all the rows at once and not one at a time.
function deleteOldData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("CallHub1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var daysago = new Date().setDate(currentDate.getDate() - 3);
var yearago = new Date().setDate(currentDate.getDate() - 365);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][0];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < daysago) {
if(tempdate < yearago) {continue;}
sheet.deleteRows(1, i);
break;
}
}
}