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.
Related
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
Can somebody help me with my script. Its been quite sometime now and I still can't able to pull off what I want.
Script's Purpose: To transfer values from Form Responses (sheet) to Tracker (sheet) OnFormSubmit.
Then the entries from Form should be transferred on the last row/blank row every time. Then when the value is already transferred to Tracker it can be overwrite/updated if needed any time.
So whenever we have new entry from Form, the other value that's been altered should not be fixed with the transferred entries only.
Please see my initial script:
var lastrow = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1").getRange("A1").getDataRegion().getLastRow() //Gets last row from form responses
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1").getRange("C" + lastrow).getValue() // gets the value from column C and last row
var lastrowts = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tracker").getRange("A1").getDataRegion().getLastRow()
var ts = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tracker").getRange("C" + lastrowts).setValue(ss) // sets the value from ss
}
//function onFormSubmit(e) {
//var form = FormApp.openById("1FAIpQLScnJT1KEXiMvinZZ5LyIDG-l8FJcdeaGzU3MmTkshYNA4lcww")
//var formResponses = form.getResponses();
//for (var i = 0; i < formResponses.length; i++) {
//var formResponse = formResponses[i];
//var itemResponses = formResponse.getItemResponses();
//for (var j = 0; j < itemResponses.length; j++) {
//var itemResponse = itemResponses[j].getResponse();
//var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Tracker")
//Logger.log(itemResponse)
//ss.appendRow([itemResponse])
//}
//}
//}```
If you interested in the data from the linked spreadsheet then this should do the trick:
function onMyFormSubmit(e) {
const sh=e.source.getSheetByName('Tracker');
sh.appendRow(e.values);
}
There's often more information in an event object than is described in the documentation. And I usually check it with something like this:
e.source.getSheetByName('Sheet1').getRange('A1').setValue(JSON.Stringify(e));
Just stick that somewhere in your function in the beginning to remind yourself what parameters you have to play with. I usually usually just copy the header line in the response sheet and copy to the sheet I'm going to append to. You can do it in code if you prefer but I usually take the path of least resistance.
I have a trigger that places the Edit Response URL in the 100th column.
Not sure who i plagiarized this from, please feel free to cite yourself, lol
function assignEditUrls() {
var form = FormApp.openById('XXXXXXXXXXXXXX');
//enter form ID here
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Current');
//Change the sheet name as appropriate
var data = sheet.getDataRange().getValues();
var urlCol = 100; // column number where URL's should be populated; A = 1, B = 2 etc
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);
}
However, i need to expand it to run one of two different scripts, depending on if this is the initial response to a form or an edit of an existing response
//first run
if (check_if_edited(e)==false)
{
do_something();
}
//all other runs
else
{
do_something_else();
}
How do i do this?
[Edit]
I apologize: I want to do this per response, not for the first submission of the form. So the initial response runs one script, but if a user edits their response, i need to run a separate script
Answer:
Use the Properties Service to save a key-value pair after ther first run to check against in the future.
More Information:
As per the documentation:
This service allows scripts to store strings as key-value pairs scoped to one script, one user of a script, or one document in which an editor add-on is used.
So you can use it to create a variable which is bound to the script, on first run, and then change which code you want to execute based on if it exists or not. You can see it like a global-scope boolean which continues existing after the script finishes executing.
Code:
Editing your example:
function onFormSubmit() {
var sp = PropertiesService.getScriptProperties();
var user = e.response.getRespondentEmail());
//first run
if (!sp.getProperty(user)) {
do_something();
sp.setProperty(user, true);
}
//all other runs
else {
do_something_else();
}
}
Make sure to turn on the setting for collecting respondent email addresses from the ⚙️ > General > Collect email addresses checkbox in the Form UI.
You will also need to set this up as an installable trigger on form submit from the triggers page accessible from the View > Current project's triggers in the Apps Script UI.
References:
Class PropertiesService | Apps Script
Class Properties | Apps Script
Method .getProperty(key)
Method .setProperty(key, value)
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.
i'm writing a script that will take data from a spreadsheet and replace text keys on a document, adding one duplicated page to the document for each row of data on the spreadsheet.
the script was working properly when i created some test arrays with dummy data but it's not working when i try to pull the data from the spreadsheet.
function requestGen3() {
var templateDocID = ScriptProperties.getProperty("backRxRequestDocID");
// go back to variable below after testing
//var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sheet = sheets[3];
var activeSheetName = sheet.getName();
var range = sheet.getRange(2, 1, sheet.getMaxRows() - 1, sheet.getMaxColumns());
var user = Session.getUser().getEmail();
///////////////////////////////////////////////////////////////////////////////////
// the problem seems to be somewhere between here....
///////////////////////////////////////////////////////////////////////////////////
// For every row of employee data, generate an employee object.
var ptObjects = getRowsData(sheet, range);
// Get document template, copy it as a new temp doc, and save the Doc’s id
var docID = DocsList.getFileById(templateDocID).makeCopy().getId();
var doc = DocumentApp.openById(docID);
var body = doc.getActiveSection();
var pars = doc.getParagraphs();
for( var i in pars ) //loop to keep a copy of the original paragraphs
pars[i] = pars[i].copy();
// Create an array for every row object
for (var i = 0; i < ptObjects.length; ++i) {
// Get a row object
var rowData = ptObjects[i];
for (var i = 0; i < rowData.length; ++i) {
// Replace place holder keys,
body.replaceText('%PHYS_NAME%', rowData.physName[i]);
body.replaceText('%PHYS_ADDR1%', rowData.physAddr1[i]);
body.replaceText('%PHYS_ADDR2%', rowData.physAddr2[i]);
body.replaceText('%PHYS_CITY%', rowData.physCity[i]);
body.replaceText('%PHYS_STATE%', rowData.physState[i]);
body.replaceText('%PHYS_ZIP%', rowData.physZip[i]);
body.replaceText('%PHYS_PHONE%', rowData.physPhone[i]);
body.replaceText('%PT_NAME%', rowData.firstName[i]);
body.replaceText('%PT_DOB%', rowData.ptDOB[i]);
if( i != physName.length-1 ) { //has next?
doc.appendPageBreak();
for( var j in pars )
doc.appendParagraph(pars[j].copy());
}
}
}
///////////////////////////////////////////////////////////////////////////////////
// ...... and here
///////////////////////////////////////////////////////////////////////////////////
// Save and close the document
doc.saveAndClose();
}
the other functions referenced are from the "reading data from a spreadsheet" tutorial. when i debug the script it seems like the ptObjects and rowData variables contain the right information but it is not replacing the keys (which are formatted %KEY_NAME%) in the document properly. i'm fairly new to this so there may be some obvious mistakes.
any help would be very much appreciated
This looks like it could a simple problem assuming that the getRowsData function is the one described in the Reading Spreadsheet Data tutorial from the Apps Script Articles site.
That being the case, rowData.physName[i] should simply be rowData.physName.