I am trying to add another line of code to this code to get the 'green' cells to switch back to 'yellow' after a given amount of time. would I add another function or add another else statement? Is it possible to nest the utilities.sleep function in one more time and only trigger it if a greater than condition is met?
In addition if I wanted this to go across rather than columns and pinpoint specific cells that represent tables. Think of a hostess with her seating chart could this be done in the offset clause for rows. and could this code also be run on another sheet and just show the checkboxes to the hostess while the color change and time stamp are run on another sheet?
Right now I have created a time stamp that only satisfies 2 conditions. Un clicked go to green and clicked go to red after a certain amount of time. If I need to create another function who would I run both functions or do I just add more var to the current function to include satisfying my 3rd condition of green to yellow showing a stag-net table ready to be seating while red is showing they have been at the table a long time but its still occupied
function onEdit(e) {
var s = SpreadsheetApp.getActiveSheet(); // the active sheet (no need to check if the sheet == sheet1 as the active sheet will always be the one that's being edited)
var r = e.range; // the range of the edited cell
var c = r.getColumn(); // the column of the range
var timeDelay = 5; // number in seconds
var checkbox = r.getValue(); // the value of the checkbox after being
edited
var date = new Date(); // the date for the timestamp
if (c == 3 && checkbox === true) { // if the checkbox has been checked,
change the color to red
var nextCell = r.offset(0,1);
Utilities.sleep(timeDelay * 100); // Utilities.sleep takes a number in
milliseconds
nextCell.setValue(date).setBackground("red");
} else if (c == 3 && checkbox === false){ // unchecked switch to green
var nextCell = r.offset(0,1);
nextCell.setValue(date).setBackground("green");
Utilities.sleep(timeDelay * 1);
}
}
any time I try to add another else statement I can not and if I add another condition to the green else if to get it to turn to yellow after x amount of minutes it skips go to green and goes right to yellow instead of vacillating between the two
Perhaps you could use something like this:
function onEdit(e) {
var r = e.range;
var c = r.columnStart;
var date = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyyMMdd HH:mm:ss");
if(e.range.columnStart==3 && e.value) {
switch (Number(e.value)) {
case 1:
e.range.offset(0,1).setValue(date).setBackground("red");
break;
case 2:
e.range.offset(0,1).setValue(date).setBackground("green");
break;
default:
e.range.offset(0,1).setValue(date).setBackground("yellow");
break;
}
}
}
Related
I'm trying to have my sheet trigger an email alert when the last row on certain column matches an if statement after a google form feeds the sheet. it worked the first time but when i try to do a second condition it only acomplishes the second if. so separated the ifs work, but not combined.
can you guys help? here is the function:
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Observaciones Diarias IMPRG");
var lr = ss.getLastRow();
var currentTemp = ss.getRange(lr, 6).getValue();
var currentkidName = ss.getRange(lr, 3).getValue();
var currentTexture = ss.getRange(lr, 15).getValue();
if(currentTemp >39) {
MailApp.sendEmail("xxx25#gmail.com","Temperature>39°Alert", currentkidName + " had atemperature of " + currentTemp + "° " +" which is extremely high, please check")
}
else if (currentTexture = 1){
MailApp.sendEmail("xxx#gmail.com","Texture Alert", currentkidName + " had a " + " liquid Evacuation. which indicates an issue, please check")
}
}
currentTexture = 1 this is asigning a 1 to currentTexture. To do a comparison use
currentTexture == 1
or
currentTexture === 1
Related
Google Script checking that the data within one column on one sheet is the same as another column in another sheet
How do I find the cell with a certain background color, and set background of different cell in relation to it?
How to set a variable based on other variables
I'm trying to make an id searcher which does a thing when you input the right id. However, the if statement always runs. Why is this?
I'm close, but my logic just isn't quite working. I am able to run the code below within Google Sheets Scripts to create a calendar event for each row in the sheet. I am trying to get it to only create an event when a new row is entered and to only read the spreadsheet until it comes to the first column/row being empty/null. enter image description here
Here is the associated code:
function createCalendarEvent() {
var sheet = SpreadsheetApp.getActiveSheet();
var calendar = CalendarApp.getCalendarById('dentaldigitaldesign.bkp#gmail.com');
var startRow = 100; // First row of data to process - 100 exempts my header row and adds to the case number count.
var numRows = sheet.getLastRow(); // Number of rows to process
var numColumns = sheet.getLastColumn();
var dataRange = sheet.getRange(startRow, 1, numRows-1, numColumns);
var data = dataRange.getValues();
var complete = "TRUE";
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var caseID = row[0]; //Case ID Number
var patient = row[4]; //Patient Name
var doctor = row[5]; //Doctor
var contact = row[14]; //Doctor contact info
var tooth = row[15]; //Tooth number
var shade = row[10]; //Tooth Shade
var notes = row[8]; //Notes
var callNotes = row[7]; //Call notes if there are any
var timeStamp = new Date (row[2]); //Retrieve the timestamp field
// year as 4 digits (YYYY)
var year = timeStamp.getFullYear();
// month as 2 digits (MM)
var month = ("0" + (timeStamp.getMonth() + 1)).slice(-2);
// date as 2 digits (DD)
var day = ("0" + timeStamp.getDate()).slice(-2);
var dueDate = new Date(month + day, + year); //Due date
var rDate = new Date(row[2]-1); //Remind date
var caseComplete = row[3]; //Case marked as complete
if (caseComplete !== complete && caseID !== null) {
var currentCell = sheet.getRange(startRow + i, numColumns);
calendar.createEvent(patient, rDate, rDate, {
description: doctor + '\r' + patient + '\r' + contact + '\r' + dueDate + '\r' + tooth + '\r' + shade + '\r' + notes + '\r' + callNotes
});
currentCell.setValue(complete);
}
}
}
When these events are created, they are all created for 8:59am. Ideally, I could do a check on the calendare if an event is set for that time, a new event is added immediately after. (perhaps in 15min or 30min slots). For now it works well for me to get the reminders on cases that are due, but eventually an invite to the doctor for them to know the due date might work well, too.
I can also use help in formatting the description field as it is not pushing the return value and everything is on one line.
And finally, the script continues to run on numerous fields beyond the scope of the desired rows, ultimately ending up with the script failing because too many event attempts are created in too short a time. (all the attempts with fields that are empty do not result in any events being created, but it is a resouce issue....and who knows maybe Google eventually blocks me?)
I appreciate any help that can be offered.
Here is the link to the Google Sheet. No data on it is sensitive as it is only test data: https://docs.google.com/spreadsheets/d/1M9qYzSl1PnRv-GehHEYvpiag15UI_GjnanA0wgA4xmg/edit?usp=sharing
There are several issues with your code, causing this expression to always return true, so that the script tries to create an event for each row:
if (caseComplete !== complete && caseID !== null) {
Empty string !== null:
You want to check whether the cell in column A is empty (that is, whether its value is an empty string), and to do that you are comparing its value to null. null is not the same as an empty string, so the following expression will always be true (a cell value never returns null):
caseID !== null
You should be comparing this to an empty string. For example, like this:
caseID !== ""
So the if statement should be:
if (caseComplete !== complete && caseID !== "") {
Wrong complete column:
Once an event has been created, you want to set the corresponding cell in D to TRUE. You're not doing that, since you specify the last column in the sheet (numColumns) when setting the currentCell:
var currentCell = sheet.getRange(startRow + i, numColumns);
Because of this, the value in D never changes to TRUE, so caseComplete !== complete is always true.
You should specify the correct column index for D instead, which is 4. It should be like this:
var currentCell = sheet.getRange(startRow + i, 4);
Edit: Also, the retrieved value for cell with checked checkboxes is the boolean true, and you're trying to compare it with the string TRUE. Because of this, this condition is not working correctly. Please change:
var complete = "TRUE";
To
var complete = true;
Wrong number of rows in source range:
You want to get the value from row 100 till the last one in the sheet. In this case, the total number of rows in the range should be the last row (numRows) minus the first row in the range (startRow) plus one (numRows - startRow + 1). The dataRange should be defined like this instead:
var dataRange = sheet.getRange(startRow, 1, numRows - startRow + 1, numColumns);
Reference:
Class Range
null
I am working on a course registration system.I need to check for time conflicts.
Already registered courses object:
{"00001":{"days":"Monday-Tuesday","hours":"11:40-12:30*13:40-15:30"}}
this means that 00001 course is in monday 11:40-12:30 in tuesday 13:40-15:30
Courses to register object:
{"00003":{"days":"Friday","hours":"9:40-10:40"}}
I have managed to check is student already registered to course with this code:
Object.keys(registeredcoursesobject).forEach(function(key){
if( Object.keys(coursestoregisterobject).includes(key)) {
alert("You have already registered to "+key+" crn number course");
//return;
}
});
A course can be at most 2 days in a week and in 1 different time intervals(what if 2 time intervals??) which means that there will be only one "-" in days property and only one "*" in hours property.
I am new to programming and working on this for days any ideas ?
I hope this answer is still relevant for you. Here is what I have:
var registeredcoursesobject = {"00001":{"days":"Monday-Thursday","hours":"11:40-12:30*16:30-18:30"}}
var coursestoregisterobject = {"00002":{"days":"Monday-Friday","hours":"10:40-15:30*16:40-18:00"}}
var getTicks = function(timeStr) {
return new Date('1970-01-01T' + timeStr + ':00Z').getTime();
}
Object.keys(registeredcoursesobject).forEach(function(rKey){
if( Object.keys(coursestoregisterobject).includes(rKey)) {
alert("You have already registered to "+rKey+" crn number course");
return false;
};
Object.keys(coursestoregisterobject).forEach(function(cKey){
var regDays = registeredcoursesobject[rKey].days.split('-');
var regHours = registeredcoursesobject[rKey].hours.split('*');
var courseDays = coursestoregisterobject[cKey].days.split('-');
var courseHours = coursestoregisterobject[cKey].hours.split('*');
regDays.forEach(function(rDay, i) {
var rHourRange = regHours[i];
// I assume you need to check there is same date/time pain in registeredcoursesobject and coursestoregisterobject
courseDays.forEach(function(cDay, j) {
if (rDay == cDay) {
var cHourRange = courseHours[j];
// now, do you need to compare hours be equal exactly or do you need to check time overlap?
// assume you just need to ckeck hour ranges are equal, then:
if (rHourRange == cHourRange){
// means equal
alert("You have already registered to "+cKey+" crn number course on day "+cDay+" at "+cHourRange+" hours.");
return true;
}
// if you need to check range overlap
var rTime = rHourRange.split('-');
rTimeRange = [getTicks(rTime[0]), getTicks(rTime[1])];
rStartT = Math.min.apply(null, rTimeRange), rEndT = Math.max.apply(null, rTimeRange);
var cTime = cHourRange.split('-');
cTimeRange = [getTicks(cTime[0]), getTicks(cTime[1])]
cStartT = Math.min.apply(null, cTimeRange), cEndT = Math.max.apply(null, cTimeRange);
// now your rangeTime is a pair of int values, that represent time range rStartT:rEndT
// and your courseTime is a pair of int values cStartT:cEndT
// so now you just check the overlap of two integer pais.
// according to this: https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-two-integer-ranges-for-overlap#answer-3269471
if (rStartT < cEndT && cStartT < rEndT) {
alert("You have already registered to "+cKey+" crn number course on day "+cDay+" within time range "+cHourRange+" hours overlap with "+rHourRange+" time range.");
// means time ranges are overlap at some range. But I don't count the border, like "14:00-15:00" and "15:00-16:00" do not overlap
// otherwise replace < with <=
return true;
}
}
})
});
return false;
});
});
I am making some assumptions here about your task.
UPDATE: added time range check.
UPDATE: check keys equal first and values swap if start time is for some reason is bigger than end time.
I found this script (below) and it works when simply typing in the number zero into Column G but it does not work when the result of column G comes from subtracting the values of column E and F. When the values become 0, it is left in the sheet "default". Any help would be appreciated. I have searched and find nothing about how this works when applied to the result of a formula. Thanks!
function onEdit() {
// moves a row from a sheet to another when a magic value is entered in a column
// adjust the following variables to fit your needs
// see https://productforums.google.com/d/topic/docs/ehoCZjFPBao/discussion
var sheetNameToWatch = "default";
var columnNumberToWatch = 7; // column A = 1, B = 2, etc.
var valueToWatch = 0;
var sheetNameToMoveTheRowTo = "toMoveTo";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
}
}
the script works as intended. I created a test spreadsheet with the script and did the following tests:
Enter random numbers in Column A — as expected nothing happened
Entered 0 in Column A — as expected nothing happened.
Entered random number in Column G (7) — nothing happened
Entered 0 in Column G — that row was moved to the other sheet
Entered 5 in columns E and F and =E3-F3 which equals to 0 (in that order) — row was moved to the other sheet
Entered 5 in column E and 4 in column F and in column G I wrote the formula =E3-F3 which resulted in 1. After that, I changed F4 to value 5 and formula recalculates to 0 — as expected, the row is not moved.
Please make sure that the formula actually returns a value of 0. It may be that your cell is formatted to write 0.1 as 0 and the formula returns a number 0 < n < 1 which would not be moved as it must be exactly 0 in order for this to work. If you wish to move values greater than 0 but less than 1, introduce a Math.floor() against the read value.
In test scenario 6 we have to note that the script does not account for changes made to any column other than G (column number 7) because you are only watching var range = sheet.getActiveCell(); so if you change anything other than the column where you are supposed to have 0 it will not do anything because of the following if statement part range.getColumn() == columnNumberToWatch
I'm new to using the DocumentApp in Google Apps, so looking for some help!
I'm trying to create an FAQ (in a Google Doc) automatically from a spreadsheet. If certain conditions are met in the spreadsheet row, I want the script to find the category of the question in the document and insert a new question and response underneath it (pushing anything already there back).
So I'd have a document that looks like this:
https://docs.google.com/document/d/1fjb3RO6hUY6n7x0bu6WvtcleMWRNC8VQ9U82hXiGqcY/edit?usp=sharing
And a spreadsheet that looks like this:
https://docs.google.com/spreadsheets/d/1fb3ceqP6142_C7QQ1PfkWtVNswOyzOxkWCofvauf4Ps/edit?usp=sharing
And this is the code I'm trying to use. I'm getting a ton of errors- mainly because I don't have a good grasp on what the different elements involved are. Can anyone point me in the right direction?
function insertnewquestion() {
//(works fine)Get active document and related spreadsheet
var doc = DocumentApp.getActiveDocument().getBody();
var ss = SpreadsheetApp.openById("xxxxxxx");
var sheet = ss.getSheetByName("xxxxx");
//(works fine)Go through the various rows in the spreadsheet up to the last row
for (var row = 2; row <= sheet.getLastRow(); ++row) {
var status = sheet.getRange(row,4).getValue();
var question = sheet.getRange(row,1).getValue();
var response = sheet.getRange(row,2).getValue();
var category = sheet.getRange(row,3).getValue();
var date = sheet.getRange(row,5).getValue();
//(works fine)find rows with blank status and a response filled in
if (status !== "Entered" && response !== "") {
//(errors! this is where i need help) find the pertinent header
var categoryposition = body.findText(category); //looking for the category header- new text should be added after this, the idea is that what was already under this header will move down
var questionheader = categoryposition.appendText(question); //trying here to add in question text after where the category was found
questionheader.setHeading(DocumentApp.ParagraphHeading.HEADING3); //set question text as heading 3 (so it shows up on table of contents)
questionheader.appendText("\r"+"\r"+response+"\r\r"); //add line breaks and then the response text in normal font, then more line breaks to put space between new stuff and old stuff
//(works fine)Mark in the spreadsheet that it was entered in FAQ and the date so that it isn't double entered next time the script runs
sheet.getRange(row,4).setValue("Entered");
var currentTime = new Date()
var month = currentTime.getMonth() + 1
var day = currentTime.getDate()
var year = currentTime.getFullYear()
var date = (month + "/" + day + "/" + year)
sheet.getRange(row,5).setValue(date);
}
else {continue}
}
//(need help!) Refresh table of contents to include new questions
//no idea how to do this!
}
In the code you are referring to body.findText(category); where it should be doc.findText(category);. Also for the line:
var categoryposition = body.findText(category);
it returns the RangeElement — a search result indicating the position of the search text, or null if there is no match
Before adding any lines of code you have to check for null value in categoryposition.
The text class has a method to insert text in particular offset value to particular String value gives as shown here.
Hope that is helpful.