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';
}
}
Related
can someone help me figure what's wrong with my logic?, i'm new using google script app and stuck around a week and got this error
Error message:
TypeError: d1.getTime is not a function (inDays)
var DateDiff = {
inDays: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
Logger.log("t1" + t1)
return parseInt((t2-t1)/(24*3600*1000)+1);
}
}
var dateStr = data[m][xMonth].toString() // the value here is =>1/10/2022
var todayDate = new Date();
if(dateStr.toString().includes('/')){
var yearA = '20'+dateStr.substring(6, 8)
var monthA = +dateStr.substring(3, 5)
if(monthA.toString() != '11' || monthA.toString() != '12') monthA = '0'+monthA
var dayA = +dateStr.substring(0, 2)
var tempDate = yearA + monthA + dayA
var Ryear = +tempDate.substring(0, 4)
var Rmonth = +tempDate.substring(4, 6)
var Rday = +tempDate.substring(6, 8)
var newDate = new Date(Ryear, Rmonth - 1, Rday)//because month start from 0
var realDueDate = DateDiff.inDays(todayDate, newDate) // error here in var newDate
}
Try this:
function myFunk() {
const D2 = new Date();
const D1 = new Date(D2.getFullYear(),D2.getMonth() - 2,D2.getDate());
var DateDiff = {
d1:D1,d2:D2,
inDays: function () {
let t2 = this.d2.getTime();
let t1 = this.d1.getTime();
return parseInt((t2 - t1) / (24 * 3600 * 1000) + 1);
}
}
Logger.log(DateDiff.inDays());
}
Execution log
10:58:41 AM Notice Execution started
10:58:39 AM Info 62.0
10:58:41 AM Notice Execution completed
I have code snippet below for grouping records for last 12 months and it works properly but I just noticed that empty months is not included. Where did I go wrong?
Thanks in advance
public IQueryable<DashboardGrouping> DashboardStats()
{
var yearAgo = DateTime.Now.AddYears(-1);
var date = new DateTime(yearAgo.Year, yearAgo.Month, 1);
var items = context.Set<Transaction>()
.Where(x => x.IsActive &&
x.CreatedAt.HasValue && x.CreatedAt.Value.Date >= date.Date && x.PaymentStatusId ==
PaymentStatus.Completed)
.Include(x => x.Payment)
.Include(x => x.Branch)
.AsNoTracking()
.Select(x => new
{
Year = x.CreatedAt.Value.Year,
Month = x.CreatedAt.Value.Month,
CashAmount = x.Payment.CashAmount,
CardAmount = x.Payment.CardAmount,
})
.GroupBy(x => new
{
Year = x.Year,
Month = x.Month,
})
.Select(x => new DashboardGrouping
{
Year = x.Key.Year,
Month = x.Key.Month,
TotalSale = x.Sum(s => s.CashAmount + s.CardAmount)
});
return items;
}
You can do client-side postprocessing and enrich result with missing records.
Helper function for generating months:
static IEnumerable<DateTime> GetMonths(DateTime startDate, DateTime endDate)
{
startDate = new DateTime(startDate.Year, startDate.Month, 1);
endDate = new DateTime(endDate.Year, endDate.Month, 1);
while (startDate < endDate)
{
yield return startDate;
startDate = startDate.AddMonths(1);
}
}
Postprocessing:
var currentDate = DateTime.Now;
var yearAgo = currentDate.AddYears(-1);
var months = GetMonths(yearAgo, currentDate);
var stats = DashboardStats().ToList();
// left join months to actual data
var query =
from m in months
join s in stats on new { m.Year, m.Month } equals new { s.Year, s.Month } into gj
from s in gj.DefaultIfEmpty()
select s ?? new DashboardGrouping
{
Year = m.Year,
Month = m.Month,
TotalSale = 0
};
var result = query.ToList();
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.
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.
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!