Get created and modified date after editing response from google forms - javascript

function assignEditUrls() {
var form = FormApp.openById('Your form key goes here');
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Your responses Google Sheet name goes here - The tab name, not the file name');
var data = sheet.getDataRange().getValues();
var urlCol = Column number where URLs get entered goes here;
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);
}
I am currently using this code which allows me to update the record which is generating a edit link to edit that respective record. But the challenge is that it also changes the timestamp.
Question is
How can we amend this code so i can get created and last modified date and time for the particular record in the google sheet?
Any help much appreciated. Many thanks.

You can create an onFormSubmit Trigger to save the created date of your rows whenever a new record is added. By using this method, we can easily store the Created Date and the Modified Date (Timestamp) which you can use for other operations.
Example:
Here I updated the email of Test Data 1:
Before:
After:
Code:
function assignEditUrls() {
var form = FormApp.openById('Enter form id here');
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 1');
var data = sheet.getDataRange().getValues();
var urlCol = 9;
var responses = form.getResponses();
var urls = [];
for (var i = 0; i < responses.length; i++) {
urls.push([responses[i].getEditResponseUrl()]);
}
sheet.getRange(2, urlCol, urls.length).setValues(urls);
}
function triggerTest(e){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Form Responses 1');
var createdDateCol = 8;
var row = e.range.getRow();
sheet.getRange(1, createdDateCol, 1, 1).setValue("Created Date"); // Add created date header
var cdRange = sheet.getRange(row, createdDateCol, 1, 1);
if(cdRange.getValue() == ''){ // this indicates that the record is new
cdRange.setValue(e.namedValues['Timestamp'])
}
}
Reference:
Installable Triggers

Related

What is the most efficient way to import event details from Google Calendar to Google Sheets? (Google Apps Script) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 months ago.
Improve this question
I am working on a script to save Google Calendar events to a Google Sheets file. There were many other posts on the subject, but I needed a single row per event with the guest list split into multiple columns based on criteria and I was unable to find any scripts with this output format. I've built a similar function in a low-code app builder (Appsheet) but I am very new to Javascript.
I've tested the script below and it works well, but I wanted to ask if this was the most efficient way to arrange the for loops to get the information that I need.
function getEventsFromRangeGeneric() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("EventsRange");
var employees = ['test1#email.com','test2#email.com','test3#email.com'];
//Get date range from cells
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
//Get calendar ID and events
var id_cal = 'workcalendartest#group.calendar.google.com';
var cal = CalendarApp.getCalendarById(id_cal);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
//Create headers and set to fifth row
var header = [["Title","Name","Employee","Client","Start","End","Duration","Location"]]
var range = sheet.getRange(5,1,1,8).setValues(header);
//Loop through each event to get details
var row = 6;
for (var i = 0;i<events.length;i++){
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var duration = '';
var loc = events[i].getLocation();
var guestList = events[i].getGuestList();
var guestEmails = [];
var employEmail = [];
var clientEmail = [];
var clientName = '';
//Loop through each guest object to get list of emails
for (var j = 0;j<guestList.length;j++){
guestEmails.push(guestList[j].getEmail());
}
//Loop through each list of emails to determine which is employee and which is client
for (var g = 0;g<guestEmails.length;g++) {
if (employees.includes(guestEmails[g]) === true) {
employEmail.push(guestEmails[g])
} else {
clientEmail.push(guestEmails[g])
}
}
//Use details to fill in corresponding columns
var details = [[title,clientName,employEmail, clientEmail, start_time, end_time, duration, loc]];
var range2 = sheet.getRange(row+i,1,1,8);
range2.setValues(details);
var cell2=sheet.getRange(row+i,7); // go to column 7 (the placeholder) of the output data for duration column
// Calculate the number of hours of the session
cell2.setFormula('=(F' +row+ '-E' +row+ ')');
cell2.setNumberFormat('hh:mm:ss')
}
row=row+i
}
Modification points:
In your script, setValues and setFormula are used in a loop. In this case, the process cost will become high. Ref (Author: me)
In this case, I think that setValues can be used outside of the loop. By this, the process cost can be reduced a little.
The unused variable is included.
for (var j = 0; j < guestList.length; j++) {} and for (var g = 0; g < guestEmails.length; g++) {} can be written by one loop.
I think that var start_time = sheet.getRange("A2").getValue(); and var end_time = sheet.getRange("B2").getValue(); can be written by one request.
In your script, employEmail and clientEmail are an array. In this case, when the value of var details = [[title,clientName,employEmail, clientEmail, start_time, end_time, duration, loc]]; is put to the sheet, the 1st element is used. Please be careful about this.
row=row+i is put outside of the loop. By this, row is always the initial value of var row = 6;.
When these points are reflected in your script, how about the following modification?
Modified script:
function getEventsFromRangeGeneric() {
var employees = ['test1#email.com','test2#email.com','test3#email.com'];
var id_cal = 'workcalendartest#group.calendar.google.com';
var header = ["Title", "Name", "Employee", "Client", "Start", "End", "Duration", "Location"];
var row = 6;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("EventsRange");
var [start_time, end_time] = sheet.getRange("A2:B2").getValues()[0];
var cal = CalendarApp.getCalendarById(id_cal);
var events = cal.getEvents(new Date(start_time), new Date(end_time));
var values = [header];
for (var i = 0; i < events.length; i++) {
var title = events[i].getTitle();
var start_time = events[i].getStartTime();
var end_time = events[i].getEndTime();
var loc = events[i].getLocation();
var guestList = events[i].getGuestList();
var employEmail = [];
var clientEmail = [];
var clientName = '';
for (var j = 0; j < guestList.length; j++) {
var email = guestList[j].getEmail();
if (employees.includes(email) === true) {
employEmail.push(email);
} else {
clientEmail.push(email);
}
}
values.push([title, clientName, employEmail.join(","), clientEmail.join(","), start_time, end_time, `=F${i + row}-E${i + row}`, loc]);
}
sheet.getRange(row - 1, 1, values.length, values[0].length).setValues(values);
}
References:
Best Practices
Benchmark: Reading and Writing Spreadsheet using Google Apps Script (Author: me)

