Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
I have a google spreadsheet with many sheets which is used for requirement gathering. the stakeholder fills the data in every sheet
Now, some fields in each spreadsheet are very critical, hence we plan to highlight in some manner and the validation to take place
Once a sheet is filled the stakeholder will click on a button
This button will check if the mandatory fields are filled
If those cells are empty, a toast notification will pop up mentioning what is to be filled along with highlighting the cells in red color
After the stakeholder fills the info, hits validate button again, the same check happens and colors the cell background to white and display another toast pop up if all is ok.
I have following data in the google sheet
I wrote this apps script to have the validation stated in the above 4 points, as I am new to google apps script, I am facing difficulty with some bits of it
function toastMessageTitle() {
var sheet = SpreadsheetApp.getActive();
var rg1= sheet.getRange('B2');
var rg1_lbl = sheet.getRange('A2').getValue();
var rg2 = sheet.getRange('B5')
var rg2_lbl = sheet.getRange('A5').getValue();
var rg3 = sheet.getRange('B8')
var rg3_lbl = sheet.getRange('A8').getValue();
if (rg1.isBlank() && rg2.isBlank() && rg3.isBlank())
{ SpreadsheetApp.getActive().toast("Please fill - " + rg1_lbl+ ", " + rg2_lbl + ", " + rg3_lbl , "⚠️ Unfilled data",10);
rg1.setBackgroundColor("red");
rg2.setBackgroundColor("red");
rg3.setBackgroundColor("red");
}
else
{ SpreadsheetApp.getActive().toast("All filled", "Thank you",10);
}
}
Please help how can I get the validation done.
Here is a script you can use to achieve this:
function toastMessageTitle() {
var sheet = SpreadsheetApp.getActive();
var rg1= sheet.getRange('B2');
//var rg1_lbl = sheet.getRange('A2').getValue();
var rg2 = sheet.getRange('B5')
//var rg2_lbl = sheet.getRange('A5').getValue();
var rg3 = sheet.getRange('B8')
//var rg3_lbl = sheet.getRange('A8').getValue();
var ranges = [rg1, rg2, rg3];
var unfilled = [];
for(var range of ranges) {
if(range.isBlank()) {
unfilled.push(range.offset(0,-1).getValue())
range.setBackground('red');
} else {range.setBackground(null)};
}
if(unfilled.length == 0) SpreadsheetApp.getActive().toast("All filled", "Thank you",10);
else {
unfilled = unfilled.join(", ");
SpreadsheetApp.getActive().toast("Please fill - " + unfilled, "⚠️ Unfilled data",10);
}
}
This script simply goes through the different ranges, checks if they are blank, and then proceeds accordingly. If none of the cells are blank (ie the unfilled array has nothing in it), it shows the success message.
Related
I have just set up a google form that automatically populates a Google Sheet. I'm trying to set up an automatic email to notify a specific contact everytime someone submits a form and marks their test as positive. If they submit a negative test, I don't want it to send anything.
I've written the following with the following trigger:
Select event source - From Spreadsheet
Select event type - On from Submission
I've linked the formula to another Sheet for the script contacts. I managed to get it to send an email, however, it was previously sending an email even if a negative test was submitted. Because of this, I added another 'If' for a negative display but now it wont send anything at all.
Can anyone help? This is my first time coding any feel like I have hit a roadblock.
Formula:
function positiveemailsubmission()
{
var positiverange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("LFT Submissions").getRange("G2:G50000")
var positivevalue = positiverange.getDisplayValue("Positive");
{
if (positivevalue.getDisplayValue() === "Positive")
{
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Script info").getRange("B2");
var emailAddress = emailRange.getDisplayValue();
var message = 'A positive LFT test has been submitted. Please see the form for more information (WWW.DOCUMENTLINK.CO.UK)';
var subject = 'Positive LFT Submission ';
GmailApp.sendEmail(emailAddress, subject, message);
}
if (positivevalue.getDisplayValue() === "Negative")
{
}
}
}
In order to provide a proper response to the question, I'm writing this answer as a community wiki, since the solution is in the comments section.
Like #Yuri Khristich said, positiverange was a range of a lot of rows "G2:G50000", in this case what you need is the value of the last row (last submit from Form) to determine if that specific answer was "Positive" or "Negative".
I tested your script with the changes mentioned in the comments and it worked.
function positiveemailsubmission()
{
var positiverange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("LFT Submissions");
var positivevalue = positiverange.getRange("G" + positiverange.getLastRow());
{
if (positivevalue.getDisplayValue() === "Positive")
{
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Script info").getRange("B2");
var emailAddress = emailRange.getDisplayValue();
var message = 'A positive LFT test has been submitted. Please see the form for more information (WWW.DOCUMENTLINK.CO.UK)';
var subject = 'Positive LFT Submission ';
GmailApp.sendEmail(emailAddress, subject, message);
}
if (positivevalue.getDisplayValue() === "Negative")
{
}
}
}
I have a code written to validate some blank cells and display a toast with the label names which are not filled, Since the label names are lengthy and too many, the toast opo is not able to show the names of all labels as below -
My script is as below-
function validation() {
var sheet = SpreadsheetApp.getActive();
var rg1= sheet.getRange('B9');
var rg2 = sheet.getRange('D9')
var rg3 = sheet.getRange('F9')
var rg4 = sheet.getRange('H9')
var rg5 = sheet.getRange('B13')
var rg6 = sheet.getRange('D13')
var rg7 = sheet.getRange('B26')
var rg8 = sheet.getRange('D26')
var rg9 = sheet.getRange('B30')
var ranges = [rg1, rg2, rg3,rg4,rg5,rg6,rg7,rg8,rg9];
var unfilled = [];
for(var range of ranges) {
if(range.isBlank()) {
unfilled.push(range.offset(-1,0).getValue())
range.setBackground('red');
} else {range.setBackground(null)};
}
if(unfilled.length == 0) SpreadsheetApp.getActive().toast("All filled", "Thank you",10);
else {
unfilled = unfilled.join(", ");
SpreadsheetApp.getActive().toast("Please fill - " + unfilled, "⚠️ Unfilled data",10);
}
}
Can I increase the size of the toast? or use use two toasts to break the info and display, or any other way I can show the names of the fields.
Please help!
As suggested by the comments it would be important to leave an answer for the future.
The documentation on how the API works or features in general using Sheet it is not possible to add size or adjust the way the toast is presented or variables that you can add, for example:
toast(msg, title, timeoutSeconds)
The second suggestion also works great as it shows a bigger alert and you can add buttons to it, example:
This could be achieved by utilizing a sample code like:
function alertMessageOKButton() {
var result = SpreadsheetApp.getUi().alert("Alert message", SpreadsheetApp.getUi().ButtonSet.OK);
SpreadsheetApp.getActive().toast(result);
}
You can also share your feedback or request the feature for the future here:
https://developers.google.com/apps-script/support
References:
Alert Messages in Google Sheets
Toast Sheets
Gory title but I couldn't find a way of being clearer.
I have no experience with coding and I was wondering if doing something like what I'm about to explain would be possible.
This is my example sheet:
What I'm looking to do is to have automated emails sent out to the person assigned to the task if the task status is set to urgent, while referencing people by names and having an auxiliary sheet with all the names and corresponding emails.
I've browsed around and found some similar questions which I unfortunately had no success in adapting. The one thing I got is that I need to setup an onEdit trigger, which I've done, but I'm completely clueless from here on out.
Can someone point me in the right direction? I don't have a clue where to start.
Looking forward to hearing your advice.
Thanks and stay safe in these crazy times!
It was a funny exercise. I tried to make the script as clean and reusable as possible for others to be able to adapt it to their needs.
Usage
Open spreadsheet you want to add script to.
Open Script Editor: Tools / Script editor.
Add the code. It can be configured by adjusting variables in the top:
var trackerSheetName = 'Tracker 1'
var trackerSheetStatusColumnIndex = 2
var trackerSheetNameColumnIndex = 4
var triggeringStatusValue = 'Urgent'
var peopleSheetName = 'AUX'
var peopleSheetNameColumnIndex = 1
var peopleSheetEmailColumnIndex = 2
var emailSubject = 'We need your attention'
var emailBody = 'It is urgent'
function checkStatusUpdate(e) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var activeSheet = spreadsheet.getActiveSheet()
// skip if different sheet edited
if (activeSheet.getName() !== trackerSheetName) {
return
}
var editedRange = e.range
// skip if not a single cell edit
if (editedRange.columnStart !== editedRange.columnEnd || editedRange.rowStart !== editedRange.rowEnd) {
return
}
// skip if edited cell is not from Status column
if (editedRange.columnStart !== trackerSheetStatusColumnIndex) {
return
}
// skip if Status changed to something other than we're looking for
if (e.value !== triggeringStatusValue) {
return
}
var assigneeName = activeSheet.getRange(editedRange.rowStart, trackerSheetNameColumnIndex, 1, 1).getValue()
var peopleSheet = spreadsheet.getSheetByName(peopleSheetName)
var people = peopleSheet.getRange(2, 1, peopleSheet.getMaxRows(), peopleSheet.getMaxColumns()).getValues()
// filter out empty rows
people.filter(function (person) {
return person[peopleSheetNameColumnIndex - 1] && person[peopleSheetEmailColumnIndex - 1]
}).forEach(function (person) {
if (person[peopleSheetNameColumnIndex - 1] === assigneeName) {
var email = person[peopleSheetEmailColumnIndex - 1]
MailApp.sendEmail(email, emailSubject, emailBody)
}
})
}
Save the code in editor.
Open Installable Triggers page: Edit / Current project's triggers.
Create a new trigger. Set Event Type to On edit. Keep other options default.
Save the Trigger and confirm granting the script permissions to access spreadsheets and send email on your behalf.
Go back to your spreadsheet and try changing status in Tracker 1 tab for any of the rows. Corresponding recipient should receive an email shortly.
This should get you started:
You will need to create an installable trigger for onMyEdit function. The dialog will help you to design you email by giving you an html format to display it. When you're ready just comment out the dialog and remove the // from in front of the GmailApp.sendEdmail() line.
function onMyEdit(e) {
//e.source.toast('Entry');
const sh=e.range.getSheet();
if(sh.getName()=="Tracker") {
if(e.range.columnStart==2 && e.value=='Urgent') {
//e.source.toast('flag1');
const title=e.range.offset(0,-1).getValue();
const desc=e.range.offset(0,1).getValue();
const comm=e.range.offset(0,3).getValue();
if(title && desc) {
var html=Utilities.formatString('<br />Task Title:%s<br />Desc:%s<br />Comments:%s',title,desc,comm?comm:"No Additional Comments");
//GmailApp.sendEmail(e.range.offset(0,2).getValue(), "Urgent Message from Tracker", '',{htmlBody:html});
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html).setWidth(600), 'Tracker Message');
e.source.toast('Email Sent');
}else{
e.source.toast('Missing Inputs');
}
}
}
}
GmailApp.sendEmail()
I'm running into a strange issue that is causing me considerable difficulty hoped someone her might have some insight.
I have a form that is accepting responses and sending the results to a sheet. I've written an additional onsubmit script that then marks up some other sheets both in order to facilitate tracking and to provide a prefilled url that can be sent next time the form needs to be submitted.
The forms are for student data collection and I therefor need three each collecting data about students in different years. My issue is that I can't seem to copy the scripts to the other forms without them ceasing to work.
I have taken the following approaches:
Initially I just tried duplicating the entire form and then changing it, this meant the scripts came along with the copy.
I then tried keeping the duplicated form but deleting out all the script information and copy and pasting the script to a new project within the form.
I then tried creating a new test form and copy and pasting the script to that - again no success.
All attempts have resulted in the data being successfully submitted to the responses sheet but the script either not triggering or failing silently.
I can't see anything in the script I have produced that would cause it to work only on one form but I'm not very experienced in JS and it may be I am not seeing something obvious ( I am aware there are some foolish bits in the script but this is the version I know works).
If anyone can point out anything that would make the script not work for any other forms or can explain how the script can be successfully copied I'd be really grateful.
Code:
/* onsubmit function that creates a prefilled url and prints to sheet */
function onSubmit(e) {
var subject = "ICT";
//generate url
var url=e.response.toPrefilledUrl();
var responses = e.response;//e is of type formresponse.
var name = responses.getItemResponses()[0].getResponse();
var sheet1 = SpreadsheetApp.openByUrl("https://docs.google.com/a/rbair.org.uk/spreadsheets/d/1w_rCPJR-O9_fUs1T5HKmaTUsRjk_9JRVRPxV2kJzNMk/edit#gid=0").getSheetByName("Admin");
update(name, subject);
//print to cell in feedback sheet
var data = sheet1.getDataRange().getValues();
for(i=0; i<100; i++)
{
if(data[i][1]==name)
{
sheet1.getRange(i+1, 3).setValue(url);
}
}
}
function test()
{
var name = "Piers Hartley";
var subject = "ICT";
update(name, subject);
}
function update (name, subject)
{
//var name = "Piers Hartley";
//var subject = "ICT";
var msheet = SpreadsheetApp.openByUrl("https://docs.google.com/a/rbair.org.uk/spreadsheets/d/1IauIkNCrE95qNAL2KxfJhespEcRWuMXYGzkkjwFnezg/edit#gid=0");
var refsheet = msheet.getSheetByName("Subject Teachers");
var track = refsheet.getRange(2,10).getValue();
var tsheet = msheet.getSheetByName(track);
var trdr = tsheet.getDataRange();
var trdata = trdr.getValues();
var lcol = trdr.getLastColumn();
var lrow = trdr.getLastRow();
for(i=0; i<lcol; i++)
{
if (trdata [0] [i] == subject)
{
for (j=1; j<lrow; j++)
{
if (trdata [j] [i] == name)
{
tsheet.getRange(i+2, j+1).setValue("Done");
}
}
}
}
}
Have you added the On Form Submit trigger? (under Resources in the script editor).
I am currently receiving data through an RSS feed into my spreadsheet. I have a script (below) which I am hoping to run on a time trigger (every minute) to check the data and then in turn send an email out if the data meets certain criteria.
Problem: After the first email is sent out, I want to create a system to check (timestamp?) within the script if an email for that particular row of data has already been sent. Is this the best way to do this? How do I do it? Script is below.
function sendEmail(email_address, email_subject, email_message) {
MailApp.sendEmail(email_address, email_subject, email_message);
}
function test_sendEmail() {
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.setActiveCell('A2');
var criterion_cutoff = 5;
var i = 0;
var addr;
var subj;
var msg;
do {
addr = cell.offset(i,0).getValue();
subj = cell.offset(i,1).getValue();
msg = cell.offset(i,2).getValue();
criterion = cell.offset(i,3).getValue();
if(criterion < criterion_cutoff) {
sendEmail(addr,subj,msg);
Browser.msgBox('Sending email to: ' + addr);
}
i++;
} while( cell.offset(i, 0).getValue().length > 0 )
Browser.msgBox('Done!');
}
If I'm understanding your question correctly, you want some way of marking which rows in the spreadsheet that you've already sent emails for, so that you don't send duplicates. If so, then this tutorial shows one way of doing that: https://developers.google.com/apps-script/articles/sending_emails#section2