Exception: Cannot call SpreadsheetApp.getUi() from this context. at CheckInventory(onChange2:13:27)
I am getting the above error when my code runs. I have it set to an onchange trigger. It checks the values in one column of my spreadsheet and compares it to another. I don't believe the issue lies in that, but rather somewhere else? my code is as follows;
// Check inventory and send email on Change to Column AA (27)
function CheckInventory() {
// Fetch the current inventory)
var currentRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getActiveRange().getA1Notation();
var currentRow = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getActiveRange().getRow();
var currentColumn = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getActiveRange().getColumn();
var currentInventoryRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getRange(currentRow,11);
var currentInventory = currentInventoryRange.getValue();
var oneMonthInventoryRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getRange(currentRow,27);
var oneMonthInventory = oneMonthInventoryRange.getValue();
var currentSKU = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master").getRange(currentRow,1).getValue();
var ui = SpreadsheetApp.getUi();
// Check totals sales
if (currentColumn === 27){
if (currentInventory < oneMonthInventory){
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email").getRange("B2");
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = 'Item SKU ' + currentSKU + ' inventory is low! Reorder now.'; // Second column
var subject = 'Low Inventory Notification: ' + currentSKU;
MailApp.sendEmail(emailAddress, subject, message);
}}
}
Any thoughts on why this is breaking and not triggering properly?
I have tried updating the ui line and checked it to ensure it was written properly, but it did not fix it.
Related
I've mashed together a couple of functions for Google Apps Script but I'm getting a syntax error at the end. I'm a beginner and I'm not sure why Google Sheets Script editor is giving me the syntax error on the very last line.
function CheckSales() {
// Fetch the monthly sales
var monthSalesRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Day Breakdown").getRange("K35");
var monthSales = monthSalesRange.getValue();
// Check totals sales
if (monthSales > 999){
function sendEmail() {
var recipient = "myemail";
var subject = "SubjectTest";
var body = "Simple Message + monthSales variable tag here.";
MailApp.sendEmail(recipient, subject, body);
}
}
Syntax error: SyntaxError: Unexpected end of input line: 13 file: unit_notifier.gs
I'm a beginnier so I didn't know what to do or where to turn.
I tried deleting the trailing "}".
Removing part of the script.
I would appreciate learning what I did wrong and any tips on resources for the future. I'm am incredibly grateful. Thank you.
try it this way:
function checkSales() {
var monthSalesRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Day Breakdown").getRange("K35");
var monthSales = monthSalesRange.getValue();
if (monthSales > 999) {
var recipient = "myemail";
var subject = "SubjectTest";
var body = "Simple Message " + monthSales;
MailApp.sendEmail(recipient, subject, body);
}
}
If you wish to create a standalone sendEmail function then you can but you need to have some parameters to pass recipient, subject and body and the call would simply be something like sendEmail(recipient,subject,body);
It appears to be that the sendEmail function is defined but you never called it and the variable monthSales is not included in the body of the email. Try this possible approach.
function checkSales(){
// Fetch the monthly sales
var monthSalesRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Day Breakdown").getRange("K35");
var monthSales = monthSalesRange.getValue();
// Check totals sales
if (monthSales > 999){
sendEmail(monthSales);
}
}
function sendEmail(monthSales) {
var recipient = "myemail";
var subject = "SubjectTest";
var body = "Simple Message. Total sales for the month: " + monthSales;
MailApp.sendEmail(recipient, subject, body);
}
I want to have an automatic email machine, without having to write all of the messages and email addresses myself.
I'm really new to this, so please don't be too harsh.
function sendOrder() {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Are you sure you want to send the order?',
ui.ButtonSet.YES_NO);
var deliveryDate = ui.prompt('Delivery date:');
// Process the user's response.
if (response == ui.Button.YES) {
var s = SpreadsheetApp.getActive().getSheetById('1pON34oXVhlpC8goyBxfu6-Gw92tgQBUVUpskZUtgp4E');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getActiveSheet().getDataRange();
var range = s.getRange('A1:C102');
var to = "example#example.com";
var body = '';
var htmlTable = SheetConverter.convertRange2html(range);
var body = "Here is the table:<br/><br/>" +
htmlTable +
"<br/><br/>The end."
MailApp.sendEmail(to, 'Subject', body, {
htmlBody: body
});
};
SpreadsheetApp.getUi().alert('Yeah! Your order has been sent :)');
}
I just expect this to give me a box to enter a date, once the date is entered it should say it has sent and our supplier will see all of the orders.
Issue:
This is because function getSheetById() does not exist.
Solution:
Use openById() instead:
var s = SpreadsheetApp.openById('yourIdHere');
Reference:
openById()
you need to add the function getSheetById(id):
function getSheetById(id) {
return SpreadsheetApp.getActive().getSheets().filter(
function(s) {return s.getSheetId() === id;}
)[0];
}
I have a table in ServiceNow that contains Store and a corresponding Tier that is associated with the Store.
I am trying to auto-populate a record producer, once Store is selected. and my script is not running.
The table is a custom table created in a scoped application which is new to me so not sure what I am doing wrong in the scripting. Any advice?
//Catalog Client Script (runs on [Store] Record Producer Change)
function onChange(control, oldValue, newValue, isLoading) {
if (isLoading || newValue == '') {
return;
}
// new GlideAjax object referencing store of AJAX script include
var ga = new GlideAjax("HRProfileAjax");
// add store parameter to define which function we want to call
// method store in script include will be getFavorites
ga.addParam("sysparm_store", "getHRProfile");
ga.addParam("sysparm_tier", "getHRProfile");
// submit request to server, call ajaxResponse function with server response
ga.getXML(ajaxResponse);
function ajaxResponse(serverResponse) {
// get result element and attributes
var result = serverResponse.responseXML.getElementsByTagstore("result");
var message = result[0].getAttribute("tier");
//check for message attribute and alert user
//if(message)
//alert(message);
//build output to display on client for testing
// get favorite elements
var favorites = serverResponse.responseXML.getElementsByTagstore("favorite");
for(var i = 0; i < favorites.length; i++) {
var store = favorites[i].getAttribute("store");
g_form.setValue(store);
var tier = favorites[i].getAttribute("tier");
//output += store + " = " + tier + "\n";
g_form.setValue(store,tier);
}
//g_form.setValue('number',output);
}
//Script #2 HR PROFILE AJAX
/*
* HRProfileAjax script include Description - sample AJAX processor returning multiple value pairs
*/
var HRProfileAjax = Class.create();
HRProfileAjax.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
/*
* method available to client scripts call using:
* var gajax = new GlideAjax("HRProfileAjax");
* gajax.addParam("sysparm_store", "getFavorites");
*/
getHRProfile : function() {
// build new response xml element for result
var result = this.newItem("result");
var store = this.getParameter('store');
var hrPro = new GlideRecord('x_hiring_gri_hr_storetier');
hrPro.addQuery('store',store);
hrPro.query();
if(hrPro.next()){
result.setAttribute("message", "returning all favorites");
this._addFavorite("tier", hrPro.tier);
}
},
_addFavorite : function(store, value) {
var favs = this.newItem("favorite");
favs.setAttribute("store", store);
},
type : "HRProfileAjax"
});
I am trying to save chat message on localStorage (or sessionStorage) and display on web page, I can found the key-value pair stored in Devtool -> application -> localStorage, the message value update everytime when user sends the message and display on web page. However the content gone everytime when page reload. How to solve this?
Also what I am encountering is the push() to save messages to array will replaces instead of adds value, not sure if these 2 issues are related. Thanks.
pug file
#test2(style='height:200px; width:200px; border:1px solid #ccc')
js file
$('#sendMessage').on('click', function() {
var msg = $('#message').val()
var messages = [];
console.log(typeof(messages)); //obj
messages.push(msg);
console.log(messages); //array value
if (localStorage) {
for (var i = 0; i < messages.length; i++) {
localStorage.setItem('message', msg);
}
localStorage.setItem('username', $('#username').val());
localStorage.setItem('date', currentTime());
var cUser = localStorage.getItem('username');
var cMsg = localStorage.getItem('message');
var cTime = localStorage.getItem('date');
} else {
console.log('localStorage is not supported.');
}
document.getElementById("test2").innerHTML += "<div>" + cUser + " : " + cMsg + "</div>";
// Clear the field
$('#message').val('');
}); // End click
reload page lose data
// Send Message
$('#sendMessage').on('click', function() {
// get value
var username = $('#username').val();
var msg = $('#message').val();
var time = currentTime();
//check if localStorage works and create msgArray
if (!localStorage) {
console.log('localStorage is not supported.');
} else {
//check if there is existing message array in msgArray
var msgArray = localStorage.getItem('message');
//if there is NULL, setup msgArray = [], converts a JavaScript value to a JSON string
if (JSON.stringify(msgArray) == 'null') {
msgArray = [];
} else {
//else parses a JSON string, constructing the JavaScript value or object described by the string
msgArray = JSON.parse(msgArray);
}
}
//add new message object to msgArray
var newMsg = {
msg: msg,
username: username,
time: time
};
msgArray.push(newMsg);
// stringsfy the message and store it to localStorage
localStorage.setItem('message', JSON.stringify(msgArray));
// dispaly current messages
var cMsg = JSON.parse(localStorage.getItem('message'));
// console.log(cMsg); // should shows list of array with new added message objects
// for (var i = 0, max = cMsg.length; i < max; i++) {
//document.getElementById("test2").innerHTML += "<div>" + cMsg[i].username + " : " + cMsg[i].msg + " at " + cMsg[i].time + " </div>";
$('#test2').append('<div class="well well-sm">' + cMsg[cMsg.length - 1].username + ' : ' + cMsg[cMsg.length - 1].msg + ' <span class="pull-right"><small id="date"> at ' + cMsg[cMsg.length - 1].time + '</small></span></div>');
// load the bottom of message
var objDiv = document.getElementById("chatArea");
objDiv.scrollTop = objDiv.scrollHeight;
// Clear the field
$('#message').val('');
}); // End click
I am not sure what you are trying to accomplish with your for loop, since you seem to be setting the same value as many times as you have messages (essentially that's worth nothing, setting it once should be enough)
Let's revisit your steps:
You are getting a value from an input element with id message, and saving it into the msg variable
var msg = $('#message').val()
You construct a new array, and push it in
var messages = [];
messages.push(msg);
And then you iterate the array, but re-use the msg variable
for (var i = 0; i < messages.length; i++) {
localStorage.setItem('message', msg);
}
So essentially, you did this:
localStorage.setItem('message', $('#message').val());
and nothing more. Maybe you wanted to get the array of messages first, and then add the new message to it, rather something like the following
function addMessage() {
// get the potential array
var messages = JSON.parse( localStorage.getItem('message') || '[]' );
// add the message
messages.push($('#message').val());
// save the array as a string, using JSON.stringify
localStorage.setItem('message', JSON.stringify( messages));
// empty the message value
$('#message').val('');
console.log(messages);
}
If you want to save some chat messages, I think you should make sure that all message are properly linked with the author's username and the time it was wrote.
You tried an array... For the messages, but not for the other infos.
And you misused the array.
LocalStorage will only store a string.
Well... I think it can store objects too... But It is a habit of mine to always store strings.
This way, it always can be console logged fast, instead of bugging...
So stringify the array before saving it.
And when you retreive it,you have to parse it back to an array to be able to push a new message into it.
Ok... So will you try to synchronize 3 or more arrays?
I suggest ONE array of objects.
Each objects containing all the relevant infos linked to a particular message.
See comments in code.
$('#sendMessage').on('click', function() {
// ...
var chatWindow = $("#chatWindow");
// Get all values now.
var msg = $('#message').val();
var username = $('#username').val();
var time = moment().format("hh:mm:ss");
if (!localStorage) {
console.log('localStorage is not supported.');
}else{
// Retreive previous messages
var messageArray = localStorage.getItem('message');
// If there was none, set it as an array
if(JSON.stringify(messageArray) == "null"){
console.log(JSON.stringify(messageArray));
messageArray = [];
// If there was, get them back from string to an array of objects.
}else{
messageArray = JSON.parse(messageArray);
}
// Set the new message object.
var newMsg = {msg:msg,
time:time,
username:username
}
// Insert the new message object in the array.
messageArray.push(newMsg);
// Save the array as a string.
var messagesStringified = JSON.stringify(messageArray);
localStorage.setItem('message', messagesStringified);
// I suppose that showing the messages from what is saved re-assures you about the saving...
var cMsg = localStorage.getItem('message');
// Empty chatWindow
chatWindow.empty();
// Loop through the messages.
var allMessages = JSON.parse(cMsg);
for(i=0;i<allMessages.length;i++){
chatWindow.append("<div>" +
allMessages[i].time +
" | "+ allMessages[i].username +
" : " + allMessages[i].msg + "</div>");
}
console.log(JSON.stringify(messageArray));
// Clear the field
$('#message').val('');
}
}); // End click
$('#clear').on('click', function() {
localStorage.clear();
});
Have a look on **CodePen.
I created a form using UI Page and am trying to have some fields autopopulated onChange. I have a client script that works for the most part, but the issue arises when certain fields need to be dot-walked in order to be autopopulated. I've read that dot-walking will not work in client scripts for scoped applications and that a GlideAjax code will need to be used instead. I'm not familiar with GlideAjax and Script Includes, can someone help me with transitioning my code?
My current client script looks like this:
function beneficiary_1(){
var usr = g_user.userID;
var related = $('family_member_1').value;
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee',usr);
rec.addQuery('sys_id',related);
rec.query(dataReturned);
}
function dataReturned(rec){
//autopopulate the beneficiary fields pending on the user selection
if(rec.next()) {
$('fm1_ssn').value = rec.ssn;
$('fm1_address').value = rec.beneficiary_contact.address;
$('fm1_email').value = rec.beneficiary_contact.email;
$('fm1_phone').value = rec.beneficiary_contact.mobile_phone;
var dob = rec.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0] ;
$('fm1_date_of_birth').value = date;
}
}
fm1_address, fm1_email, and fm1_phone do not auto populate because the value is dot walking from the HR_Beneficiary table to the HR_Emergency_Contact table.
How can I transform the above code to GlideAjax format?
I haven't tested this code so you may need to debug it, but hopefully gets you on the right track. However there are a couple of steps for this.
Create a script include that pull the data and send a response to an ajax call.
Call this script include from a client script using GlideAjax.
Handle the AJAX response and populate the form.
This is part of the client script in #2
A couple of good websites to look at for this
GlideAjax documentation for reference
Returning multiple values with GlideAjax
1. Script Include - Here you will create your method to pull the data and respond to an ajax call.
This script include object has the following details
Name: BeneficiaryContact
Parateters:
sysparm_my_userid - user ID of the employee
sysparm_my_relativeid - relative sys_id
Make certain to check "Client callable" in the script include options.
var BeneficiaryContact = Class.create();
BeneficiaryContact.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getContact : function() {
// parameters
var userID = this.getParameter('sysparm_my_userid');
var relativeID = this.getParameter('sysparm_my_relativeid');
// query
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee', userID);
rec.addQuery('sys_id', relativeID);
rec.query();
// build object
var obj = {};
obj.has_value = rec.hasNext(); // set if a record was found
// populate object
if(rec.next()) {
obj.ssn = rec.ssn;
obj.date_of_birth = rec.date_of_birth.toString();
obj.address = rec.beneficiary_contact.address.toString();
obj.email = rec.beneficiary_contact.email.toString();
obj.mobile_phone = rec.beneficiary_contact.mobile_phone.toString();
}
// encode to json
var json = new JSON();
var data = json.encode(obj);
return data;
},
type : "BeneficiaryContact"
});
2. Client Script - Here you will call BeneficiaryContact from #1 with a client script
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var usr = g_user.userID;
var related = $('family_member_1').value;
var ga = new GlideAjax('BeneficiaryContact'); // call the object
ga.addParam('sysparm_name', 'getContact'); // call the function
ga.addParam('sysparm_my_userid', usr); // pass in userID
ga.addParam('sysparm_my_relativeid', related); // pass in relative sys_id
ga.getXML(populateBeneficiary);
}
3. Handle AJAX response - Deal with the response from #2
This is part of your client script
Here I put in the answer.has_value check as an example, but you may want to remove that until this works and you're done debugging.
function populateBeneficiary(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
answer = answer.evalJSON(); // convert json in to an object
// check if a value was found
if (answer.has_value) {
var dob = answer.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0];
$('fm1_ssn').value = answer.ssn;
$('fm1_address').value = answer.address;
$('fm1_email').value = answer.email;
$('fm1_phone').value = answer.mobile_phone;
$('fm1_date_of_birth').value = date;
}
else {
g_form.addErrorMessage('A beneficiary was not found.');
}
}