Create a condition in an OnEdit function - javascript

I have the following onEdit function
function onEdit(e) {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange('D2:D');
range.createTextFinder('[^0-9]').useRegularExpression(true).replaceAllWith(');
It removes all characters (text and special) from the cell, leaving only the numbers.
However, I would like it to be executed only if Column B says “after x hours”.
For example:
Cell B2 is equal to “após x horas”, so I want the above function to be executed in cell D2, when I enter something in it — that is, if I paste some data into D2, all characters will be removed, just sticking the numbers, because B2 is “após x horas”.
Cell B3 is equal to “7 dias ”, so the function should not be executed — that is, when I write something in cell D3, the characters CANNOT be removed.
How to do this?

You need to declare the two conditions and execute the replace action only when the conditions are met:
B2 = 'apox...'
B3 != '7 dias'
So your code should be like this:
let first_condition = "após x horas"
let second_condition = "7 dias"
function onEdit(e) {
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange('D2:D');
if (sheet.getRange('B2:B2').getValues()[0][0].trim() == first_condition
&& sheet.getRange('B3:B3').getValues()[0][0].trim() !== second_condition) {
range.createTextFinder('[^0-9]').useRegularExpression(true).replaceAllWith('');
console.log("Cleaning out non valid characters")
}
else {
console.log("Skipping the cleaning process")
}
}
You probably need to adjust the conditions and I suggest to remove the logs.

Related

Values are correct and within range but still sends an email

I have a Upper Limit and Lower Limit on my spreadsheet responses that I input towards the right of my responses. The limits are both on F2 and G2. F2 is Lower Limit and G2 is Upper Limit. The code is using the function onFormSubmit and it has an MailApp.sendEmail function that will send an email in case someone enters a figure that is out of the limit.
What I do not understand that, the value that I read when the form is submitted is actually within the range but it still triggers an email.
I have tried this code specifically on a brand new form and spreadsheet and it did not have any problem.
function onFormSubmit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Responses 1");
var speedUL = sheet.getRange("K2").getValue(); //250V
var speedLL = sheet.getRange("L2").getValue(); //207V
//var speedUL= parseInt(activess.getRange("K2").getValue()); //250V
//var speedLL = parseInt(activess.getRange("L2").getValue()); //207V
var speed1 = parseInt(e.values[2]);
if((speed1 >= speedUL) || (speed1 <= speedLL)){
console.log('SpeedUL: '+speedUL);
console.log('SpeedLL: '+speedLL);
console.log('Speed1: '+speed1);
var template1 = HtmlService.createTemplateFromFile("speed1");
template1.speed1 = speed1;
MailApp.sendEmail("someone#gmail.com ",
"Out of Range Notification Speed of VSD",
"",
{htmlBody : template1.evaluate().getContent()});
}else
{
return;
}
}
This is the test script that I am trying to do. With this code, I'm getting this
Error
Aug 26, 2019, 5:24:29 PM
TypeError: Cannot call method "getRange" of null.
at onFormSubmit(Code:7)
Line 7 refers to var speedUL = sheet.getRange("K2").getValue();
Probable Cause:
getRange() is called upon spreadsheet class (ss) and not on the sheet class (sheet). This usually means value of G2 and F2 of the first sheet is taken and not the specied sheet.
e.values is array of strings. Implicit conversion takes place when numbers are compared with strings. This is probably not the cause of your issue, but still needs to be addressed.
Solution:
Call getRange() on the sheet or specify the sheet name, when calling getRange() on spreadsheet.
Use explicit type conversion of e.value to number.
Snippet:
var temperature = Number(e.values[1]);
var temperatureUCL = ss.getRange("H3 Reponses!G2").getValue();
//or
var temperatureUCL = sheet.getRange("G2").getValue();
References:
Spreadsheet#getRange
Sheet#getRange

Using JS to create a dynamic seating chart

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;
}
}
}

How can I make this Google Apps Script loop efficiently?

