I am getting the data from a form and writing in a google Document. It has fields like Name, Age, Address and so on. Address is of type paragraph text. My question is that while writing the data in a google Doc through a on-submit trigger script, how do I remove manual line breaks in the Address as input by the person filling the form. i.e. I want address to be a continuous string, without the breaks that the person filling the form may have put while typing his address.
ok here are more details.. the Address field in my form is called 'Address', i have a onformsubmit triggered script that reads all the data entered by the person in the form and puts in a google Doc App.
i read the values typed in the form as :
for(var field in e.namedValues) {
message += field + ' :: ' + e.namedValues[field].toString().replace("\n",", ") + "\n";
}
But in my google doc, the lines for the value of Address sre still broken where the person filling the form has broken the lines. i want to eliminate these line breaks and substitute it with commas so the address is continuous.
Change part of the line with the replace function to
e.namedValues[field].toString().replace(/(\r\n|\n|\r)/gm, ", ");
It works!
Remove the line breaks by taking the string that has the text from the paragraph, and passing it through string.Replace("\n", ""); If that doesn't work, then you will need to provide more details.
Also you can work with the range class:
function editRow(r){
var sheet = SpreadsheetApp.getActiveSheet();
var relevantRange = sheet.getRange(r, 21, 1, 1);
artefactRange.setValue(relevantRange.getValue().replace(/(\n)/g, ', '));
}
Related
This is my scenario:
I have a Google Form, and the values are added to a SpreadSheet. I have an Apps Script started with function onFormSubmit(event)
I get the values from the Form with var Variable = event.namedValues["Question 1"];
I use the value of this variables with some "if statements".
This Apps Script has been running OK, but i'm still making changes to add new functionalities (adding more questions on the Form, new functions on the Script), but suddenly in one of the variables starts to appear a comma into the values from this variable.
After checking all the Script, i decided to copy all the script to a new one. And when I used this new scenario (same content of files), the mysterious comma disappeared. I continued with new developments, but after some new changes (newer ones) the comma started to appear on one of the variables in their values. And after some new changes the comma moved from adding at the begging of the value, started to appear at the end.
I have checked the values on the spreadsheet, and they appear with no comma, the comma only appears when i use the values of that variable on the script.
I print the value with Logger.log(Variable) after i save the value from the event, and the comma is there, so i don't think that my code is adding this comma.
Any idea why is this happening? Is there a way to check on the value of a variable a character (in this case the comma) inside the Script? Something like Replace(Variable,",",""), with this i can check all the values got from the event before i start using them inside the Script. Commas aren't used on the values of the variables.
THESE ARE THE LINES AFFECTED (The script has more than 500 lines):
function onFormSubmit(event){
var Variable = event.namedValues["Question 1"];
Logger.log("Value after event" + Variable);
if (Variable == "AAAA"){
// do "something";
}
else {
// do "something different"
}
}
As the comma appears the if statement never gets a TRUE because the value starts to be "AAAA," so the do "something" never happens.
Answers:
Any idea why is this happening?
There might be some typos out there that needs to be cleaned. It would be better if you could also provide your code or at least how you wrote it.
Is there a way to check on the value of a variable a character (in this case the comma) inside the Script?
You can check the presence of a character/string in a variable by using includes.
var string = "I am Iron man,";
var hasComma = string.includes(","); // True
If you want to replace all the instances of comma, then use replace
// Replace all commas with blank
var string = string.replace(",", ""); // "I am Iron man"
EDIT:
Since e.namedValues["Question 1"] returns an object, you need to change the variable into string and then use the replace function
Code:
var Variable = e.namedValues["Question 1"];
Variable = String(Variable).replace(",", "");
Logger.log("Value after event: " + Variable);
if (Variable == "AAAA"){
// do "something";
}
else {
// do "something different";
}
References:
includes
replace
I hit a wall here with this script. I am trying to get the body of a PayPal email that tells me I have a new subscription. I need the email address of the new subscriber. So...
I get the thread
I get the body. It's full of CSS and code, I don't see any info on the use. On the web page in the source it's all code it seems.
When I output it to a spreadsheet Show modal dialog it's looks perfect. I see the email address I am trying to get.
Is there a way to get that text? Then I can get the email address and the rest is EASY for me :-).
I hope I'm explaining things right.
This is far as I get with trying to get the text from this.
Thanks for any help you can spare. Maybe this is way over my head in which case, I'll drop it. But I just need the email address from this!
function getEmailFromFolder() {
// Log the subject lines of the threads labeled with MyLabel
var label = GmailApp.getUserLabelByName("NewVWMember");
var threads = label.getThreads();
var message = threads[0].getMessages()[0]; // Get first message
var body = message.getBody();
var output = HtmlService.createHtmlOutput(body);
//var n = body.search("mailTo");
var ui = SpreadsheetApp.getUi();
ui.showModalDialog(output, 'I want this!');
}
Answer:
You can use a regular expression to extract all emails out of a string.
Regular Expression:
There are multiple diffent ways of doing this, an example would be the following:
/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/g
Rundown of this regular expression:
[a-zA-Z0-9._-]+: matches the username - any number of characters from [A-Z], [a-z], [0-9], . and _
# matches the literal character #
[a-zA-Z0-9._-]+: matches the domain - again like the username, any number of characters from [A-Z], [a-z], [0-9], . and _
\.: macthes the literal character .
[a-zA-Z0-9._-]+: matches the top-level domain, as beforethis can be any number of characters from [A-Z], [a-z], [0-9], . and _.
g: returns globally, so will not return after the first email has been found.
You can test out the regular expression on RegEx101 here.
Email Extraction:
With the regular expression, you can extract an array of email addresses from the message body with just a few extra lines of code:
function getEmailFromFolder() {
var regex = /([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/g;
var label = GmailApp.getUserLabelByName("NewVWMember");
var threads = label.getThreads();
var message = threads[0].getMessages()[0];
var body = message.getBody();
var output = HtmlService.createHtmlOutput(body);
var emails = output.getContent().match(regex).toString();
var html = HtmlService.createHtmlOutput(emails);
var ui = SpreadsheetApp.getUi();
ui.showModalDialog(html, 'I want this!');
}
Here, output is a string of all the email addresses in the message. It needs to be converted to string to display in the modal dialog, but you can do with this as you see fit.
References:
Regular Expression - Wikipedia
RegEx 101
I have a column of email addresses and would really like to turn them into clickable links. I am a rookie coder still and trying to figure this out. So the code below is from trying to record a macro in google app script. I need it to reference the current cell, turn that cells email address into a link to it, then move down the column.
Should be super simple, take cell A1's contents, turn into link of the contents in the cell, then move down the list and do it again until it completes the entire column.
function emailing() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getActiveRangeList().setShowHyperlink(true);
spreadsheet.getCurrentCell().setFormulaR1C1('=HYPERLINK("mailto:test#emailaddress.com","test#emailaddress.com")');
};
Each email will be turned into a link to that email address.
I have tested the following code and worked successfully converting each email to a hyperlink. Assuming you want to convert all of them when you use the macro, this code works for you:
function emailing() {
var sheet = SpreadsheetApp.getActiveSheet();
for(i=0; i<1048576; i++) {
var gcells = sheet.getRange(6 + i, 6); //In my test i put the emails in the F column starting from the 6th row.
var email = gcells.getValue();
if (gcells.isBlank()) {
break
}
gcells.setFormulaR1C1('=HYPERLINK("mailto:' + email + '","' + email + '")');
}
}
I used the number 1048576 as the limit on the for because that's the maximum number of rows you can have, although it'll break when it takes a blank cell.
If what you want is to convert to a hyperlink only the cell you have selected and then change the selected cell, you should use the getActiveCell function [1] to set only that value and then the activate() function [2] to change the selection to the next cell.
[1] https://developers.google.com/apps-script/reference/spreadsheet/sheet#getactivecell
[2] https://developers.google.com/apps-script/reference/spreadsheet/range#activate()
I have a google-form that has the following two fields:
Email address: - A text box
Tool: - A radio button
Tool 1
Tool 2
Tool 3
The user would enter his email address and select a tool and click submit. I would like the following message to appear:
Thanks for responding. An email has been sent to you to at entered email address to download selected tool.
I have the following piece of code in the script editor
function emailFormSubmission() {
var form = FormApp.getActiveForm();//the current form
var dest_id = form.getDestinationId(); //the destination spreadsheet where form responses are stored
var ss = SpreadsheetApp.openById(dest_id);//open that spreadsheet
var theFormSheet = ss.getSheets()[0]; //read the first sheet in that spreadsheet
var row = theFormSheet.getLastRow(); //get the last row
var emailid = theFormSheet.getRange(row,2,1,1).getValue();//get column 2 corresponding to the email id. column 1 is timestamp. so, skip that.
var tool = theFormSheet.getRange(row,3,1,1).getValue();//get column 3 corresponding to the selected tool.
form.setConfirmationMessage('Thanks for responding. An email has been sent to you '+ emailid + ' to download' + tool);
}
I have also set the triggers to be Run -> emailFormSubmission, Events -> from Form , onFormSubmit.
What happens is: Suppose the first user ('A') enters his information and clicks submit. His entered information gets displayed correctly. When second user ('B') enters his information and clicks submit, A's information is displayed. When third user ('C') enters his information and clicks submit, then B's information is displayed. I found that the issue is with "getlastrow()" since the spreadsheet is updated after emailFormSubmission is processed.
Whats wrong with the above code? How do I fix this?
UPDATE
Based on #wchiquito's comments, I changed the code to following to make it work.
function emailFormSubmission(e) {
var form = FormApp.getActiveForm();
//Check this link on how to access form response:
//https://developers.google.com/apps-script/understanding_events?hl=en
var responses = e.response;//e is of type formresponse.
var emailid = responses.getItemResponses()[0].getResponse();
var tool = responses.getItemResponses()[1].getResponse();
Logger.log(emailid);
Logger.log(tool);
form.setConfirmationMessage('Thanks for responding. An email has been sent to '+ emailid + ' with instructions to download ' + tool +'. If you do not find our email in your inbox, please check your spam folder');
Logger.log(form.getConfirmationMessage());
}
Remember that the event On form submit (Understanding Events) receives a parameter that has the following structure:
values
range
namedValues
and you can do something like:
function emailFormSubmission(e) {
...
var row = e.range.getRow();
...
}
Try the following code to observe the structure of the parameter e:
function emailFormSubmission(e) {
...
Logger.log(e);
...
}
UPDATE
First, excuse my confusion, I showed you the structure of a Spreadsheet form submit event when you really are using a Form submit event.
Sure enough, a Form submit event has the following structure:
response
Returning an object of type FormResponse.
Therefore, defining the event: On submit form (Form submit event), you can do something like the following:
function emailFormSubmission(e) {
var itemResponses = e.response.getItemResponses();
for (var i = 0, len = itemResponses.length; i < len; ++i) {
Logger.log('Response #%s to the question "%s" was "%s"',
(i + 1).toString(),
itemResponses[i].getItem().getTitle(),
itemResponses[i].getResponse());
}
}
However, the confirmation message set according to the data sent as responses of the form, does not seem very clear, you can set the message, but will not display for the active response, if not for the next.
My first guess is these two lines right here:
var emailid = theFormSheet.getRange(row,2,1,1).getValue();//get column 2 corresponding to the email id. column 1 is timestamp. so, skip that.
var tool = theFormSheet.getRange(row,3,1,1).getValue();//get column 3 corresponding to the selected tool.
When you call getLastRow() on a sheet - you're getting the last row. Sure, but considering the order of events and how these values are processed, you need a +1, to get the most recent submission. Currently you're one row behind when your code runs to update the Form confirmation message.
So just change your code to the following:
var emailid = theFormSheet.getRange(row+1,2,1,1).getValue();
var tool = theFormSheet.getRange(row+1,3,1,1).getValue();
Spreadsheets are the most confusing of Google services, in my opinion. When you get values in the Spreadsheet, they're returned as an [] or [][] depending on what your Range is when you call getValues(). But getRange() on a sheet starts at index 1 (to make it easier to read in code I suppose). Often times I find that I have an off-by-one error because of the way data is passed around. Just keep that in mind as you work with Spreadsheets :)
Short answer: want you want can't be done with Google forms.
Explanation:
form.setConfirmationMessage() sets the confirmation message for the form as stored on the server, not for the current active form. Same applies for example for form.setTitle(). The active form will not be modified. One would expect different behaviour for the confirmation message, but alas, this is not the case.
Yes, you can do this with the add-on "Formfacade".
It's free to use in 1 form.
I'm Working on creating script that will perform the actions described below. so far, I've managed to get the first two parts to function, but am now stuck on getting anything more to work. I've reviewed several response forums and tried the suggestions, but no success.
Desired script flow:
form submitted from spreadsheet form
completes fields:
Timestamp
Username (email collected on submission)
Student
Grade
Intervention Plan
Core Reading/Math
Team (email list)
1 script runs onFormSubmit that then creates a copy of a template document, renames that new copy to the e.value "student" submitted in form,
2 then replaces selected text strings within the document with values submitted in the form.
3 Add editors to new document and sends notification with desired instructions
4 creates event (one week from submission date) event details include instructions and link to shared document for team members to complete with their input, sends event invitation to email list.
Here is the working script so far.
function formSubmitValues(e) {
var timeStamp = e.values[0];
var userEmail = e.values[1];
var student = e.values[2];
var grade = e.values[3];
var conern = e.values[4];
var readingCore = e.values[5];
var mathCore = e.values[6];
var interventions = e.values[7];
var team = e.values[8].toString(); // "just to be sure"..Henrique says add .toString this allowed the replaceText part to work
//Makes copy of template document and renames
var tempID = ("1Rq0pDAnuGNfL6W3GB0ZuLeWM2uYzHpKzoyxoXlwjtgE") // use document ID from Template Document
var copyId = DocsList
.getFileById(tempID)
.makeCopy(student + " Initial Referral") // names new copy as student's name
.getId();
// trying to add editors to new document using email list generated in form submit value of "team"
DocsList.getFileById(copyId).addEditors([team]);
// replaces text within template with selected fields from formSubmitValues
var doc = DocumentApp.openById(copyId)
var body = doc.getActiveSection();
body.replaceText("%STUDENT%", student);
body.replaceText("%DATE%", timeStamp);
body.replaceText("%TEACHER%", userEmail);
body.replaceText("%TEAM%", team);
return doc;
}
REPORTED ISSUE RESPONSE: Here is what they said: "The function takes an array or strings, like: DocsList.getFileById(copyId).addEditors(['parent#domain.com', 'parent2#domain.com']);
I tried entering emails directly into script like this and things worked.
So my problem is not the 'addEditors method, but lies in getting the form submitted emails to be passed correctly. Any suggestions on how I would do this?
I have tried what I believe to be all combinations of using .toString(), or not, and using .Split(',').
RE-DEFINE PROBLEM : So it is an issue of how the emails are passed from the e.values form submit.
Here is where I'm at:
When I type emails into script directly: .addEditors(['parent#domain.com', 'email2#domain.net', 'email3#gmail.com']) it works, (I did have to move the addEditors method in the script to go right after the .makeCopy instead of at the end.)
This is what the Execution Transcript shows:
File.addEditors([[parent#domain.com, email2#domain.net]]) and it runs the rest of the script. note: One part I don't understand is the single quotes i.e. 'email' They must be typed in the script, but don't show up on Transcript when run. I've tried putting them around emails in the form, but it makes them show in Transcript and still doesn't run anyway.
So this is what script looks like now:
var tempID = ("1Rq0pDAnuGNfL6W3GB0ZuLeWM2uYzHpKzoyxoXlwjtgE") // use document ID from Template Document
var copyId = DocsList
.getFileById(tempID)
.makeCopy(student + " - TestingCopy") // names new copy as student's name + text
.addEditors([team.split(',')])
.getId();
But when I use the var team with or without .split(',') it does not work. But in the Transcript it shows:
File.addEditors([[rreynolds#domain.net, parent#domain.com]])
which looks identical as to what shows when it does work, but that is the last thing shown in Transcript and editors are not added to document and the script does not finish.
I'm obviously not understanding something here. Is there a way I could get the emails in the team e.values to be treated in a way that the addEditors method is requiring? In the spreadsheet cell they appear as a CSV. i.e rreynolds#domain.net, parent#domain.com
Do they have to be read one at a time, or something?
I'm learning a lot, and appreciate all your help. I am sorry for the confusion with all the comments, but am not sure of the correct way to address issues in this forum. For example: should I go back and edit my original script to show the current version, or add it someplace else? I'm trying to keep the conversation flowing, so that it is easier for others to follow - Thanks rob
please let me give a last (hopefully) clear answer : (thanks for sharing the spreadsheet, this is far more easy to work on ;-)
here is your code fully working.
I have created some intermediate variables to show how it works.
function formSubmitEditors(e) {
// defines spreadsheet form events on submit of form. This function formSubmitEditors is triggered on formSubmit
var timeStamp = e.values[0];
var fileName = e.values[1];
var team = e.values[2].replace(/, /g,"|"); // remove unwanted spaces and commas replace by | for visibility ;-)
Logger.log(team);// contains | as separators
var teamArray = team.split('|');
Logger.log(teamArray.length+' : '+teamArray);// check that it is an array of x elements
//Makes copy of template document and renames
var tempID = '1Rq0pDAnuGNfL6W3GB0ZuLeWM2uYzHpKzoyxoXlwjtgE' // use document ID from Template Document
var copyId = DocsList
.getFileById(tempID)
.makeCopy(fileName + " - TestingCopy") // names new copy as student's name + text
.getId(); //
var file = DocsList.getFileById(copyId).addEditors(teamArray);
// replaces merged-text values within template with selected fields from formSubmitValues
var doc = DocumentApp.openById(copyId)
var body = doc.getActiveSection();
body.replaceText("%FILE%", fileName);// you wrote %FILENAME% in place of %FILE%
body.replaceText("%DATE%", timeStamp);
body.replaceText("%TEAM%", team);// it will be shown with | as separators, if you don't like it replace team by teamArray.toString() to get commas again.
}
EDIT : I removed the toString() for team event, not necessary since e.parameters are already strings.
EDIT2 : to be complete and do what you needed in the initial question you could replace the end of the code with this one that creates the Cal event on next week and sends invites with link to the doc.
var file = DocsList.getFileById(copyId).addEditors(editorsArray);
var fileurl = file.getUrl();
Logger.log(fileurl)
// replaces merged-text values within template with selected fields from formSubmitValues
var doc = DocumentApp.openById(copyId)
var body = doc.getActiveSection();
body.replaceText("%FILE%", fileName);
body.replaceText("%DATE%", timeStamp);
body.replaceText("%MAILS%", editors);
var Cal = CalendarApp.getCalendarsByName('testencodage')[0];// replace with your calendar name you want to use
var newEvent = Cal.createAllDayEvent('Fill the questionnary', new Date(new Date(newtimeStamp).getTime()+7*24*3600*1000), { guests : e.values[2] , sendInvites : true , description :"Don't forget to fill this document "+fileurl})
}
I'd suggest a couple of things
Add a few Logger.log statements in your code to print out debug information.
Add a try ... catch block around the entire section of code and print out the exception. See if you are getting any exception.
Last, use the Execution transcript window to see where your script stopped, if it did.
There are 2 ways to add an editor by email : addEditors([emailAddresses]) and addEditor(emailAddress)
The first has an "s" and needs an array of email adress strings, the second takes a single string as argument. You should use the second or add [brackets] to the email string in your code.
concerning you comment // need to figure out where/how to: .addEditors(email1,email2,etc);
// is this done from DocsList or DocumentApp class?
addEditor() and addEditors() belong to the file class, a member of DocsList class , you can add user(s) using user(s) objects or user(s) email(s) as explained in the doc.
It could be used like this DocFile.addEditors([email1,email2])
EDIT : A lot of comments on this post, sorry about that, it has become quite uneasy to read... I tested these addEditors feature with spreadsheet and it works as expected, using simple array for multiple user emails and string for single email. The document service seems to have a problem with the addEditor() method and it should be reported to the issue tracker.
REPORTED I've reported issue #1512 - Rocketrob