Here is what I want to do:
I got a date range from e.g. 03.04.2013 to 23.04.2013 - that's my main range.
Now I have the possibility to create some own time ranges (e.g. 04.04.2013 to 09.04.2013 and 11.04.2013 to 23.04.2013). Those have to cover the whole main range, so every day of the main range (excluding weekens) needs an corresponding day in my own time ranges.
My plan would be to create an Array for the main range. Then I check each day of my own time ranges against the main range. If there is an accordance, I would remove the day from the main range.
So in the end, if everything is ok, there would be an emtpy array, because all days are covered by my own time ranges. If not, then the days not covered would still be in the main range and I could work with them (in this example: 03.04.2013, 10.04.2013)
Does anybody have an better idea to solve this problem? NotesDateTimeRanges?
I would add the dates into a sorted collection and then a "pirate algorithm". Look left, look right and if any of the looks fails you can stop (unless you want to find all missing dates).
Off my head (you might need to massage the final list to store the value back):
var AbsenctSince:NotesDateTime; //Start Date - stored in the NotesItem
var endDate:NotesDateTime; // Return, could be in Notes or Today
var wfDoc:NotesDocument = docApplication.getDocument();
var responseCDs:NotesDocumentCollection = wfDoc.getResponses();
var docResponse:NotesDocument;
var nextResponse:NotesDocument;
//Get the date, which limits the function - if there is a return information, then this is the limit, else today
AbsenctSince = wfDoc.getDateTimeValue("AbsentSince") ;
if (wfDoc.hasItem("ReturnInformationDat")) {
endDate = wfDoc.getDateTimeValue("ReturnInformationDat");
} else {
endDate = session.createDateTime("Today");
}
//Get all days between two dates - as pure Java!
var dateList:java.util.List = getWorkDayList(AbsenctSince.toJavaDate(), endDate.toJavaDate());
// Looping once through the reponse documents
var docResponse = responseCDs.getFirstDocument();
while (docResponse != null) {
nextResponse = responseCDs.getNextDocument(docResponse);
var CDValidSince:NotesDateTime = docResponse.getDateTimeValue("CDValidSince");
var CDValidTill:NotesDateTime = docResponse.getDateTimeValue("CDValidTill");
// Now we need get all days in this range
var removeDates:java.util.List = getWorkDayList(CDValidSince.toJavaDate(),CDValidTill.toJavaDate());
dateList.removeAll(removeDates);
docResponse.recycle();
docResponse = nextResponse;
}
// Both docs are null - nothing to recycle left
// Now we only have uncovered dates left in dateList
docApplication.replaceItemValue("openDates", dateList);
// Cleanup
try {
AbsenctSince.recycle();
endDate.recyle();
wfDoc.recycle();
responseCDs.recycle();
} catch (e) {
dBar.error(e);
}
function getWorkDayList(startDate, endDate) {
var dates:java.util.List = new java.util.ArrayList();
var calendar:java.util.Calendar = new java.util.GregorianCalendar();
calendar.setTime(startDate);
while (calendar.getTime().before(endDate)) {
var workDay = calendar.get(calendar.DAY_OF_WEEK);
if (workDay != calendar.SATURDAY && workDay != calendar.SUNDAY) {
var result = calendar.getTime();
dates.add(result);
}
calendar.add(java.util.Calendar.DATE, 1);
}
return dates;
}
I've done it this way now (seems to work so far):
var dateArray = new Array();
var responseCDs:NotesDocumentCollection = docApplication.getDocument().getResponses();
var dt:NotesDateTime = session.createDateTime("Today");
var wfDoc = docApplication.getDocument();
dt.setNow();
//Get the date, which limits the function - if there is a return information, then this is the limit, else today
var AbsenctSince:NotesDateTime = session.createDateTime(wfDoc.getItemValue("AbsentSince").toString().substr(0,19));
if (wfDoc.hasItem("ReturnInformationDat")) {
var endDate:NotesDateTime = session.createDateTime(wfDoc.getItemValue("ReturnInformationDat").toString().substr(0,19));
} else {
var endDate:NotesDateTime = session.createDateTime("Today");
}
//Get all days between two dates
dateArray = getDates(AbsenctSince, endDate);
for (var i=dateArray.length-1; i >= 0 ; i--) {
var checkDate:NotesDateTime = session.createDateTime(dateArray[i].toString().substr(0,19));
var day = checkDate.toJavaDate().getDay();
//Remove weekends first
if ((day == 6) || (day == 0)) { //6 = Saturday, 0 = Sunday
dBar.info("splice: " + dateArray[i]);
dateArray = dateArray.splice(i,1);
} else {
var docResponse = responseCDs.getFirstDocument();
//Work through all response docs to check if any date is covered
while (docResponse != null) {
var CDValidSince:NotesDateTime = session.createDateTime(docResponse.getItemValue("CDValidSince").toString().substr(0,19));
var CDValidTill:NotesDateTime = session.createDateTime(docResponse.getItemValue("CDValidTill").toString().substr(0,19));
//checkDate covered? If yes, it will be removed
if (checkDate.timeDifference(CDValidSince)/86400 >= 0 && checkDate.timeDifference(CDValidTill)/86400 <= 0 ) {
dBar.info("splice: " + dateArray[i]);
dateArray = dateArray.splice(i,1);
}
docResponse = responseCDs.getNextDocument();
}
}
}
docApplication.replaceItemValue("openDates", dateArray);
And I'm using this function (adopted from this question here):
function getDates(startDate:NotesDateTime, endDate:NotesDateTime) {
var dateArray = new Array();
var currentDate:NotesDateTime = startDate;
while (endDate.timeDifference(currentDate) > 0) {
dateArray.push( currentDate.getDateOnly() );
currentDate.adjustDay(1);
}
return dateArray;
}
Related
Hi i want to compare column with date (i.e "Referral Date" column)
with present day , here is what i have
function newF(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Worksheet');
var range = ss.getDataRange();
var headers = range.getValues()[0];
var colIndex = headers.indexOf("Referral Date");
var today = new Date();
var searchRange = ss.getRange(2,colIndex+1,ss.getLastRow()-1);
for (i=0;i<range.getLastRow();i++){
var dates = searchRange.getValues();
if (today.valueOf()>dates.valueOf()){
updatelFilter()
} else{
SpreadsheetApp.getUi().alert('Future Date Error');
break;
}
}
}
The problem i have is, it throws alert Future Date Error irrespective of date in column (Referral Date). Let me know if additional information is required.
My goal:
1)if date column (Referral Date) is greater than present date : Throw alert error & should not run updateFilter
2)if (Referral Date) is lesser than present date: Run updateFilter function
Issues
searchRange.getValues() yields a two dimensional array. So dates[0][0] points to a date, while dates[0] points to an array.
var dates = searchRange.getValues(); is being called inside the loop repeatedly, when it should ideally be called outside once since the value will not change; calling it inside the loop is costly and redundant
for (i=0;i<range.getLastRow();i++){ the condition can be replaced with i<dates.length if point 2 is followed
if (today.valueOf()>dates.valueOf()){ I believe is supposed to have dates[0] instead
Modified Code
function newF(){
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Worksheet');
var range = ss.getDataRange();
var headers = range.getValues()[0];
var colIndex = headers.indexOf("Referral Date");
var today = new Date();
var searchRange = ss.getRange(2,colIndex+1,ss.getLastRow()-1);
var dates = searchRange.getValues().map(d=>d[0]);
for (i=0;i<dates.length;i++) {
if (today.valueOf()>dates[i].valueOf()){
updateFilter()
} else {
SpreadsheetApp.getUi().alert('Future Date Error');
break;
}
}
}
To run updateFilter only if no future dates
Replace the loop with the following -
if(dates.some(d => today.valueOf() < d.valueOf())) {
SpreadsheetApp.getUi().alert('Future Date Error');
} else {
for (let i=0; i<dates.length; i++) {
updateFilter();
}
}
Hi so I have a class Calculations with a series of functions one of these is keplerianElementsToEcef. In my view controller I hard code the values for the parameters and then call the function. However later on in a seperate class I have a bool isInRange. If my spacecraft is out of cellular range, I return false and a string as well. I also want to then iterate through the keplerianElementsToEcef function, each time increasing the timeOfCalculation parameter by two minutes until at some point in time in the future the satellite is in range.
I've tried to simply call the function but increase the value used initially as the time, current time, by two minutes. The other variables rangeMeanMotion etc, are the same as those hardcoded in the view controller
var isInRange: Bool
var rangeString: String
if distance < range {
isInRange = true
rangeString = "In Range"
} else {
isInRange = false
rangeString = "Not In Range"
while isInRange == false {
var dateString = dateFormatter.date(from: calculationTime!)!
var updatedDate = dateString.addingTimeInterval(TimeInterval(5.0 * 60.0))
var updateDateAsString = dateFormatter.string(from: updatedDate)
Calculations.shared.keplerianElementsToECEF(meanMotion: rangeMeanMotion, eccentricity: rangeEccentricity, Inclination: rangeInclination, LongitudeAscendingNode: rangeLongitudeAscendingNode, argumentPerigee: rangeArgumentPerigee, M0: rangeM0, epoch: rangeEpoch, date: updateDateAsString) {
}
}
}
In the function parameters under date: updateDateAsString I get the following error: Extra argument 'date' in call
var timeOfCalculation : TimeInterval = 0
func doItUntilSpacecraftIsInRange(){
repeat {
timeOfCalculation += TimeInterval(2.0 * 60.0)
Calculations.shared.keplerianElementsToECEF(meanMotion: rangeMeanMotion, eccentricity: rangeEccentricity, Inclination: rangeInclination, LongitudeAscendingNode: rangeLongitudeAscendingNode, argumentPerigee: rangeArgumentPerigee, M0: rangeM0, epoch: rangeEpoch, date: updateDateAsString)
} while spacecraft.isInRange == false
}
doItUntilSpacecraftIsInRange()
I solved this issue. I made the statement iterate during a certain time period (1 day) and my code looks like this:
else {
isInRange = false
rangeString = "Not In Range"
print(calculationTime)
if let calcTime = calculationTime {
let parsedDate = dateFormatter.date(from: calcTime) ?? Date()
for interval in stride(from: 0, to: 1440, by: 2) {
var updatedDate = parsedDate.addingTimeInterval(TimeInterval(interval * 60))
var updateDateAsString = dateFormatter.string(from: updatedDate)
Calculations.shared.keplerianElementsToECEF(meanMotion: rangeMeanMotion, eccentricity: rangeEccentricity, Inclination: rangeInclination, LongitudeAscendingNode: rangeLongitudeAscendingNode, argumentPerigee: rangeArgumentPerigee, M0: rangeM0, epoch: rangeEpoch, date: updateDateAsString)
let xDistance = ecefX - wgs84X
let yDistance = ecefY - wgs84Y
let zDistance = ecefZ - wgs84Z
let iteratedDistance = sqrt(xDistance*xDistance + yDistance*yDistance + zDistance*zDistance)
if iteratedDistance < 7000 {
nextVisible = updateDateAsString
break
}
}
}
}
I want to make a script that send me mail whith the content of what I've enterd in a form some days after the form is submitted. As a help for students to study. In the form enter what to study, then 1 day, 7 days and 28 days later get that in a mail.
I've made a form that collect time, recipient adress, subject and body for the mail. These are saved in a Google spreadsheet.
The code kind of work. But it send all of the mail from my test input in the sheet. I've added one 6 days ago, one yesterday and one today.
Today I should only get one mail and tomorrow two. But I get all of them today.
I think it's this line:
if (diffDays == 1 || diffDays == 7 || diffDays == 28) continue;
I've trided to change it, searched other ways of writing it, as array for example.
Here's the full code:
function createTimeDrivenTriggers() {
ScriptApp.newTrigger('reminder')
.timeBased()
.everyDays(1)
.atHour(16) // Change time of day here
.inTimezone("Europe/Stockholm")
.create();
}
function reminder() {
var today = new Date(); // Today
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
var headerRows = 1;
for (i=0; i<data.length; i++){
if (i < headerRows) continue;
var row = data[i];
var time = row[0];
// Get time difference
var timeDiff = Math.abs(today.getTime() - time.getTime());
var diffDays = Math.ceil((timeDiff) / (1000 * 3600 * 24)-1);
if (diffDays == 1 || diffDays == 7 || diffDays == 28) continue;
var recipient = row[1];
var subject = row[2];
var body = row[3];
// Send mail
GmailApp.sendEmail(recipient, subject, body)
}
}
Thanks
Make sure to execute the code only when your if statement is true.
Include all code after if statement in the statement itself, only executing it when diffDays = 1, 2 or 28.
function reminder() {
var today = new Date(); // Today
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
var headerRows = 1;
for (i=0; i<data.length; i++){
if (i < headerRows) continue;
var row = data[i];
var time = row[0];
// Get time difference
var timeDiff = Math.abs(today.getTime() - time.getTime());
var diffDays = Math.ceil((timeDiff) / (1000 * 3600 * 24)-1);
if (diffDays == 1 || diffDays == 7 || diffDays == 28) {
var recipient = row[1];
var subject = row[2];
var body = row[3];
// Send mail
GmailApp.sendEmail(recipient, subject, body)
}
}
}
Note that continue means "stop processing this iteration of whatever loop is getting executed, and begin the next iteration." So your script sends reminders on every day except the days you want to remind them.
Changing your test to an "AND NOT", moving the code for reminding inside the existing check, or using a more expressive syntax like switch will satisfy your intent.
switch (diffDays) {
case 1:
case 7:
case 28:
sendReminder(your, Args, Here);
break;
case 0:
sendWelcome(some, other, Args);
break;
...
default:
break;
}
...
function sendReminder(your, Args, Here) {
/* Code that uses function arguments to build and send an email */
}
"And not" meaning if (diffDay != 1 && diffDay != ...), i.e. "if it's not this, and not that, and not this other thing, and not..."
I have four date fields on a form and I need to alert the user when they have entered repetitive dates. I have already created an array that generates and checks the dates, but throwing the alert is not working for me. This is what I have so far.
else if ((dateRow1.text== dateRow2.text) || (dateRow1.text == dateRow3.text) || (dateRow1.text == dateRow4.text)) {
alert.show("You must have unique dates for each field");
Thanks.
You can check if your text fields are all distinct from each other:
var t:Array = [dateRow1, dateRow2, dateRow3, dateRow4];
var l:Number = t.length;
var i:Number;
var j:Number;
for (i = 0; i < l; i++) {
var ti = t[i]; // dateRow1... dateRow4
for (j in t) {
if (ti != t[j] && ti.text == t[j].text) trace(ti + "==" + t[j]);
}
}
I am trying to modify a script I found online that seems to make the event an all day event, which I don't want, I want it to be just the time specified in the form/spreadsheet.
The spreadsheet is located here - https://docs.google.com/spreadsheet/ccc?key=0ApxazoOhNSK-dGFvZVhVOTQ1X3F3aWh4QTh3Wm9sbFE#gid=0
Here is the script I am using, but its not adding...
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "<removed for privacy>";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 4;
var endDtId = 4;
var titleId = 2;
var titleId2 = 3;
var descId = 7;
var tstart = 4;
var tstop = 5;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var start = new Date(sheet.getRange(lr,tstart,1,1).getValue());
var end = new Date(sheet.getRange(lr,tstop,1,1).getValue());
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var subOn = "Submitted on :"+sheet.getRange(lr,formTimeStampId,1,1).getValue()+" by "+sheet.getRange(lr,titleId,1,1).getValue();
var desc = "Comments: "+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()+" "+sheet.getRange(lr,titleId2,1,1).getValue();
createEvent(calendarId,title,start,end,desc);
}
function createEvent(calendarId,title,start,end,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(sheet.getRange(lr,tstart,1,1).getValue());
var end = new Date(sheet.getRange(lr,tstop,1,1).getValue());
var loc = 'Computer Center';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
The original article is located here: http://bruceburge.com/2012/09/05/automatically-adding-events-to-a-google-calendar-from-a-google-form-submission/
I just can't seem to get the dates to work at all... If I use the original code it works fine, but the time is the full day, not the specified time... I seem to have broken it in an attempt to make it work... Any help would be appreciated...
It was a lot simpler than I though... I just removed some of his lines (the ones that set the hour and minutes to 0. Once I removed that and changed a few things, I get the following which works just great:
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "alcc.ccenter#gmail.com";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 4;
var endDtId = 5;
var titleId = 2;
var titleId2 = 3;
var descId = 7;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
var subOn = "Added :"+sheet.getRange(lr,formTimeStampId,1,1).getValue()+" by: "+sheet.getRange(lr,titleId,1,1).getValue();
var desc = "Comments :"+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()+" - "+sheet.getRange(lr,titleId2,1,1).getValue();
createEvent(calendarId,title,startDt,endDt,desc);
}
function createEvent(calendarId,title,startDt,endDt,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(startDt);
var end = new Date(endDt);
var loc = 'Computer Centre';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
My form has the following Columns - Timestamp, Name, Absence, Start, End, Reason, Comments. They didn't need to be ne word but I changed them to one word headings because of the video example I was trying to follow... But the above code works miracles.
I had to modify the way Forms handles dates to accommodate Calendar
function createEvent() {
var form = FormApp.getActiveForm();
var cal = CalendarApp.getDefaultCalendar();
var responses = form.getResponses();
var len = responses.length;
var last = len – 1;
var items = responses[last].getItemResponses();
var email = responses[last].getRespondentEmail();
var name = items[0].getResponse();
var bring = items[1].getResponse();
var date = items[2].getResponse();
Logger.log(date);
var replace = date.replace(/-/g,”/”);
Logger.log(replace);
var start = new Date(replace);
Logger.log(‘start ‘+start);
//Logger.log(newStart.getHours());
var endHours = 2+0+start.getHours();
//Logger.log(start.getDay());
var day = start.getDate();
var minutes = start.getMinutes();
var year = start.getFullYear();
var month = start.getMonth();
var hours = start.getHours();
var d = new Date(year, month, day, endHours, minutes);
Logger.log(d);
var event = cal.createEvent(‘Class Party ‘+name+’ brings ‘+bring, start, d)
.addGuest(email)
.setDescription(name+’ you will be bringing ‘+bring+’ to the party.’);
GmailApp.sendEmail(email, name + ’ a Google Calendar invite has been created for you’, name + ’ You filled out the Google Form for the date of ‘ + start + ’. Check your Google Calendar to confirm that you received the invite.\n’);
}