I have the following Google Script. It runs through a spreadsheet and imports information into a Google Calendar. However, I also want it to populate an array with the uploaded data and send it in a Google email. Is this possible? Here is what I have so far.
var MAINTENANCE_EXPORTED = "MAINTENANCE_EXPORTED";
var MAINTENANCE_ERROR = "MAINTENANCE_ERROR";
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var menuEntries = [{name: "Upload CS Maintenance Schedule", functionName: "importCalendarCS"}, {name: "Upload EP Maintenance Schedule", functionName: "importCalendarEP"}];
ss.addMenu("Maintenance Scripts", menuEntries);
}
//
//Coral Street Import Function
//
function importCalendarCS() {
var sheet = ss.getSheetByName('CS');
var startcolumn = 1; // First column of data to process
var numcolumns = sheet.getLastRow(); // Number of columns to process
var dataRange = sheet.getRange(startcolumn, 1, numcolumns, 13) // Fetch values for each column in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) { // this is a "for loop" that asks the script to run through all rows.
var column = data[i];
var building = column[0]; // 1st column in spreadsheet "BLDG"
var cart = column[1]; // 2nd column in spreadsheet "CART OR LAB"
var room = column[2]; // 3rd column in spreadsheet "LOCATION OF CART OR ROOM"
var deviceType = column[3]; // 4th column in spreadsheet "TYPE OF DEVICES"
var deviceQuantity = column[4]; // 5th column in spreadsheet "# of Devices"
var maintenancePerson = column[5]; // 7th column in spreadsheet "Maintenance Person"
var maintenanceDate = column[6]; // 6th column in spreadsheet "Maint Date"
var maintenanceImported = column[13];
var title = building + " - " + room;
var description = "Building: " + building
+ "\n" + "Room: " + room
+ "\n" + "Cart: " + cart
+ "\n" + "Device Type: " + deviceType
+ "\n" + "Device Quantity: " + deviceQuantity;
var calendarName = "Cart Maint Schedule";
if (maintenancePerson == "Bobby Obvious") {
var email = "example#example.com"
}
else {
var email = "example#example.com"
}
if ((maintenanceImported != MAINTENANCE_EXPORTED) && (maintenanceImported != MAINTENANCE_ERROR) && (building != "BLDG") && (cart != "Cycle 1 Checklist") && (cart != "Cycle 2 Checklist")) { // Prevents importing duplicates
var cal = CalendarApp.openByName(calendarName);
var advancedArgs = {description: description, location: ("Cart: " + cart)};
var itsEmail = "example#example.com";
if
if (maintenanceDate != "") {
cal.createAllDayEvent(title, new Date(maintenanceDate), advancedArgs);
var sheet2 = ss.getSheetByName('CS');
sheet.getRange(startcolumn + i, 14).setValue(MAINTENANCE_EXPORTED);
SpreadsheetApp.flush();
}
else {
var sheet2 = ss.getSheetByName('CS');
sheet.getRange(startcolumn + i, 14).setValue(MAINTENANCE_ERROR);
SpreadsheetApp.flush();
}
}
}
}
Yes it's possible. Use the MailApp class.
https://developers.google.com/apps-script/reference/mail/mail-app
or the GmailApp Class:
https://developers.google.com/apps-script/reference/gmail/gmail-app
Try to use the MailApp.sendEmail method. It accepts an address.
Related
I have a script that creates forms that need to be filled out for ordering, the onformsubmittrigger places this weird line of text when it comes to the multi choice option [Ljava.lang.Object;#7c2a6e46, if possible I would also like to define where the answer are placed instead of the default of column a,b,c
function snore() {
var sheet = SpreadsheetApp.getActive().getSheetByName('TC');
var value = sheet.getRange("B2").getValue();
var em = sheet.getRange("C2").getValue();
var cos = sheet.getRange("F2").getValue();
var name = sheet.getRange("E2").getValue();
var sup = sheet.getRange("D2").getValue();
var form = FormApp.create(value);
var item = form.addMultipleChoiceItem();
item.setHelpText("Name: " + name +
"\n\nEmail: " + em +
"\n\nQuote No: " + value +
"\n\nProject: " + sup +
"\n\nTotal Cost: " + cos +
"\n\nBy selecting approve you agree to the cost and timeframe specified by the quote and that the details above are correct")
.setChoices([item.createChoice('Approved'), item.createChoice('Denied')]);
var itm = form.addCheckboxItem();
itm.setTitle('What extras would you like to add on? (all prices are Ex-GST)');
itm.setChoices([
itm.createChoice('Watergate Plus 1370mm x 36.5m, 36.5Lm - $109.80'),
itm.createChoice('Watergate Plus 2740mm x 30m, 30Lm - $171.60'),
itm.createChoice('White General Purpose Repair Tape 60mm x 66m, 66Lm - $39.21'),
itm.createChoice('Wall Wrap, Foil Fasteners, 500/box - $39.21'),
itm.createChoice('Super Course 500, 300mm x 0.5 x 50Lm - $29.30'),
itm.createChoice('40mm Metal Top Hat Batten - 3.10/mtr')
])
.showOtherOption(true);
Logger.log('Published URL: ' + form.getPublishedUrl());
Logger.log('Editor URL: ' + form.getEditUrl());
Logger.log('ID: ' + form.getId());
var myDId = DriveApp.getRootFolder().getId();
var rootFolder = DriveApp.getFolderById(myDId);
var archiveFolder = DriveApp.getFolderById("1Rt6xikEpHs-F2cQOTRrvATCZHCFU0bQ6");
var newForms = rootFolder.getFilesByName(value);
while (newForms.hasNext()) {
var newForm = newForms.next();
archiveFolder.addFile(newForm)
rootFolder.removeFile(newForm);
}
//const spreadsheetId = SpreadsheetApp.getActive().getId();
//form.setDestination(FormApp.DestinationType.SPREADSHEET, spreadsheetId);
SpreadsheetApp.getActiveSheet().getRange('J2').setValue('SENT');
var id = "1uw8HAJsuNHses_9XGfNtQ71fp3DXE7q1";
var buildBlob = DriveApp.getFileById(id).getBlob().setName("buildBlob");
var SendTo = "Jonathon.banks#westal.com.au";
var link = form.getId();
var message = "Please follow the link to accept you Quotation " + form.getPublishedUrl();
//set subject line
var body = HtmlService.createTemplateFromFile("email");
body.order = value;
body.overdue = form.getPublishedUrl();
var con = sheet.getRange("A2").getValue();
var file = DriveApp.getFilesByName(con).next()
var Subject = 'Quote' + value + 'Confirmation';
const recipient = em;
const subject = "Confirmation of order"
MailApp.sendEmail({
to: recipient,
attachments: file,
subject: subject,
htmlBody: body.evaluate().getContent(),
inlineImages:
{
build: buildBlob
}
});
//const subect = "confirm for id"
//const rcipient = SendTo;
//var mssage = "please run id confirm " + link;
//GmailApp.sendEmail(rcipient, subect, mssage)
const SOURCE_FORM_ID = link; // Change according to your needs
{
const form = FormApp.openById(SOURCE_FORM_ID);
ScriptApp.newTrigger("onFormSubmitTrigger")
.forForm(form)
.onFormSubmit()
.create();
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var seet = ss.getSheetByName('TC'); //source sheet
var testrange = seet.getRange('J:J'); //range to check
var testvalue = (testrange.getValues());
var csh = ss.getSheetByName('C'); //destination sheet
var data = [];
var j =[];
//Condition check in H:H; If true copy the same row to data array
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] == 'SENT') {
data.push.apply(data,seet.getRange(i+1,1,1,25).getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
//Delete matched rows in the source sheet
for (i=0;i<j.length;i++){
var k = j[i]+1;
sheet.deleteRow(k);
//Alter j to account for deleted rows
if (!(i == j.length-1)) {
j[i+1] = j[i+1]-i-1;
}
}
}
//const TARGET_SPREADSHEET_ID = "1JRhCnS048fhWMifkrD1mqdgFcs3-Cw-kGOzSgpLWfI0"; // Change according to your needs
//const TARGET_SHEET_NAME = "C"; // Change according to your needs
function onFormSubmitTrigger(e) {
const targetSpreadsheet = SpreadsheetApp.openById("1JRhCnS048fhWMifkrD1mqdgFcs3-Cw-kGOzSgpLWfI0");
const targetSheet = targetSpreadsheet.getSheetByName("C");
if (targetSheet.getLastRow() === 0) { // Add headers if they don't exist yet
const itemTitles = e.source.getItems().map(item => item.getTitle()); // Get item titles
itemTitles.unshift("Timestamp"); // Append "Timestamp" to the sheet (if desired)
targetSheet.appendRow(itemTitles); // Append form item titles to the sheet
}
const itemResponses = e.response.getItemResponses();
const responses = itemResponses.map(itemResponse => itemResponse.getResponse()); // Get user responses
responses.unshift(new Date()); // Add today's date to the responses (if desired)
targetSheet.appendRow([JSON.stringify(responses)])
}
Well we have this google form and the details are being added to google sheet with custom g apps scripts. When the details have been appended to the google sheet log, it should send email. If I run the sendmail() manually, it works but when I call it inside onFormSubmit(), it's not working. What could have gone wrong?
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var logSheet = sheet.getSheetByName("Log");
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var newFileName = e.namedValues['Name'][0] + "-" + e.namedValues['Date'][0];
var populatedDocsFolder = DriveApp.getFolderById("1yTSd7W0U4Gcsm6CIw8NtD022F-MA7CPx");
var templateDocID = DocumentApp.openByUrl(templateLink).getId();
var newDocID = DriveApp.getFileById(templateDocID).makeCopy(newFileName, populatedDocsFolder).getId();
var newDocLink = DriveApp.getFileById(newDocID).getUrl();
var newDoc = DocumentApp.openById(newDocID);
var newDocBody = newDoc.getBody();
for (i = 0; i < formResponsesHeader[0].length; i++) {
var thisHeader = formResponsesHeader[0][i];
var thisValue = e.namedValues[thisHeader][0];
newDocBody.replaceText("<<" + thisHeader + ">>", thisValue);
}
//Log
var name = e.namedValues['Name'][0];
var email = e.namedValues['Email'][0];
var date = e.namedValues['Date'][0];
logSheet.appendRow([name,email,date,newDocID]);
//Trigger
ScriptApp.newTrigger("sendEmail").timeBased().after(15000).create();
//sendEmail();
}
function sendEmail() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var logSheet = sheet.getSheetByName("Log");
var logSheetData = logSheet.getDataRange().getDisplayValues();
var templateName = sheet.getSheetByName("Template Name").getRange(1, 1).getValue();
for (i = 1; i < logSheetData.length; i++) {
if (logSheetData[i][4] == "") {
//SEND EMAIL
var name = logSheetData[i][0];
var email = logSheetData[i][1];
var date = logSheetData[i][2];
var id = logSheetData[i][3];
var pdfName = templateName + "-" + name + "-" + date;
//PDF EMAIL
try{
var doc = DriveApp.getFileById(id);
var blob = doc.getBlob().getAs('application/pdf').setName(pdfName + ".pdf");
var subject = 'Document Created';
//GmailApp.sendEmail(email, subject, "This is just a test", {attachments: [blob]});
MailApp.sendEmail(email, subject, "", {attachments: [blob], name: pdfName});
}catch(err){
continue;
}
//Log Sheet Update
logSheet.getRange(i + 1, 5).setValue("Sent");
}
}
}
function onOpen() {
SpreadsheetApp.getUi().createMenu("Custom Menu")
.addItem("Build Form Submit Trigger", "formSubmitTrigger")
.addSeparator()
.addItem("Send Email", "sendEmail")
.addSeparator()
.addItem("Mismatch Check", "mismatchCheck")
.addToUi();
}
function formSubmitTrigger() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger("onFormSubmit").forSpreadsheet(sheet).onFormSubmit().create();
}
function mismatchCheck() {
var result = "";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var templateLink = sheet.getSheetByName("Template Link").getRange(1, 1).getValue();
var formResponsesSheet = sheet.getSheetByName("Form Responses 1");
var formResponsesHeader = formResponsesSheet.getRange(1, 2, 1, formResponsesSheet.getLastColumn() -1).getValues();
var docBody = DocumentApp.openByUrl(templateLink).getBody().getText();
var matches = docBody.match(/<</g); var noOfLessThanMatches = matches.length;
var matches = docBody.match(/>>/g); var noOfMoreThanMatches = matches.length;
var lessThan = docBody.search(/<</g);
var moreThan = docBody.search(/>>/g);
Logger.log([noOfLessThanMatches,noOfMoreThanMatches]);
result += "<b>Less Than Signs:</b> " + noOfLessThanMatches + "<br>";
result += "<b>More Than Signs:</b> " + noOfMoreThanMatches + "<br>";
result += "<br><b>Doc to Form Check</b><br>";
var newDocBody = docBody;
var reverseArray = [];
for (i = 0; i < noOfLessThanMatches; i++) {
var lessThan = newDocBody.search(/<</g);
var moreThan = newDocBody.search(/>>/g);
var subString = newDocBody.substring(lessThan + 2,moreThan);
Logger.log(subString);
var indexOf = formResponsesHeader[0].indexOf(subString);
if (indexOf > -1) {
result += subString + " - FOUND<br>";
} else {
result += subString + " - NOT FOUND<br>";
}
reverseArray.push(subString);
newDocBody = newDocBody.replace("<<" + subString + ">>","XX")
}
result += "<br><b>Form to Doc Check</b><br>";
for (z = 0; z < formResponsesHeader[0].length; z++) {
var thisString = formResponsesHeader[0][z];
var indexOf = reverseArray.indexOf(thisString);
if (indexOf > -1) {
result += thisString + " - FOUND<br>";
} else {
result += thisString + " - NOT FOUND<br>";
}
}
Logger.log(result);
var htmlOutput = HtmlService
.createHtmlOutput('<p>' + result + '</p>')
.setWidth(400)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'RESULT');
}
UPDATE: I have pasted the whole code instead above so you guys can see
You have to register onFormSubmit as the function that handles the form submit trigger. Have you registered the function "onFormSubmit" like this:
ScriptApp.newTrigger('onFormSubmit').forForm(form).onFormSubmit().create();
You might also want to check the registered triggers by clicking on Edit > Current project's trigger from your Apps Script project.
[Edit] Since the trigger is created properly, change the first the line of the trigger code from:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
to this:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.openById(e.source.getDestinationId());
function findTextsendupdate(){
var sheet = SpreadsheetApp.getActiveSheet()
var startRow = 3// First row of data to process
var numRows = 50 // Number of rows to process
// if a yes is entered in column M
var sendUpdateRange = sheet.getRange(startRow, 1, numRows, 14);
// Fetch values for each row in the Range.
var yes = "yes"
var no = "no"
var send = sendUpdateRange.createTextFinder(yes);
send.matchCase(false); //{Boolean} -> match target text's case or not;
send.matchEntireCell(true); //{Boolean} -> check the whole Range or within;
send.ignoreDiacritics(true); //{Boolean} -> ignore diacretic signs during match;
send.matchFormulaText(true); //{Boolean} -> search in formulas (if any) or values;
var dontSend = sendUpdateRange.createTextFinder(no)
dontSend.matchCase(false); //{Boolean} -> match target text's case or not;
dontSend.matchEntireCell(true); //{Boolean} -> check the whole Range or within;
dontSend.ignoreDiacritics(true); //{Boolean} -> ignore diacretic signs during match;
dontSend.matchFormulaText(true); //{Boolean} -> search in formulas (if any) or values;
//invoke search;
var res = send.findNext();
var tes = dontSend.findNext();
{ //do something with result;
if (tes) {
var emailNotSent = "Email Not Sent"
sheet.getRange(startRow, 14, numRows, 1).setValue(emailNotSent)}
if(res) {
var sendEmail = sendUpdateRange.getValues();
var emailSent = "Email Sent";
for (var i = 0; i < sendEmail.length; i++) {
var row = sendEmail[i];
var Name = row[1]
var job = row[2]
var model = row[4]
var info = "Job number: " + job + "\n"
var emailAddress = row[0];
var isEmailSent = row[14]
if (isEmailSent != emailSent && no) {
var message = "Dear " + Name + "\n" + "
var body = info + "\n" + message
var subject = "email";
MailApp.sendEmail(emailAddress, subject, body);
sheet.getRange(startRow, 14, numRows, 1).setValue(emailSent);
} }}}}
I have dedicated column M for the edit trigger. But, every time I enter a yes or a no in the first row, it sends the emails for all the other rows. If I put no on the first row, and yes on the send, it changed from not sending to sending all emails whereas if I put yes on the first row and no on the second, it flips between sending and not sending all emails.
I want to make the script look at column M and decide on a row by row basis on whether to send or not to send an email. This is the part I'm having trouble with and I've exhausted my search options.
Assuming everything you had in there works then this might be close.
function findTextsendupdate(e){
const sh=e.range.getSheet();
if(sh.getName()=="My Email Sheet" && e.range.columnStart==13 && e.value=="TRUE") {
const row=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0];
var Name = row[1];
var job = row[2];
var model = row[4];
var info = "Job number: " + job + "\n";
var emailAddress = row[0];
var isEmailSent = row[14];
if (isEmailSent != "EmailSent" && MailApp.getRemainingDailyQuota()>0) {
var message = "Dear " + Name + "\n";
var body = info + "\n" + message;
var subject = "email";
MailApp.sendEmail(emailAddress, subject, body);
sh.getRange(e.range.rowStart,14).setValue('EmailSent');
}
}
}
How I record an action for this function?
Basically I have to do this and others actions everyday and always is the same.
searching and replacing does not record in google sheets
That is right, the find and replace function is not accessible via Google App Scripts and is not therefore able to be recorded. You need to create your own code to accomplish a behavior similar to the behavior you want manually.
Here is one of many example ways of doing it: https://webapps.stackexchange.com/questions/104157/auto-find-and-replace-in-google-sheets-with-scripts
Thanks i used that code and i edited a litle bit.
function Herramienta() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A1:A69').activate();
spreadsheet.getRange('A1:A69').splitTextToColumns();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("a2:a69");
var to_replace = "HH-";
var replace_with = "";
replaceInSheet(sheet,range, to_replace, replace_with);
function replaceInSheet(sheet, range, to_replace, replace_with) {
//Confirm
var ui = SpreadsheetApp.getUi();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var result = ui.alert(
"Will update " + to_replace + " to " + replace_with + " ",
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
spread.toast("Will update " + to_replace + " to " + replace_with + " ", "ALERT");
var data = range.getValues();
var oldValue="";
var newValue="";
var cellsChanged = 0;
for (var row=0; row<data.length; row++) {
for (var item=0; item<data[row].length; item++) {
oldValue = data[row][item];
newValue = data[row][item].replace(to_replace, replace_with);
if (oldValue!=newValue)
{
cellsChanged++;
data[row][item] = newValue;
}
}
}
range.setValues(data);
spread.toast(cellsChanged + " cells changed", "STATUS");
}
else {
// User clicked "No" or X in the title bar.
spread.toast("No action taken", "ABANDONED");
}
}
}
I am trying to get an e-mail to be sent when the value in a cell that contains a formula goes below a certain number.
I have achieved this for various other spreadsheets that have the cell value manually entered, but for this specific one sheet where the value on the cell results from a simple SUM formula, the e-mail is not being sent. Now if I enter the value manually into the cell, the e-mail is sent right away.
Below is the code and here is a copy of my spreadsheet:
https://docs.google.com/spreadsheets/d/1gnmJfkmIKHyNqLqTFK-bdOZnh2Ejkia6xo3r_3cjwkk/edit?usp=sharing
function CheckBasketsInventory(e) {
var ss = e.source;
var inventorySheet = ss.getSheetByName("Baskets");
var rowIndex = e.range.getRow();
var columnIndex = e.range.getColumn();
var numCols = 11;
var row = inventorySheet.getRange(rowIndex, 1, 1, numCols).getValues()[0];
var editedInventory = row[10];
var editedMinimum = row[8];
var sheetName = ss.getActiveSheet().getName();
// Checking that: (1) edited cell is an inventory quantity, and (2) Inventory is below minimum
if(editedInventory <= editedMinimum && sheetName == "Baskets" && columnIndex == 11 && rowIndex > 1) {
var inventoryValues = inventorySheet.getDataRange().getValues();
var emailBody = "";
for(var i = 1; i < inventoryValues.length; i++) {
var inventory = inventoryValues[i][10];
var minimum = inventoryValues[i][8];
if(inventory <= minimum) {
var productName = inventoryValues[i][0] + " " + inventoryValues[i][1] + " " + inventoryValues[i][2];
var productUnits = minimum + " " + inventoryValues[i][9];
var messagePart1 = "Inventory for " + productName + " has gone under " + productUnits + ". ";
var messagePart2 = "Organise purchase order. Inventory as of today is: " + inventory + " " + inventoryValues[i][9];
var message = messagePart1.concat(messagePart2);
var newItem = "<p>".concat(message, "</p>");
emailBody += newItem;
}
}
var emailSubject = "Low inventory alert";
var emailAddress = "danielrzg#gmail.com";
// Send Alert Email
if(emailBody != "") {
MailApp.sendEmail({
to: emailAddress,
subject: emailSubject,
htmlBody: emailBody
});
}
}
}
Thank you.
As you can see in the documentation:
Script executions and API requests do not cause triggers to run. For
example, calling FormResponse.submit() to submit a new form response
does not cause the form's submit trigger to run.
This includes values edited by a Sheet Formula not triggering an onEdit trigger.