I am attempting to automate emails from google sheets. However, an error pops up each time I try to save.
What do I need to adjust on line six with the error 'Illegal character. (line 6, file "Code")'
i am a beginning any help would be appreciated.
function sendEndOfYearEmails() {
var spreadSheet = SpreadsheetApp.getActiveSheet();
var dataRange = spreadSheet.getDataRange();
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var text = ‘our initial sample text’;
for (var i = 1; i < data.length; i++) {
(function(val) {
var row = data[i];
var emailAddress = row[1]; //position of email header — 1
Var name = row[0]; // position of name header — 1
var message = ‘Dear’ + name + ‘\n\n’ + text;
var subject = ‘Sending emails from a Spreadsheet’;
MailApp.sendEmail(emailAddress, subject, message);
})(i);
}
}
My desire is to achieve an automated email system to work smoothly with no errors in the script.
‘’ is not valid here, use '' to define string literal
TL;DR: You're using the wrong type of quote, use ' instead of ’.
Detailed answer:
This is a template literal:
let what = "World";
`Hello ${what}!`
This is a string literal:
"Hello World!"
'Hello World!'
All three strings output the exact same thing (Hello World!).
The problem you're facing occurs because you're not using the correct type of single quote, you're supposed to use ' or " instead of ’.
Good luck.
Related
I am using extendscript to build some invoices from downloaded plaintext emails (.txt)
At points in the file there are lines of text that look like "Order Number: 123456" and then the line ends. I have a script made from parts I found on this site that finds the end of "Order Number:" in order to get a starting position of a substring. I want to use where the return key was hit to go to the next line as the second index number to finish the substring. To do this, I have another piece of script from the helpful people of this site that makes an array out of the indexes of every instance of a character. I will then use whichever array object is a higher number than the first number for the substring.
It's a bit convoluted, but I'm not great with Javascript yet, and if there is an easier way, I don't know it.
What is the character I need to use to emulate a return key in a txt file in javascript for extendscript for indesign?
Thank you.
I have tried things like \n and \r\n and ^p both with and without quotes around them but none of those seem to show up in the array when I try them.
//Load Email as String
var b = new File("~/Desktop/Test/email.txt");
b.open('r');
var str = "";
while (!b.eof)
str += b.readln();
b.close();
var orderNumberLocation = str.search("Order Number: ") + 14;
var orderNumber = str.substring(orderNumberLocation, ARRAY NUMBER GOES HERE)
var loc = orderNumberLocation.lineNumber
function indexes(source, find) {
var result = [];
for (i = 0; i < source.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
alert(result)
}
indexes(str, NEW PARAGRAPH CHARACTER GOES HERE)
I want all my line breaks to show up as an array of indexes in the variable "result".
Edit: My method of importing stripped all line breaks from the document. Using the code below instead works better. Now \n works.
var file = File("~/Desktop/Test/email.txt", "utf-8");
file.open("r");
var str = file.read();
file.close();
You need to use Regular Expressions. Depending on the fields do you need to search, you'l need to tweek the regular expressions, but I can give you a point. If the fields on the email are separated by new lines, something like that will work:
var str; //your string
var fields = {}
var lookFor = /(Order Number:|Adress:).*?\n/g;
str.replace(lookFor, function(match){
var order = match.split(':');
var field = order[0].replace(/\s/g, '');//remove all spaces
var value = order[1];
fields[field]= value;
})
With (Order Number:|Adress:) you are looking for the fields, you can add more fields separated the by the or character | ,inside the parenthessis. The .*?\n operators matches any character till the first break line appears. The g flag indicates that you want to look for all matches. Then you call str.replace, beacause it allows you to perfom a single task on each match. So, if the separator of the field and the value is a colon ':', then you split the match into an array of two values: ['Order number', 12345], and then, store that matches into an object. That code wil produce:
fields = {
OrderNumber: 12345,
Adresss: "my fake adress 000"
}
Please try \n and \r
Example: indexes(str, "\r");
If i've understood well, wat you need is to str.split():
function indexes(source, find) {
var order;
var result = [];
var orders = source.split('\n'); //returns an array of strings: ["order: 12345", "order:54321", ...]
for (var i = 0, l = orders.length; i < l; i++)
{
order = orders[i];
if (order.match(/find/) != null){
result.push(i)
}
}
return result;
}
What I need is to check for several key words within a textarea before allowing my students to submit their lesson summaries.
The following regex works fine as long as they don't click enter to create a new paragraph.
/^(?=.*\bmodel|models\b)(?=.*\btheory|theories\b)(?=.*\blaw|laws\b)(?=.*\bscale\b)/i;
From what I've been reading, it would seem that the following modification to the regex should allow my validation script to read across line breaks, but I haven't had any success.
var ck_summary = /^(?=.[\S\s]*\bmodel|models\b)(?=.[\S\s]*\btheory|theories\b)(?=.[\S\s]*\blaw|laws\b)(?=.[\S\s]*\bscale\b)/i;
I'm (obviously) a beginner at this and eager to learn. Can anyone please explain what am I doing wrong? Many thanks!
Here's my entire summary validation script...
var ck_studentid = /^[0-9]{6,6}$/;
var ck_summary = /^(?=.[\S\s]*\bmodel|models\b)(?=.[\S\s]*\btheory|theories\b)(?=.[\S\s]*\blaw|laws\b)(?=.[\S\s]*\bscale\b)/i;
function validate(sumform){
var studentid = sumform.studentid.value;
var summary = sumform.summary.value;
var errors = [];
if (!ck_studentid.test(studentid)) {
errors[errors.length] = "Check your Student ID";
}
if (!ck_summary.test(summary)) {
errors[errors.length] = "Make sure you used all of the vocabulary terms AND you spelled them correctly.";
}
if (errors.length > 0) {
reportErrors(errors);
return false;
}
return true;
}
function reportErrors(errors){
var msg = "Uh oh, looks like we have a problem...\n";
for (var i = 0; i<errors.length; i++) {
var numError = i + 1;
msg += "\n" + numError + ". " + errors[i];
}
alert(msg);
}
From what I've been reading, it would seem that the following
modification to the regex should allow my validation script to read
across line breaks, but I haven't had any success.
var ck_summary = /^(?=.[\S\s]*\bmodel|models\b)(?=.[\S\s]*\btheory|theories\b)(?=.[\S\s]*\blaw|laws\b)(?=.[\S\s]*\bscale\b)/i;
This didn't work for you because you did not modify it very well.
.*: captures every character/word except a newline \n, that was why you were told to modify it to [\S\s]* which capture every character/word including a newline \n. But looking at your pattern, you didn't totally modify it, you should remove all the dots . before [\S\s]*.
Your new code should be like this
var ck_summary = /^(?=[\S\s]*\bmodel|models\b)(?=[\S\s]*\btheory|theories\b)(?=[\S\s]*\blaw|laws\b)(?=[\S\s]*\bscale\b)/i;
I am working on a tool that would receive text that has been copied from a word document, and return an html output for copy/paste into an email client for email marketing.
During this process, one of the steps the tool needs to handle is the replacement of special characters within the copied values. The output needs to show the encoded values so when they are copied into the email client, they render accordingly during the mail send process
The problem is that there are multiple inputs the user can populate and right now the code is VERY WET... I want to set up the tool to be a little cleaner, and not repeat the code as often.
Currently the input is given to the tool via a prompt();
I am taking that input and replacing the special characters ™, ®, Ø, ´, ”, ‟ and others (partial list given for this example) as needed:
JS (Commented Version)
msg2 = prompt("enter text here");
//long version to tag each replacement with it's identifying name
msg2 = msg2.replace(/[\u0027]/g, '''); // Apostrophe ´
msg2 = msg2.replace(/[\u2122]/g, '™'); // trademark ™
msg2 = msg2.replace(/[\u00AE]/g, '®'); // R-Ball ®
msg2 = msg2.replace(/[\u201c]/g, '"'); // Left Double Quote ‟
msg2 = msg2.replace(/[\u201D]/g, '"'); // Right Double Quote ”
msg2 = msg2.replace(/[\u2018]/g, '''); // Left Single Quote ‛
msg2 = msg2.replace(/[\u2019]/g, '''); // Right Single Quote ’
msg2 = msg2.replace(/[\u2022]/g, 'ߦ') // Bullet •
JS (Short Version)
msg2 = prompt("enter text here");
msg2 = msg2.replace(/[\u0027]/g, ''').replace(/[\u2122]/g,
'™').replace(/[\u00AE]/g, '®').replace(/[\u201c]/g,
'"').replace(/[\u201D]/g, '"').replace(/[\u2018]/g,
''').replace(/[\u2019]/g, ''').replace(/[\u2022]/g,
'ߦ');
BUT... I need to run this same replacement on a number of prompts. I don't want to repeat this in the code a bunch of times with each of the variables changing as needed.
What I would rather do is create a function to handle the replacement, and then simply create an array of the variables and run the function on the array...
Example
function txtEncode () {
...replacment code here...
}
var inputTxt = [msg1, msg2, msg3...];
for (var i=0; i < inputTxt.length; i++){
txtEncode(i)
}
Just make an array with replacement pairs:
var replacements = [ ["&", "&"], ["'", """] etc
and apply them one by one:
replacements.forEach(function(pair) {
msg = msg.split(pair[0]).join(pair[1]);
});
split/join is better to replace literal strings than .replace which is intended for use with regular expressions.
Also, your encoding doesn't look right, ® will be displayed as ®, not as ®
You can use a global find/replace function and extend the string prototype, I have this code in one of my fiddles, but I can't find the origin.
Code:
String.prototype.replaceArray = function(find, replace) {
var replaceString = this;
var regex;
for (var i = 0; i < find.length; i++) {
regex = new RegExp(find[i], "g");
replaceString = replaceString.replace(regex, replace[i]);
}
return replaceString;
};
var msg2 = 'demo \u0027'
var find = ["\u0027"];
var replace = ["'"];
msg2 = msg2.replaceArray(find, replace);
Demo: http://jsfiddle.net/IrvinDominin/YQKwN/
Add a method to the String object for your code.
String.prototype.myCleanString = function(){
return this.replace(/[\u0027]/g, ''')
.replace(/[\u2122]/g,'™')
.replace(/[\u00AE]/g, '®')
.replace(/[\u201c]/g, '"')
.replace(/[\u201D]/g, '"')
.replace(/[\u2018]/g, ''')
.replace(/[\u2019]/g, ''')
.replace(/[\u2022]/g, 'ߦ')
.replace(/foo/g, 'bar');
}
Call as needed... http://jsfiddle.net/XKHNt/
I'm fairly new to GAS but learning fast. Thanks in advance for any help you can offer on this!!
I need to be able to send an email to two different email addresses based on the first characters of my last name field. So, if the first character of var last is A - L, send the email to this person, otherwise, if the first character is M - Z, send to this other person. How would I create a conditional if statement for this? My current script which currently sends all email to the same address is as follows:
function onFormSubmit(e) {
var timestamp = e.values[0];
var last = e.values[3];
var first = e.values[4];
var employment_status = e.values[5];
var unemployed_date = e.values[6];
var employment_type = e.values[7];
var employer_name = e.values[8];
var employer_address = e.values[9];
var employment_begin = e.values[10];
var comments = e.values[11];
var email = "xxxxx#gmail.com";
var subject = "Employment Update Received";
var message = "<HTML><BODY>"
+ "<P>Dear " + first + " " + last + ","
etc. etc.
+ "</HTML></BODY>";
MailApp.sendEmail(email, subject, "", {htmlBody: message});
}
#JonnyJS is on the right track. I used just regular expressions. Regex literals are wrapped in / / and options occur after the last /. I usually use RegexPal to test regular expressions for GAS. You can find more information about JS Regex on MDN. Most notably, the test function that I use below.
Here's the regex I used:
^ Starts of string
[A-L] Any letter A-L
.* Any character, 0 or more times
$ End of String
i Option for case insensitive regex
Here is a snippet for you to use.
var last = e.values[3].trim(); // Remove any leading spaces to be safe
var email = "Catch-Other-Names#mydomain.com";
var reAtoL = /^[A-L].*$/i;
var reMtoZ = /^[M-Z].*$/i;
if (reAtoL.test(last)) {
email = "A-to-L-Recipient#mydomain.com";
} else if (reMtoZ.test(last)) {
email = "M-to-Z-Recipient#mydomain.com";
}
// If both fail, then it's going to the Catch Other Names
Mail.sendEmail(email, subject, "", {htmlBody:message});
You havent been really clear but i hope i got what you meant.
I solve it by using two built in js stuff.
we cut the string to the first latter.
we matching the cutted part to regular expression.
Consider view that on JSFIDDLE
lets write the markup first:
<form>
<input name="last" type="text"/></form>
<br><br>
<div id="status">
</div>
now some JS:
var rel = new RegExp("[a-l A-L]");
var rez = new RegExp("[m-z M-Z]");
$("form input").on("change",function(e){
vall = $("form input").val().substr(0,1);
console.log(vall);
if (rel.exec(vall)) {
$("#status").text("We Got a winner! the last name starts with letter from a-l");
}
else if (rez.exec(vall)) {
$("#status").text("Hodey! the last name starts with letter from m-z");
}
else {
$("#status").text("Well, Nothing cool here.");
}
});
as you can see im using jquery to prettify things.
if you still in trouble please write in comments.
i have data having emails:
data pattern is like: first_name last_name email
data = foo bar foo#bar.com, foo baz foo#baz.com,foo foo foo#foo.com,bar#bar.com , bar baz bar#baz.com
It may contain spaces. I have to valiadte all the emails by extracting the data.
Note: There may be spaces between words so that spliting by space gives me more some unwanted data ...
function validate() {
email_data = data.split(',') // This will get the all data spliting by ','
for (i = 0; i<email_data.length; i++) {
email_new_data = email_data.split(' ') //spliting data by space
// Now I could not find the way to extract emails (only ) from data
}
}
Any suggestion will be helpful.. thanks
The following function split the main data string into an array; which then can be parsed with RegExp. As far as I can tell you only want to get the email address; so, we use a Regular Expression to match an email address. If it matches, you have a valid email. If there's no match; then basically there's no valid email on the given segment.
Please note that Regular Expression 100% success Email Validation is just impossible; because the RFC is just extremely complicated, check more about here: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html
function validate() {
data = "foo bar foo#bar.com, foo baz foo#baz.com,foo foo foo#foo.com,bar#bar.com , bar baz bar#baz.com";
email_data = data.split(','); // This will get the all data spliting by ','
for (i = 0; i < email_data.length; i++) {
// Get emails, change console.log to alert if you don't know how to use console.
console.log(email_data[i].match(/[\w._+-]+#[\w._+-]+\.[\w]{2,6}/));
}
}
validate();
Working example:
http://jsfiddle.net/kuroir/H7VaT/
var email_list = new Array();
var k = 0;
for (j=0; i<email_new_data.length; i++) {
if (email_new_data.search('#') != -1) {
email_list[k++] = email_new_data;
}
}
Unless you have people with # in their name, it should work...
(This is in case you have people with space in their name/empty name string)
You need to clarify a bit more of what you want to do? Judging from your wording, you want to validate email addresses. Here's some untested code:
var emailpattern = new RegExp("^[a-zA-Z0-9._-]+#[a-zA-Z0-9-]+\.[a-z]{2,4}$");
function validateEmail(email){
return emailpattern.match(email);
}
function processEmail(emailData){
emailData = emailData.split(' ');
var firstName = emailData[0];
var lastName = emailData[1];
var email = emailData[2];
if (validateEmail(email)){
// Your stuff if valid
} else {
// If email is not valid
}
}
var data = data.split(','); // Whereever you get your data from
for (var i=0; i<data.length; i++){
processEmail(data[i]);
}
Can you validate this on the server instead?
The reason I ask is that many server-side libraries have pre-built libraries that do exactly this, implemented as a proper parser for the spec, not a RegEx.
Splitting the data and extracting the email is the easy part, validating the email is what will be hard.
See here: http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx