Using insertText to edit a google form response on google sheet - google-apps-script

I have a form that stores responses in a google sheet and what I'm trying to do is on form submit, I want to add or insert a text to a column to turn the response to a hyperlink. For example the response is 123456, I need to convert it to https://www.google.com/123456. I currently have this script but I'm getting an error on the insertText part.
var hyperlink = 'https://www.google.com/'
function onformsubmit(e){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 1');
var rg = sheet.getRange(1,3,sheet.getLastRow(),1);
var data = rg.getValues();
for(var i=0;i<data.length;i++){
var datstr=String(data[i][0]).insertText(0,hyperlink);
data[i][0]= (datstr);
}
rg.setValues(data);
}
Any suggestion will be much appreciated.

For the insert part I think what you want is this code in the for-loop:
for(var i=0; i < data.length; i++){
data[i][0] = hyperlink + data[i][0];
}
rg.setValues(data);
That will change all text in that column to include the modified hyperlink. If you want to just modify the new row whenever you submit a form response you'll need to access the values or range from the event argument (e), using e.range, e.values, e.namedValues or probably some combination. See the documentation here.

Related

Why does updating a form cause onFormSubmit trigger to run?

My code here:
function script1(){
//What is the form and data item ID?
var form = FormApp.openById("Form ID");
var namesList = form.getItemById("Item ID").asListItem();
//What sheet is used to update the form?
var ss = SpreadsheetApp.getActive();
var names = ss.getSheetByName("Update");
// Grab the values in the sixth column of the sheet - use 2 to skip header row
var namesValues = names.getRange(2, 6, names.getMaxRows() - 1).getValues();
var departmentNames = [];
// Convert the array ignoring empty cells
for(var i = 0; i < namesValues.length; i++)
if(namesValues[i][0] != "")
departmentNames[i] = namesValues[i][0];
// Populate the drop-down
namesList.setChoiceValues(departmentNames);
}
appears to triggers the form to submit causing problems. I have an onFormSubmit trigger set up to copy the data to a database and then delete the row. Unfortunately, the headers keep getting copied to the database since the form does not actually send any data and the only row with data is the headers. How can I update the form without the form submitting? Screenshot example is included below.
[
I hope I was able to make myself clear. Thank you for any help.
Modified Screenshot
Here is a screenshot of the trigger and its executions.

Create and update time in google form responses

Is there away to get google form (response) submit time and update time?
I have created google form and responses are being recorded in Google sheet. As soon as response is submitted it automatically captures time under first column that is "Timestamp". Now, if the response is updated ( for an example after three hours) then the time recorded initially (Timestamp) also gets updated. By the way i have created script which generates link to edit response in last column so that users can update their responses anytime. Is there any work around to get response submitted (created) time and update in different columns?
Any help is appreciated.
As suggested by Ruben,
I've created below script but it is not working
function assignEditUrls() {
var form = FormApp.openById('1UoHiwgl2Kw6RK5c7-
0kp1iFP0CPPR_LDbvSm1hw9xLg');
var sheet =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form
responses 1');
var data = sheet.getDataRange().getValues();
var urlCol = 16;
var responses = form.getResponses();
var timestamps = [], urls = [], resultUrls = [];
for (var i = 0; i < responses.length; i++) {
timestamps.push(responses[i].getTimestamp().setMilliseconds(0));
urls.push(responses[i].getEditResponseUrl());
}
for (var j = 1; j < data.length; j++) {
resultUrls.push([data[j][0]?urls[timestamps.indexOf(data[j]
[0].setMilliseconds(0))]:'']);
}
sheet.getRange(2, urlCol,
resultUrls.length).setValues(resultUrls);
{
var blankRow=sheet.getLastRow(); //identify the next blank row
// date function to update the current date and time as
submittted on
var value = sheet.getRange(blankRow, 19).setValue(new
Date()).setNumberFormat('dd-mm-yyyy h:mm:ss'); //Submitted On
sheet.getSheetValues(value);
}
}
It is updating time in the last column, but if I update the form response then again it gets updated. I want create date which should be entered in the initial entry. Please help me with the correction in my script.
There is no built-in way to do that.
One option is that you use your script that adds the URL to edit the form response to also add the timestamp to another column when a new form response is submitted and to another column when the form response is edited.
Related
How to check if current submission is editing response or a new response

How to check if current submission is editing response or a new response

I am working with google forms via app script. I want to determine if the current form that is being submitted is in edit mode or a new response? How can I check this in the onSubmit event.
If yes that user is edit a previously submitted response than I want to change the value in my spread sheet to "yes".
below is a snippet of my code:
function testExcel2() {
var email = "email";
var s = SpreadsheetApp.openById("id");
var sheet = s.getSheets()[0];
var headers = sheet.getRange(1,1,1,sheet.getLastColumn() - 1).getValues()[0];
var datarow = sheet.getRange(sheet.getLastRow(),1,1,sheet.getLastColumn() - 1).getValues()[0];
var message = "";
for(var i in headers)
{
message += "" + headers[i] + " : " + datarow[i] + "\n\n";
}
MailApp.sendEmail(email, "Submitted Data Test", message);
var af = FormApp.getActiveForm();
//af.setCustomClosedFormMessage("The form is currently processing a submission, please refresh the page.");
af.setConfirmationMessage('Thanks for responding!')
//af.setAcceptingResponses(false);
var rowKey = "o" + sheet.getLastRow();
var editCell = sheet.getRange(rowKey).setValue('no');
}
The Google Form form submit event doesn't have a field that could help to know if the response is a new response or if it's a response edit. As Sandy already said through question comments, the Form Servicer classes and methods, nor the response values include something that could help on this.
By the other hand, the Google Sheets submit event has a range field that could help. The following script bounded to a Google spreadsheet logs the response row:
function onFormSubmit(e){
var response = e.range;
Logger.log(response.getRow());
}
The above could be used to keep updated a column to hold a revision counter. If the corresponding cell is blank, then the response is a new response, other way it's a response edit.
The following script it to be bounded to the spreadsheet that receives the Form responses. It requires a on form submit installable trigger. Other instructions to adapt it are included on the script comments.
/*
*
* Global Variables
*
*/
/*
* Sheet name used as destination of the form responses
*/
var sheetName = 'Form Responses';
/*
* Name of the column to be used to hold the response revision counter
* It should match exactly the header of the related column,
* otherwise it will do nothing.
*/
var revisionsColumn = 'Rev';
/*
* Responses starting row
*/
var startRow = 2;
function setRevisionCounts(e){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues();
var revisionsIndex = headers[0].indexOf(revisionsColumn);
var data = sheet.getDataRange().getValues();
var response = e.range;
var rowIndex = response.getRow()-1;
var rev = data[rowIndex][revisionsIndex]+1;
sheet.getRange(rowIndex+1, revisionsIndex+1).setValue(rev);
}
This is not really an answer but rather a 'heads up'. I have found that if you resubmit (edit) a form that data that is not changed is resent unchanged.
Why does this matter? Let's say you have a branch in your form eg Do you like apples or bananas? If you like apples then the next question might be what is the colour of your car? Let's say 'red' of if you like bananas the next question might be how old are you? Let's say 35.
So you choose apples and red and submit the form.
Then you edit your reply and instead choose bananas and 35.
When the form is resubmitted the new data still says car=red and (as expected) age=35.
I would expect/hope that now car=null and age=35 but this is not the case. Car=red still appears against the updated row in the destination sheet.
I hope this is useful to you and maybe someone will suggest a work around.
You can compare the response length vs row length(or the number of columns in the row). Unless the submissions edits/changes every field/response then you know it should be less than the total number of questions.
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
const response = (e.range)
const responseValues = response.getValues()
const responseRow = Number(response.getRow())
const rowValues = sheet.getRange(responseRow, 1, 1, sheet.getLastColumn()).getValues()
if(responseValues.length < rowValues.length){
//edited submission
}else{
//likely new submission
}
Amateur here from Excel
ugly but works and this is a simple version - looks for notes - selects that row, updates values on second sheet and deletes the notes.
function mody() {
const sh = SpreadsheetApp.getActiveSpreadsheet();
const mn = sh.getSheetByName('Form Responses 1');
const puty = sh.getSheetByName('putter');
var lst = mn.getLastRow();
var dd = puty.getLastRow();
dd=dd+1
//replace row with edited form response if any
for (var z = 2;z< lst+1;z++){
var nts = mn.getRange(z,2,1,6).getNotes()
var ttt = ((nts.join()).length)
if (ttt>5){
mn.getRange(z,2,1,6).clearNote() //removes the notes on the modified
row
dd = z
lst = z
}
}
puty.getRange(dd,1,1,5).setValues(mn.getRange(lst,1,1,5).getValues());
}

Code not applying a timely sheet edit

I have code in a spreadsheet with a trigger to run it on form submit. The code is supposed to first create a link to allow for editing the submitted form data. It has worked fine in older sheets, but in my latest iteration, it is not saving the link before proceeding.
This is the beginning of the code which is the function listed in the trigger:
function sendRegEmails(e) {
var emailSubject = templateSheet.getRange("B3").getValue();
var emailHTMLTemplate = templateSheet.getRange("B4").getValue();
var emailWSAddInToHTMLTemplate = templateSheet.getRange("B9").getValue();
var emailWSReqFormLinkHTMLTemplate = templateSheet.getRange("B10").getValue();
//Create and save the URL to allow the respondent to edit their registration
assignEditUrls(REGISTRATION_FORM_ID, REGISTRATION_SHEETNAME, REGISTRATION_LINK_COL);
Utilities.sleep(5000);// pause in the loop for 5000 milliseconds or 5 seconds to make sure the URL is in the worksheet
// Create one JavaScript object per row of data.
var objects = getRowsData(mainsheet);
// For every row object, create a personalized email from a template and send
// it to the appropriate person.
for (var i = 0; i < objects.length; ++i) {...(continues)
This code is in a different .gs file in the same project:
/**-----------------------------------------------------------------------------------
|
| Begin section to create link to editable form
|
------------------------------------------------------------------------------------*/
function assignEditUrls(PassedForm_ID, SheetName, urlCol) {
var form = FormApp.openById(PassedForm_ID);
var sheet = SpreadsheetApp.openById(REGISTRATION_SHEET).getSheetByName(SheetName);
var data = sheet.getDataRange().getValues();
var responses = form.getResponses();
var timestamps = [], urls = [], resultUrls = [];
for (var i = 0; i < responses.length; i++) {
timestamps.push(responses[i].getTimestamp().setMilliseconds(0));
urls.push(responses[i].getEditResponseUrl());
}
for (var j = 1; j < data.length; j++) {
resultUrls.push([data[j][0]?urls[timestamps.indexOf(data[j][0].setMilliseconds(0))]:'']);
}
sheet.getRange(2, urlCol + 1, resultUrls.length).setValues(resultUrls);
}
When the email is sent the spreadsheet does not contain the URL. Has there been a change which would cause the assignEditURLs function to not save the URLs in the spreadsheet until after the other script is complete? Has something been added that I need to include in the code to get this to be added? I would like the email to go out within a couple minutes of the form submit.
As I said, this has worked in other spreadsheets. The only changes made to code has been to use the correct columns and files. The data ends up in the sheet, but not until after the email is sent.
REGISTRATION_FORM_ID = the ID of the Form file
REGISTRATION_SHEETNAME = the name of the sheet to receive the data
REGISTRATION_LINK_COL = the column number in REGISTRATION_SHEETNAME to place the data
REGISTRATION_SHEET = the ID of the Sheet file to receive the data
Regards,
Karl
On some scripts I maintain I've noticed with the transition to new sheets, the sheet ID changes. If you haven't already, try updating the REGISTRATION_SHEET variable with the new id.

How can I retrieve the hyperlink from a data cell in google apps script?

I am using SpreadsheetApp.getActiveRange().getValues(); to get the value of a range of cells, but it doesn't return the hyperlink associated with that cell, only the text. Is there any way to get the hyperlink or do I have to add another field with the url in it?
Thanks.
UPDATE: This is how I ended up using it to build a link list.
<ul>
<?
var range = SpreadsheetApp.getActiveRange();
var data = range.getValues();
var links = range.getFormulas();
for(var i=1; i < data.length; i++){
if(data[i][0] !== ''){
?>
<li><?= data[i][0]; ?></li>
<?
}
}
?>
</ul>
A hyperlink associated with a cell text is manifested by a formula. Google Spreadsheets does automagically converts any URL into a clickable hyperlink but in those cases formulas are not used and the text and the URL are the same.
Below is a very simple solution (no error checking) as to how you can get this through scripts. I suspect you imported this from Excel or something else and that's you don't readily see the HYPERLINK formula.
If you have a cell that looks like this -
Then this script will let you read the URL associated with it -
function getURL() {
var range = SpreadsheetApp.getActiveSheet().getActiveCell();
//logs - Google
Logger.log(range.getValue());
//logs - =HYPERLINK("http://www.google.com", "Google")
Logger.log(range.getFormulaR1C1());
//simple regex to get first quoted string
var url = /"(.*?)"/.exec(range.getFormulaR1C1())[1];
//logs - http://www.google.com
Logger.log(url);
}