Trying to Run two functions and two different emails in google scripts - javascript

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?

Related

Creating a Google Calendar Event with Google Sheets script has Errors

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

Making a custom function in Google Sheets, the code works outside of sheets but not in sheets

So I'm writing a custom function for Google sheets which is supposed to take a single row or cells, produce a 1 dimensional array and use that data to create a URL. This is basically so I can help my friends track the prices of an item in a video game.
I have ran the code in a javascript environment outside of Google Sheets and everything acted as expected. But when I put the code in the script editor, it runs with unexpected behavior. The range of cells will always be 1 row by 13 columns but some of the columns may be void so the script is supposed to truncate the array of values so that there are no empty indexes. Then it is supposed to insert a "." between each value as it is concatenated into a string to produce the final URL. For some reason it does not remove any values and the "." are ","s when the URL is created in the cell.
Here is the code:
function STONKLINK(prices, premrkt) {
var webLink = "https://turnipprophet.io?prices=";
var priceLink = "";
for (i = (prices.length - 1); prices[i] == 0; i--){
prices.pop();
}
for (i = 0; i < prices.length; i++) {
priceLink = (priceLink + prices[i] + ".")
}
priceLink = priceLink.substring(0, priceLink.length - 1);
if (premrkt == "N/A") {
webLink = webLink + priceLink;
} else if (premrkt == "Fluctuating") {
webLink = webLink + priceLink + "&pattern=0";
} else if (premrkt == "Small Spike") {
webLink = webLink + priceLink + "&pattern=3";
} else if (premrkt == "Large Spike") {
webLink = webLink + priceLink + "&pattern=1";
} else if (premrkt == "Decreasing") {
webLink = webLink + priceLink + "&pattern=2";
}
return webLink;
}
Any help is very much appreciated. Thank you so much.
EDIT: While I still do not understand why this is happening, and I would like to understand, I have added a simple work around. By adding this line of code
webLink = webLink.replace(/,/g, ".");
before the return, all the commas will be replaced with dots. Still, any insight into the problem will be much appreciated. Thank you again.
When you store values in Spreadsheets, the values which have a , are considered to be strings whilst the ones which have a . will be considered to be numbers.
So for example, if you have these values stored in the B column:
If you log the typeof(val1) and typeof(val2) (where val1 and val2 are the values stored in B1 respectively B2), this is what you will get:
So the issue you were encountering is due to this fact. The values you have stored in your sheet are numbers and when you try to build the webLink string they are converted into strings - therefore, the . for a number becomes ,.
Reference
Date and Number Formats

Email multiple rows to one recipient based on category values using Apps Script

What I'm looking for:
I am working on a spreadsheet that contains transaction information for multiple people. Some people have only 1 transaction (1 row of information) while others may have multiple transactions (rows of information). So far, the code I am working on is able send an email containing one transaction per email. However, I am having trouble figuring out how to group multiple transactions into one email. One of the column fields is "Email address" and ideally I could use that to group multiple rows. Pretty much a mail merge that can be grouped by a column in the spread sheet or by the identification of similar values.
What I've tried/what I'm thinking:
I already have the code sort by email address so that the transactions for each person are consecutive on the sheet. I am thinking that I need to loop with an if statement saying something along the lines "if the next value in the 'email address' field is the same as the previous one, add a new line in the body of the email." From what I have researched I might need to do a loop within a loop for the email body but I am not completely sure how to go about that. In the code I have, I have already somewhat formatted the email the way it should be.
Disclaimer:
I'm pretty new to coding so any help is appreciated. I am unsure how to loop in the body of the message and eventually exit once the script hits a different person. I'd like to do it all in GAS.
This is what I've got so far:
var SENT = "Y";
function sendEmails() {
//This section specifies the sheet and some definitions we are working with
var sheet =SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
var lastrow = sheet.getLastRow();
var startrow = 4; // First row of data to process
var numrows = lastrow; // Number of rows to process
sheet.sort(14, true); //Sorts the sheet by email address
//This section formats the columns so they appear correctly in the html email below
var column = sheet.getRange("K4:L");
column.setNumberFormat("MM/dd/yyyy"); // Simple date format
var column = sheet.getRange("M:M");
column.setNumberFormat("#"); // Simple plain text format
var column = sheet.getRange("K4:L");
column.setNumberFormat("#"); // Simple plain text format
var column = sheet.getRange("E:E");
column.setNumberFormat("$0.00"); // Simple currency format
//This section specifies the actual data we will be working with
var datarange = sheet.getRange(startrow, 1, lastrow, 15)// Fetch the range of cells
var data = datarange.getValues();// Fetch values for each row in the Range.
//Defining column data
for (var i = 0; i < data.length; ++i) {
var col = data[i];
var firstname = col[2]; // Column starting at 0 from left to right
var expamount = col[4]; // Column starting at 0 from left to right
var subdate = col[10]; // Column starting at 0 from left to right
var trandate = col[11]; // Column starting at 0 from left to right
var reportname = col[12]; // Column starting at 0 from left to right
var emailaddress = col[13]; // Column starting at 0 from left to right
var emailsent = col[14]; //Column starting at 0 from left to right
var subject = "MinistryCard Expenses Over 90 Days"; // Subject for the email to be sent
var emailintro = // Introduction part of the email
'Hi ' + firstname + ', <br /><br />' +
'This is the introduction to the email.' +
'The related expenses are below: <br /><br/ >'
var emailtrans = //THIS IS WHERE I WOULD LIKE THE MAGIC TO HAPPEN... I THINK
'<strong>Report Name: </strong>' + reportname + ' <br /><strong>Transaction Date: </strong>' + trandate + ' <br /><strong>Transaction Amount: </strong>' + expamount +
' <br /><strong>Approval Date: </strong>' + subdate + '<br /><br />'
var emailend = // The endd of the email
'We apologize for any inconvenience this may cause. ' +
'Also, please contact us if you believe you are recieving this email in error. Thank you. <br /><br /><br />' +
'Enjoy your day, <br /><br />'
//The section below retrieves alias email address to send as
var me = Session.getActiveUser().getEmail();// Log the aliases for this Gmail account and send an email as the first one.
var aliases = GmailApp.getAliases(); // Gets the alias ministrycard#cru.org from account
Logger.log(aliases); // Logs the alias
// The section below sends the actual emails
if (emailaddress != "" && emailsent != SENT){
if (aliases.length > 0){ // Prevents sending duplicates
GmailApp.sendEmail(emailaddress, subject , emailintro + emailtrans + emailend, {'from': aliases[0],'replyto': 'ministrycard#cru.org', htmlBody : emailintro + emailtrans + emailend});
sheet.getRange(startrow + i, 15).setValue(SENT);
SpreadsheetApp.flush(); // Make sure the cell is updated right away in case the script is interrupted
}} else { }}}
There are multiple solutions. Here's mine:
declare a nextEmail variable before the main for loop begins.
var nextEmail = '';
at the beginning of the loop, set nextEmail to the email in the next row:
if (i < data.length - 1) {
nextEmail = data[i+1][13]//looks at next row, 13th column
} else {//catch if i is the maximum row
nextEmail = ''
}
add another conditional that checks that the next email address is not the same before sending the email
if (emailaddress != "" && emailsent != SENT && nextEmail != emailaddress){
You didn't seem to specify what parts of the message you want to change each time and what parts you want to stay the same, but I'm assuming you want to change only emailtrans.
now, instead of declaing a new variable emailtrans each time it loops around, declare emailtrans before the loop as an empty string...
var emailtrans = ''
...and instead append the big string to emailtrans
emailtrans +=
'<strong>Report Name: </strong>' + reportname + ' <br /><strong>Transaction Date: </strong>' + trandate + ' <br /><strong>Transaction Amount: </strong>' + expamount +
' <br /><strong>Approval Date: </strong>' + subdate + '<br /><br />';
and then set emailtrans to an empty string right after you send the email, inside of the if statement.
emailtrans = ''
There are a few things you didn't ask about but I still think should be addressed. You probably would have caught a lot of this if only you tested whatever you've got, even if it's incomplete, to make sure it did what you want before asking for help.
SENT variable should probably be declared within the function (good practice)
numrows is only equal to lastrow if startrow is zero. Set numrows to lastrow - startrow and use numrows instead of lastrow when you declare datarange.
You sort the whole sheet based on column M, but your script only collect data from row 4 onward. Depending on your labels in rows 1-3, the sorting might place some emails in rows 1-3 and your labels in row 4 and onward. Instead, I'm guessing you only want to sort the range containing the emails, so do a .sort() on that range instead of the whole sheet.
Putting in semicolons where you define emailintro, emailtrans, and emailend in multiple lines is probably a good idea.
I could be wrong, but it seems the html tags aren't formatted right. <br /><br /> wouldn't insert a break ... they would just end two breaks?
Declaring a variable inside a for loop is bad practice. Declare it outside the loop beforehand, and set it (thing = value), not declare it (var thing = value), inside the loop.
Hope this helps.

I want to obtain a certain part of text from a large webpage using Javascript, how do I?

There is a certain webpage which randomly generates a number, for example "Frequency : 21". I am trying to create a script which takes the number, 21, and compares it to another variable, then to an if else function. Basically, I've completed most of it, but I can't obtain the number 21. And since it is random, I can't put in a fixed value.
Can anyone help me out?
My code goes like:
setTimeout(MyFunction,5000)
function MyFunction(level,legmin) {
var level = x
var legmin = 49
if (level <= legmin) {
location.reload(true)
}
else {
alert("Met requirements.")
}
where the address of the text I want is:
html>body>div#container>div#contentContainer>div#content>
div#scroll>div#scrollContent>div>div>div#pkmnappear>form>p (x in the code above).
A quick-n-dirty solution without regex.
var lookFor = "Frequency : ";
var text = document.querySelector("#pkmnappear>form>p").textContent;
var level = text.substr(text.indexOf(lookFor) + lookFor.length).split(" ")[0];
This assumes the number will be followed by a space

Adding to a Google Doc from a Google Spreadsheet Using Apps Script

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.

Categories

Resources