I'm putting together a macro that sends alert e-mails if two conditions are met.
The e-mails are being sent, but indiscriminately and not just when the conditions I want to set are being met.
The conditions: send an e-mail if any cell inside the range (I1:I9999) has white as background colour AND contains the text "QC".
This is what I have tried:
var QCJobRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("WIP").getRange("I1:I9999");
var Location = QCJobRange.getValue();
// Check for white cells with value=QC in Location column
if (Location = "QC") and (Background = "#ffffff");
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("WIP").getRange("C2");
var emailAddress = emailRange.getValues();
// Send Alert Email.
var message = 'bla';
var subject = 'bla';
MailApp.sendEmail(emailAddress, subject, message);
I'm working directly in the script editor that you can open from Google sheets.
It seems that some operators are not being picked up, f. e. "and" is not even highlighted and I get the following error message: "and" is not defined.
I've been combing the forums for a simple solution but am kind of stuck on the problem with "and".
Any suggestions?
Google Apps Script is based on Javascript
The syntax for "and" is &&
The syntax for an if statement is if(condition1&&condition2){...do something...};
The method getValue() is applicable to a single value (from a single cell), while getValues() is to be used for value ranges, which represent 2-dimentsional arrays
If you want to compare two values, use the operator ==
Here is a sample to modify your code in roder to send a message if the background of cell "I1" is white and its value "QC":
function myFunction() {
//if you do not have 999 rows full of data, please reduce your range - otherwise your code will be slow
var QCJobRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("WIP").getRange("I1:I9999");
var Locations = QCJobRange.getValues();
var firstLocation=Locations[0][0];
// Check for white cells with value=QC in Location column
if (firstLocation == "QC"&& QCJobRange.getBackgrounds()[0][0]== "#ffffff"){
// Fetch the email address
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("WIP").getRange("C2");
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = 'bla';
var subject = 'bla';
MailApp.sendEmail(emailAddress, subject, message);
}
}
Please consult the Apps Script tutorial for more samples and information:
Related
I am having an issue with a growing list. Previously I had a normal list, but as it is limited to displaying 100 items, I need to now change this to a growing list, which works fine now and I can get over 100 items loaded when I've put the growing="true" growingThreshold="50" growingScrollToLoad="false" properties on the list.
But now I have an issue with one of the number inputs in the custom list, when entering a number it is not staying set (it has a liveChange event that updates a text component).
I've set a breakpoint in the controller to test and it seems to bug out when I am trying to set the data changes (red arrow on attached image).
Can anyone see the issue with the logic? If any additional code snippets are required I could provide them.
onReceivedQuantityChange: function (oEvent) {
// get model and data
var oModel = this.getOrderModel();
var oData = oModel.getData();
// get item from path
var oItem = this._getOrderItemByPath(oEvent.getSource().getBindingContext(this.MODEL_ORDERS).getPath());
// set received value
oItem._ReceivedValue = oEvent.getParameters().newValue * (oItem.ValuationPrice / oItem.Quantity);
// apply data changes
oModel.setData(oData);
},
Controller code image
onReceivedQuantityChange: function (oEvent) {
var oModel = this.getOrderModel()
var sItemPath = oEvent.getSource().getBindingContext(this.MODEL_ORDERS).getPath()
var iValuationPrice = oModel.getProperty(sItemPath + '/ValuationPrice')
var iQuantity = oModel.getProperty(sItemPath + '/Quantity')
var iNewValue = oEvent.getParameters().newValue
var iReceivedValue = iNewValue * (iValuationPrice / iQuantity)
oModel.setProperty(sItemPath + '/_ReceivedValue', iReceivedValue)
}
If you use setProperty() on the Model you're only chaning the specific Property in DataModel and Sapui5 is able to proceed bindingchanges on this Property only (and not the whole model).
If you get the data out of the model by getData() you are only getting a reference to this Object. If you change something on this Object, you don't have to set it back by setData() (it is already there because you used the reference of this Object).
But Sapui5 need to know that there was a specific change in datamodel and this is done by using setProperty()
I used to be quite proficient in VBA with excel, but I'm currently trying to do something with Google Scripts and I am well and truly stuck.
Basically, I am trying like to extract data out of a standardised email from Gmail into a Google sheet. There are a couple of other threads on the subject which I have consulted so far, and I can get the body of the email into the sheet but cannot parse it.
I am new to regex, but it tests OK on regex101
I am also brand new to Google Script, and even the debugger seems to have stopped working now (it did before, so would be grateful if anyone can suggest why this is).
Here is my basic function:
function processInboxToSheet() {
var label = GmailApp.getUserLabelByName("NEWNOPS");
var threads = label.getThreads();
// Set destination sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Get all emails labelled NEWNOPS
for (var i = 0; i < threads.length; i++) {
var tmp,
message = threads[i].getMessages()[1], // second message in thread
content = message.getPlainBody(); // remove html markup
if (content) {
// search email for 'of:' and capure next line of text as address
// tests OK at regex101.com
property = content.match(/of:[\n]([^\r\n]*)[\r\n]/);
// if no match, display error
var property = (tmp && tmp[1]) ? tmp[1].trim() : 'No property';
sheet.appendRow([property]);
} // End if
// remove label to avoid duplication
threads[i].removeLabel(label)
} // End for loop
}
I can append 'content' to the sheet Ok, but cannot extract the address text required by the regex. Content displays as follows:
NOPS for the purchase of:
123 Any Street, Anytown, AN1 1AN
DATE: 05/05/2017
PRICE: £241,000
Seller’s Details
NAME: Mrs Seller
Thanks for reading :)
The return value of .match() is an array. The first captured group, containing the address, will be at index 1.
Based on the following line after your call to .match(), it looks like the tmp variable should have been assigned that array, not the property variable.
var property = (tmp && tmp[1]) ? tmp[1].trim() : 'No property';
That line says, if .match() returned something that isn't null and has a value at index 1, then trim that value and assign to property, otherwise assign it the string 'No property'.
So, try changing this line:
property = content.match(/of:[\n]([^\r\n]*)[\r\n]/);
To this:
tmp = content.match(/of:[\n]([^\r\n]*)[\r\n]/);
Thanks Kevin, I think I must have changed it while debugging.
The problem was with my regexp in the end. After a bit of trial and error the following worked:
tmp = content.match(/of:[\r\n]+([^\r\n]+)/);
I have a booking program in Google Sheets where a user can pick their name (uses data verification to provide a list of emails) and then the cell is then placed under protection so no other user can change the booking.
The strange thing that happens is that a person can enter in another person's email and then the cell is protected by the entered email not the user. The user can enter in a non-email string and it does not protect the cell.
The desired result would be that if the user's email and the data entered is the same, protect the cells otherwise it is free to be edited.
Any help would be appreciated!
function onEdit(e){
var CurrentUser = Session.getEffectiveUser().getEmail()
var range_DataEntered = SpreadsheetApp.getActiveRange();
var DataEntered = range_DataEntered.getValue();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var SheetName = SpreadsheetApp.getActiveSheet();
var Cell = ss.getActiveCell();
if (CurrentUser = DataEntered) {
var protection = range_DataEntered.protect()
// Ensure the current user is an editor before removing others. Otherwise, if the user's edit
// permission comes from a group, the script will throw an exception upon removing the group.
protection.addEditor(CurrentUser);
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
else {
//remove protection, set everyone to edit
range_DataEntered.protect().setDomainEdit(true);
}
}
if (CurrentUser = DataEntered) needs to be
if(CurrentUser === DataEntered)
A single = will assign a value not check for equivalency.
I'm working on converting my old Sitecore (< 8) code to work with Sitecore EXM. I'm having a hard time adding users to Recipient Lists from code. The answers in this post: Sitecore 8 EXM add a contact to list from listmanager don't answer my questions completely, and since I cannot comment, I've decided to start a new topic.
My first problem is that my EcmFactory.GetDefaultFactory().Bl.RecipientCollectionRepository.GetEditableRecipientCollection(recipientListId) gives a compilation error on the RecipientCollectionRepository, it says it does not exist. So I've used slightly different code. My code now, is as follows:
var contactRepository = new ContactRepository();
var contactName = this.Email.Text;
var contact = contactRepository.LoadContactReadOnly(contactName);
contact = contactRepository.CreateContact(Sitecore.Data.ID.NewID);
contact.Identifiers.AuthenticationLevel = Sitecore.Analytics.Model.AuthenticationLevel.None;
contact.System.Classification = 0;
contact.ContactSaveMode = ContactSaveMode.AlwaysSave;
contact.Identifiers.Identifier = contactName;
contact.System.OverrideClassification = 0;
contact.System.Value = 0;
contact.System.VisitCount = 0;
var contactPreferences = contact.GetFacet<IContactPreferences>("Preferences");
contactPreferences.Language = "nl-NL";
var contactEmailAddresses = contact.GetFacet<IContactEmailAddresses>("Emails");
contactEmailAddresses.Entries.Create("test").SmtpAddress = this.Email.Text;
contactEmailAddresses.Preferred = "test";
var contactPersonalInfo = contact.GetFacet<IContactPersonalInfo>("Personal");
contactPersonalInfo.FirstName = contactName;
contactPersonalInfo.Surname = "recipient";
if (recipientList != null)
{
var xdbContact = new XdbContactId(contact.ContactId);
if (!recipientList.Contains(xdbContact, true).Value)
{
recipientList.AddRecipient(xdbContact);
}
contactRepository.SaveContact(contact, new ContactSaveOptions(true, null));
}
So the recipientList is found, and the first time I add a contact to it, it increases the "Recipients" to 1 (checked using the /sitecore/system/List Manager/All Lists/E-mail Campaign Manager/Custom/RecipientList).
I also have a message which has this Opt-in recipient list, but when I check that message, it says it will be sent to 0 subscribers.
Any thoughts on this?
See this article listing known issues in Sitecore EXM:
https://kb.sitecore.net/articles/149565
"The recipient list shows "0" total recipients after recipients have been subscribed to the list. (62217)"
I got around this in a sandbox environment by adding a simple list (from csv, one contact) to the message. This upped the total recipient count from 0 to 1 which allows the message to be activated. All recipients in the composite list were sent a message.
Do you have a distributed environment? If so the RecipientCollectionRepository will not work as it is only available on a Content Management server. You could try using the ClientApi:
ClientApi.UpdateSubscriptions(RecipientId recipientId, string[] listsToSubscribe, string[] listsToUnsubscribe, string managerRootId, bool confirmSubscription)
and just add the id of the list you want to subscribe people to in the first string array.
Just a quick note with this option, listToUnsubscribe does not actually remove a contact from a list. You are meant to pass through the ID of the opt out list. This basically excludes them from any future emails. One draw back is that you will no longer be able to resubscribe them.
If this does not work for you you will need to create your own API between your CD server and your CM server where the CM server uses the recipientCollectionRepository to subscribe and unsubscribe
I'm struggling to get my Script to run an IF function. Basically I want to run a script based on specific cell contents.
I would like an IF function to run based on this and have written the following code:
function sendemail () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = SpreadsheetApp.getActiveSheet();
var targetSheet = ss.getSheetByName("Response");
var vCodes = ss.getSheetByName("Codes")
var vResults = targetSheet.getRange("E2").getValues();
var emailAddresses = targetSheet.getRange("B2").getValues()
var dataRange = vCodes.getRange(1, 1, vResults, 1).getValues();
var subject = "Here are your Wi-Fi Codes!";
var vLength = vCodes.getRange("C2").getValues();
if (vLength == "24 hours"){
MailApp.sendEmail(emailAddresses, subject, dataRange);
targetSheet.deleteRows(2);
vCodes.deleteRows(1,vResults);
}
}
If the value in C2 is "24 hours" I'd like it to send an e-mail. At the moment when I run the script there are no errors but it doesn't send any e-mail as the IF function obviously isn't running correctly.
If I edit the code to say:
if (vLength == "")
then the e-mail sends. It doesn't seem to recognise "24 hours" as valid data to look up.
Can anyone see what I'm doing wrong?
The value you get from the cell is not what you think because you are using getValues() with an 's' and you probably know that this method always returns an array of arrays, even when a single cell is defined as range.
You have 2 options :
use getValue() to get the string content of the cell
use getValues()[0][0] to get the first (and only) element of this array.
I would suggest the first solution as I think it's generally a good idea to use appropriate methods... getValue() for single cell and getValues() for multiple cells...
I didn't check further but I'm pretty sure it will work with this change (applies to vResults , emailAddresses and vLength) .
It would also be careful to ensure that vResults is a number since you use it to define a range... you could use Number(vResults) as a safety measure.