I'm making an script that increases the value of a cell by 0.01 until it matches the value of another cell (gets the value, pass through a formula than see if the other cell value matches). The problem is that it takes too long to execute. It was very simple to do on excel, but I don't know how to program in G-Apps Script (neither js).
I guess it's taking too long because it runs on the cloud. There is anyway I can solve it?
Here the code so far:
function Calculate() {
var ss = SpreadsheetApp.getActive();
var vF = ss.getSheetByName('magic').getRange('C31').getValue();
ss.getSheetByName('magic').getRange('C32').setValue(0);
var vE = ss.getSheetByName('magic').getRange('C32').getValue();
var vP
for(vE=0;vE != vP;vE+=0.01){
ss.getSheetByName('magic').getRange('C32').setValue(vE);
var qParc = vF - vE;
ss.getSheetByName('magic').getRange('C3').setValue(qParc);
vP = ss.getSheetByName('magic').getRange('F3').getValue();
}
Thanks in advance!
More likely it's running "too long" because vE != vP is never false, because the kind of floating point used by JavaScript (IEEE-754 double-precision binary floating point, used by most programming languages) is inherently imprecise. Famously, 0.1 + 0.2 is not 0.3 (it's 0.30000000000000004). As a result, it's unreliable to use == or != (or === or !==) with possibly-fractional numbers. (You're okay if they're integers, provided they're not really big ones.)
There probably isn't any need for a loop if you want to update a value to make it match another. Just take the difference and add that to the one you're updating.
But if you do need the loop, replace != with <.
for (vE = 0; vE < vP; vE += 0.01) {
You're also repeating a lot of operations, perhaps expensive ones, there. Once you have the object for (say) a sheet or cell, remember that object reference and reuse it:
function Calculate() {
var ss = SpreadsheetApp.getActive();
var magic = ss.getSheetByName('magic');
var c32 = magic.getRange('C32');
var c3 = magic.getRange('C3');
var f3 = magic.getRange('F3');
var vF = magic.getRange('C31').getValue();
var vE, vP, qParc;
for (vE = 0; vE < vP; vE += 0.01) {
c32.setValue(vE);
qParc = vF - vE;
c3.setValue(qParc);
vP = f3.getValue();
}
}
(I also removed an unnecessary var vE = c32.getValue(); from that, since you immediately overwrite vE with 0 at the beginning of the loop. I just added the declaration to the var declaring vP and, now, qParc.)

Script not working when get value from a formula

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

Javascript - data filtering and removing line breaks

A list of isbn's are entered in the text area and javascript opens an amazon search for each one entered.
Isbn's can be between 10 or 13 digits.
Not all isbn searches start with an isbn, sometimes there can be information in front such as "isbn10:0195433831" so you cant count from the start.
For Example, this is a typical search:
0195433831 Good
0195433831 Poor
0195433831 Excellent
Question
Often times isbn's are entered in a different format breaking it, for example:
1) With spacing between numbers
978 0 132 76682 1 like new
978 0 495 38500 4 very good
2) With additional rating numbers added creating additional unnecessary
searches.
9781118624616 9/10 condition with minimal highlighting
9780415462020 10/10 condition, brand new
So I must find a way to have Javascript filter out these conditions.
Code is here:
//the input box.
var input = document.getElementById('numbers');
//adding an event listener for change on the input box
input.addEventListener('input', handler, false);
//function that runs when the change event is emitted
function handler () {
var items = input.value.replace(/\r?\n/g, ' ').split(' ');
length = items.length;
console.log('your collection', items);
for (var i = 0; i < length; i++) {
if ( items[i] && !isNaN(items[i]) ) {
console.log('opening page for isbn ', items[i])
openPage(items[i]);
}
}
}
//opens the tab for one isbn number
function openPage (isbn) {
var base = 'https://www.amazon.com/gp/search/ref=sr_adv_b/?search-alias=stripbooks&field-isbn='
window.open(base + isbn)
}
<p>... note, after paste you may need to click outside the text area or tab out to fire the change event.</p>
<textarea id=numbers placeholder="paste isbn numbers as csv here">
</textarea>
ISBNs should be 13 numbers if I remember right so can't you just remove the whitespace and match groups of 13?
var str = "978 111 862 4616 9/10 condition with minimal highlighting\n\n9780415462020 10/10 condition, brand new",
nums = str.replace(/\s/,"").match(/\d{13}/g);

Categories

Resources