Search and return data using getRange() and getValue

I am trying to create a sheet (using Google Sheets) for our volunteers to search for, update, and/or add mentoring information (javascript).
I started with the option to search (function onSearch) and it appears to work but the information does not appear in the sheet (attached FYI). I'd appreciate help in making this run.
date entry sheet
REVISED:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form1");
var str = formSS.getRange("D3").getValues()[3]; //Search for info entered in Form1$D3
var datasheet = ss.getSheetByName("TRACKING");
var values = datasheet.getRange(2,1,2); //Datasheet where info will be retrieved
if (values == str) {
var values1 = values.getValues(); //// get the tracking data if it matchs search request
var i = 1;
myFunction().onSearch = i < values.length; i++;
{
var output = datasheet.getRange(); ///retrieve information from the Tracking spreadsheet and
//populate the information in the appropiate cells.
formSS.get("E8").datasheet.getValue(1),
formSS.getRange("E10").getdatasheet.getValue(2),
formSS.getRange("E12").datasheet.getValue(3),
formSS.getRange("E14").datasheet.getValue(4),
formSS.getRange("J8").datasheet.getValue(5),
formSS.getRange("J10").datasheet.getValue(6),
formSS.getRange("J12").datasheet.getValue(7),
formSS.getRange("J14").datasheet.getValue(8);
return }}}
function onSearch() {
var SEARCH_COL_IDX=0;
var RETURN_COL_IDX=0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Form1");
`` var datasheet = ss.getSheetByName("TRACKING");
var str = formSS.getRange("D3").getValues()[3]; //column Index
var values = ss.getSheetByName("Form1").getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
RETURN_COL_IDX = i+1;
var values = [[formSS.getRange("E8").datasheet.getValue(1),
formSS.getRange("E10").getdatasheet.getValue(2),
formSS.getRange("E12").datasheet.setValue(3),
formSS.getRange("E14").datasheet.getValue(4),
formSS.getRange("J8").datasheet.getValue(5),
formSS.getRange("J10").datasheet.getValue(6),
formSS.getRange("J12").datasheet.getValue(7),
formSS.getRange("J14").datasheet.getValue(8)]];
}
}
}
Thanks for responding. No one had the answer, and I even read that what I was asking is not available in Google Sheets. I decided to use the filter function for each cell instead.
B3 is the search field TRACKING!C:C is the sheet to retrieve the
information Tracking!E:E is the matched column to return information.
I am new here and at programming but I hope this helps someone.
=IFERROR(FILTER(TRACKING!C:C,TRACKING!E:E=B3),TRUE)

Copy Selected Columns in One Sheet and Add Them To Selected Columns in Another Sheet

