I am trying to pull an active user's email when they check a box. I wish to paste the active user's email in a separate column (adjacent currently, but the ability to be flexible would be nice). I have done this before in a different worksheet, but for some reason I cannot get it to work on this one. I can get it to paste a simple variable, or even the edit date, so I am thinking there must be something erroring out with the user specifically. I am on a work owned domain with company addresses, but so is the other sheet that is working. Anyway, here is what I have currently (amature, be gentle):
function onEditAdded(e) {
var activeSheet = e.source.getActiveSheet();
if (activeSheet.getName() == "New Hires") {
var aCell = e.source.getActiveCell(), col = aCell.getColumn();
if (col == 20) {
var dateCell = aCell.offset(0,1);
if (aCell.getValue() === true) {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
dateCell.setValue(email);
} else {
dateCell.setValue("");
}
}
}
}
I test your code and it should run without issues.
You just need to add it as an Installable Triggers
Manually create installable trigger:
Open your Apps Script project.
click Triggers alarm.
At the bottom right, click Add Trigger.
Select and configure the type of trigger you want to create.
Click Save.
function onEditAdded(e) {
var activeSheet = e.source.getActiveSheet();
if (activeSheet.getName() == "New Hires") {
var aCell = e.source.getActiveCell(), col = aCell.getColumn();
if (col == 1) {
var dateCell = aCell.offset(0,1);
if (aCell.getValue() === true) {
var email = Session.getActiveUser().getEmail();
Logger.log(email);
dateCell.setValue('user#example.com');
} else {
dateCell.setValue("");
}
}
}
}
Output:
You can also explore on how to create installable triggers programmatically, so that you wont need to add it manually every time you copy this script to a different workbook.
References:
https://developers.google.com/apps-script/guides/triggers/installable#managing_triggers_programmatically
Is there any way to automatically create installable triggers?
Related
I am trying to create an order form as a table, where a user enters a quantity required for a product in a row and the corresponding value is calculated by multiplying the user entry by the price held in another element of the same row of the table.
The form is loaded as a WebApp via Google and uses an Apps Script to retrieve the table values from a Google Sheet. The form loads OK with the data as expected but I just can't get the calculation part to work.
If I click the "place Order" button at the bottom of the form, the numberUsed values are included as parameters in the URL so it looks as though the values are updating in those elements but I haven't been able to access them to do the calculation and display it in the element called "value".
I am a novice programmer so I am sure it is something basic I am doing wrong (or not doing). I have created a JSBin https://jsbin.com/siwerat/edit?html,js,console,output and I have tried several variations of code derived from other answers and videos over the last couple of weeks without success so any help will be much appreciated.
//var numRows;
document.addEventListener('DOMContentLoaded', function() {
//new
var elems = document.querySelectorAll('cart');
var instances = M.FormSelect.init(elems);
// end new
document.getElementByname("cart").addEventListener("submit", getValues); //used to submit form - needs validation
//document.getElementByName("numberUsed").addEventListener("oninput",getValues);//used to submit form - needs validation
});
function test(event) {
"use strict";
event.preventDefault();
console.log("getValues function triggered");
}
function getValues() {
event.preventDefault();
var rows = document.querySelectorAll("package-row");
rows.forEach(function(currentRow) {
var numberUsed = Number(currentRow.querySelector('#numberUsed').value);
var price = Number(currentRow.querySelector('#price').value);
//var inPackage = Number(currentRow.querySelector('#inPackage').value);
var inPackage = 1;
var revenue = 1;
document.querySelectorAll('numberUsed');
if (numberUsed == "") {
if (isNaN(inPackage) || isNaN(price)) {
return;
}
revenue = price * inPackage;
} else {
if (isNaN(numberUsed) || isNaN(price)) {
return;
}
revenue = price * numberUsed;
}
var value = revenue * 5;
//currentRow.querySelector("#revenue").innerHTML = revenue;
currentRow.querySelector("#value").innerHTML = value;
});
}
Thanks Rafa for the guidance. After further reading/analysis I have got it working. The Event bubbling video by Learn Google Spreadsheets: [https://www.youtube.com/watch?v=fYpGe5ngujk][1] and an article on EncodeDNA.com (Dynamically create HTML table and Button using Javascript) helped narrow down the issues I had to get a solution.
I have the following working code which validates a list of recipients based on specific conditions. However, I'm looking to replace the resulting "Logger.log" actions with "Browser.msgbox" actions, and for some reason, GMail App Addons are not allowing me to do so:
function validateRecipients(e) {
var toEmails = e.draftMetadata.toRecipients, ccEmails = e.draftMetadata.ccRecipients, bccEmails = e.draftMetadata.bccRecipients, domains = [], uniqueDomains = [];
var allEmails = toEmails.concat(ccEmails, bccEmails);
for (var i = 0; i < allEmails.length; i++) {
domains[i] = allEmails[i].split("#").pop().split(".")[0];
}
uniqueDomains = domains.filter(listUnique);
if(uniqueDomains.length <= 2 && uniqueDomains.indexOf("verasafe") != -1) {
Logger.log("This Message is Good to Go");
}
else if(uniqueDomains.length == 0) {
Logger.log("This Message has no recipients");
}
else {
Logger.log("Please Validate Receipients of this Message and Try again");
}
}
Partial answer
Browser.msg can't be used on Gmail Add-ons, because, from https://developers.google.com/apps-script/reference/base/browser
This class provides access to dialog boxes specific to Google Sheets.
You cannot use Browser.msg or any of the UI classes with Gmail.
However, there is a new feature called Card Service that is meant to be used for the creation of UI for Gmail Addons.
Hope this helps!
The closest I could currently find is notification which shows a quick message at the bottom of the card (in Google's Material design it's called a snackbar
https://developers.google.com/apps-script/reference/card-service/notification
Other than that you need to replace the card with a new one.
function _navigateToCard(card: GoogleAppsScript.Card_Service.Card, replace: boolean)
{
var nav = CardService.newNavigation();
replace ? nav.updateCard(card) : nav.pushCard(card)
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}
Here is my code, and where I want to add a custom button:
function showPrompt() {
var ui = SpreadsheetApp.getUi();
var result_1 = ui.prompt(
'Enter task and associated subtasks, if any:',
ui.ButtonSet.OK_CANCEL); #ADD CUSTOM BUTTON HERE
//var button = result_1.getSelectedButton();
var task = result_1.getResponseText();
var result_2 = ui.prompt(
'Enter priority, based on when you will begin the task in a sequence of tasks:',
ui.ButtonSet.OK_CANCEL);
var button = result_2.getSelectedButton();
var priority = result_2.getResponseText();
if (button == ui.Button.OK) {
ui.alert('Task added.\nTask: '+task+'\nPriority: ' + priority);
}
}
I can not find a way to create a custom button. I came across this webpage: https://developers.google.com/apps-script/guides/ui-service, and apparently there used to be a createButton method, but this interface has already been deprecated.
Is there a work-around? I don't want to create an image of a button and link it to the script.
I am trying to generate a view based on the current user's group name. Group Name I am gathering from the custom list.
My question is how to apply the gathered group name to 'Group Name' column as a view parameter.
The only solution I figured:
I have created a view with a parameter.
I have added an HTML Form Web Part into the same page and connected it to the list view (sending the value to the parameter via web part connection). Then with a window.onload function I gather the current user's group name and pass this value via Form Postback function. But since the Postback function triggers full page reload, it falls into the endless loop of form submission > page reload.
Another way I have tried is attaching a click event listener to the BY MY GROUPS tab and it works perfectly, but the only disadvantage is that the page reloads each time user clicks on this tab, which I would like to avoid.
So the solution that I need is a way to post the form without a page reload.
Another option suggested here is to use CSR (client side rendering), but that has its own problems:
This code does not work as it is supposed to. In the console it shows me correct items, but the view appears untouchable.
Even if it worked, the other column values are still viewable in the column filter, as in this screenshot:
So, it seems that CSR just hides items from the view (and they are still available). In other words its behavior is different from, for example, a CAML query.
Or am I getting it wrong and there's something wrong with my code?
Below you can find my CSR code:
<script type='text/javascript'>
(function() {
function listPreRender(renderCtx) {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function() {
var currUserID = _spPageContextInfo.userId;
var cx = new SP.ClientContext('/sites/support');
var list = cx.get_web().get_lists().getByTitle('Group Members');
var items = list.getItems(SP.CamlQuery.createAllItemsQuery());
cx.load(items, 'Include(_x006e_x50,DepID)');
cx.executeQueryAsync(
function() {
var i = items.get_count();
while (i--) {
var item = items.getItemAtIndex(i);
var userID = item.get_item('_x006e_x50').get_lookupId();
var group = item.get_item('DepID').get_lookupValue();
if (currUserID === userID) {
var rows = renderCtx.ListData.Row;
var customView = [];
var i = rows.length;
while (i--) {
var show = rows[i]['Group_x0020_Name'] === group;
if (show) {
customView.push(rows[i]);
}
}
renderCtx.ListData.Row = customView;
renderCtx.ListData.LastRow = customView.length;
console.log(JSON.stringify(renderCtx.ListData.Row));
break;
}
}
},
function() {
alert('Something went wrong. Please contact developer')
}
);
});
}
function registerListRenderer() {
var context = {};
context.Templates = {};
context.OnPreRender = listPreRender;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(context);
}
ExecuteOrDelayUntilScriptLoaded(registerListRenderer, 'clienttemplates.js');
})();
</script>
I have the following function which works perfectly fine when I run it manually.
function LastUpdate() {
var thisSS = SpreadsheetApp.getActiveSpreadsheet();
var sheet = thisSS.getSheetByName('Roster');
var data = Session.getActiveUser().getEmail();
var Edit = 0;
var time = TimeStamp();
var Row;
Row = findInColumn("L", data);
Edit = checkEdits(Row);
if (Edit == 1)
{
sheet.getRange(Row,20).setValue(time);
}
}
I set up a trigger manually by going to Resources -> Triggers and selected the above Function to execute onEdit. Basically, whenever a cell in the sheet is edited, I want to automatically trigger this function to execute. I am not sure what the issue is !
Any help would be much appreciated.
EDIT - I tried to do this and this also does not work
function onEdit(e)
{
LastUpdate ()
}
Why don't you use the simple onEdit trigger instead of the installed trigger? Since you're looking for the latest edit made by the active user that might be a much easier, faster and more stable solution.
function onEdit(e){
var range = e.range; //edited range
range.getColumn();
range.setValue();
//etc
}