I would like to create a simple google apps script to copy specific column into another sheets.
Previously I tried using getLastRow but I get stuck to modify it.
var destinationSheetLastRow = destinationSheet.getDataRange().getLastRow();
Here is my spreadsheet: https://docs.google.com/spreadsheets/d/1rGvmlKCmbjDSCLCC2Kujft5e4ngbSLzJd2NYu0sxISs/edit?usp=sharing
And here is the modified script so far:
function pasteMultiCol(sourceSheet, destinationSheet,sourceColumns,destinationColumns, doneColumn){
var sourceDataRange = sourceSheet.getDataRange();
var sourceDataValues = sourceDataRange.getValues();
var sourcesheetFirstRow = 0;
var sourceSheetLastRow = sourceDataRange.getLastRow();
var destinationSheetLastRow = destinationSheet.getDataRange().getLastRow();
var pendingCount = 0;
//Find the row start for copying
for(i = 0; i < sourceDataValues.length; i++){
if(sourceDataValues[i][doneColumn-1] === "Copied"){
sourcesheetFirstRow++;
};
if(sourceDataValues[i][doneColumn-1] === ""){
pendingCount++;
};
};
//Update Source sheet first row to take into account the header
var header = sourceSheetLastRow-(sourcesheetFirstRow + pendingCount);
sourcesheetFirstRow = sourcesheetFirstRow+header;
// if the first row equals the last row then there is no data to paste.
if(sourcesheetFirstRow === sourceSheetLastRow){return};
var sourceSheetRowLength = sourceSheetLastRow - sourcesheetFirstRow;
//Iterate through each column
for(i = 0; i < destinationColumns.length; i++){
var destinationRange = destinationSheet.getRange(destinationSheetLastRow+1,
destinationColumns[i],
sourceSheetRowLength,
1);
var sourceValues = sourceDataValues.slice(sourcesheetFirstRow-1,sourceSheetLastRow);
var columnValues =[]
for(j = header; j < sourceValues.length; j++){
columnValues.push([sourceValues[j][sourceColumns[i]-1]]);
};
destinationRange.setValues(columnValues);
};
//Change Source Sheet to Copied.
var copiedArray =[];
for(i=0; i<sourceSheetRowLength; i++){copiedArray.push(["Copied"])};
var copiedRange = sourceSheet.getRange(sourcesheetFirstRow+1,doneColumn,sourceSheetRowLength,1)
copiedRange.setValues(copiedArray);
};
function runsies(){
var ss = SpreadsheetApp.openById("1snMyf8YZZ0cGlbMIvZY-fAXrI_dJpPbl7rKcYCkPDpk");
var source = ss.getSheetByName("Source");
var destination = ss.getSheetByName("Destination");
var sourceCols = [4,5,6,7,8,9,10];
var destinationCols = [7,8,9,10,11,12,13];
var doneCol = 12
//Run our copy and append function
pasteMultiCol(source,destination, sourceCols, destinationCols, doneCol);
};
Your code is taken from my tutorial in my blog article Copy Selected Columns in One Sheet and Add Them To The Bottom of Different Selected Columns in Another Sheet and it just needs a tweak.
I think the issue might be that you have a bunch of formulas in other columns in your "Destination" Sheet tab. So getting the last row of the sheet will result in getting the last row considering all the data including your other formulas.
You might find this explanation in a follow up blog article I wrote helpful: Google Apps Script: Get the last row of a data range when other columns have content like hidden formulas and check boxes
In short, you can change the destinationSheetLastRow variable to something simple like this.
var destinationSheetLastRow = (()=>{
let destinationSheetFirstRow = 7; // The first row of data after your header.
//Get a sample range to find the last value in the paste columns.
let sampleRange = destinationSheet.getRange(destinationSheetFirstRow,
destinationColumns[0],
destinationSheet.getLastRow())
.getValues();
let sampleLastRow = 0;
while(sampleLastRow < sampleRange.length){
if (sampleRange[sampleLastRow][0] == ""){
break;
}
sampleLastRow++;
};
return sampleLastRow;
})()

How should I add the rows (without the headers) after the last row with data (without overwriting anything in the "Master_db")

The code below is overwriting on the existing data.
#OMila helped me with the original code, I could not articulate exactly what I needed hence starting a new question.
function Dom() {
var origin_sheet = SpreadsheetApp.getActive().getSheetByName('Dom_Sum');
var firstRow = 1;
var firstCol = 1;
var numRows = origin_sheet.getLastRow();
var numCols = 22;
var origin_values = origin_sheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
var dest_values = [];
for(var i = 0; i < origin_values.length; i++) {
if(origin_values[i][0] != '') {
dest_values.push(origin_values[i]);
}
}
var dest_id = "1ZGq7L7bvF1INuDgZxhHnVsihkYkYubmncSAE5uC-Pq4";
var dest_sheet = SpreadsheetApp.openById(dest_id).getSheetByName("Master_Db");
var numRowsDest = dest_values.length;
var dest_range = dest_sheet.getRange(1, 1, numRowsDest, 22);
dest_range.setValues(dest_values);
}
I would like to add the data created in the "Dom_Sum" worksheet below the last row of data in the other workbook with the worksheet name "Master_Db"
#OMila I'm really grateful to you, and if you like we could offer you a consultation fee for future projects. (boseav#gmail.com)
Instead of writing your value into the range dest_sheet.getRange(1, 1, numRowsDest, numCols)
retrieve the last row of your destination sheet and write starting with the next row
var destLastRow=dest_sheet.getLastRow();
var dest_range = dest_sheet.getRange(destLastRow+1, 1, numRowsDest, numCols);
dest_range.setValues(dest_values);

Google Form Drop Down and Sections with Loop

So I have this project I am working on where I need to create a Google Form based on names in a Google Sheet. The way it basically needs to flow is for every name in the sheet should be an option as a drop down in section one and then have a section created for each name. When the person selects their name in the first section they should then be sent to the section titled their name. For example, Name 1 should go to the section titled Name 1, Name 2 to Name 2, etc. The code below will create a Google Form and create sections with the names. The issue that arouses is it will not add the names to a drop down list (it will create a drop down list with no options) and will also not set a destination based on the answers. Any thoughts?
function RecommendationForm(){
var form = FormApp.create('FANS Recommendation Form');
form.setTitle('FANS Recommendation Form')
.setConfirmationMessage('Thanks for responding!')//SET CONFIRMATION MESSAGE LATER
.setAllowResponseEdits(false)
.setAcceptingResponses(true);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Teacher and Email List');
var startRow = 2;
var numRows = 200;
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
var data = dataRange.getValues();
var whoAreYou = form.addListItem();
whoAreYou.setTitle('Who are you?')
var nameBreak = []
var nameChoice = []
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[0];
var recNumber = row[2]
if (name != ""){
if (recNumber != 0){
nameBreak[i] = form.addPageBreakItem().setTitle(name);
nameChoice[i] = name
}}};
whoAreYou.setChoices([
whoAreYou.createChoice(nameChoice,nameBreak)
])
}
You got the syntax of the setChoices function wrong. You need to create an array of choices like so:
var choices = []
choices[i] = whoAreYou.createChoice(name,form.addPageBreakItem().setTitle(name))
Then you can use this array in setChoices method to set all your choices.
whoAreYou.setChoices(choices)
for more details have a look here
Below is the modified code that incorporates these changes,
function RecommendationForm(){
var form = FormApp.create('FANS Recommendation Form');
//var form = FormApp.openByUrl("https://docs.google.com/forms/d/11oaebH_BeFLAkpGjqs5EykqtNxXXaabuVCTk3uuc12s/edit")
form.setTitle('FANS Recommendation Form')
.setConfirmationMessage('Thanks for responding!')//SET CONFIRMATION MESSAGE LATER
.setAllowResponseEdits(false)
.setAcceptingResponses(true);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet9');
var startRow = 2;
var numRows = 10;
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
var data = dataRange.getValues();
var whoAreYou = form.addListItem();
whoAreYou.setTitle('Who are you?')
var nameBreak
var nameChoice
var choices = []
var choiceCounter = 0
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[0];
var recNumber = row[2]
if (name != ""){
if (recNumber != 0){
nameBreak = form.addPageBreakItem().setTitle(name);
nameChoice = name
choices[choiceCounter] = whoAreYou.createChoice(nameChoice,nameBreak) // Create a array of choices with the navigation item
choiceCounter++; // This counter will be independent of i counter and will be have no breaks.
}}
};
whoAreYou.setChoices(choices) //Set Choices with the choice array.
Logger.log(form.getEditUrl())
Logger.log(form.getPublishedUrl())
}
Hope this helps!

Categories

Resources