This question is a continuation of the following: Google Apps Script: Sheets Forms Data Manipulation and Deleting Rows if Certain Cells are Blank
I have a sheet "Form Responses" where users can fill out the same question up to 5 times. The following code will organize these lines row by row in the 'Paste Values' sheet. In addition to this, I have tried to sort the columns by the Timestamp column in ascending order (so that new replies from the google form will show up at the top).
The first issue with this is that I have additional columns in my Paste Values sheet (A, O, P, Q, R, S) that are not in my Forms Sheet. When a new form goes to the top, the information in these columns do not move with the correct row they were supposed to be in; they just stay where they are.
The second issue with this is that if I try to add an On Form Submit trigger, so that the Paste Values sheet updates every time a new form gets submitted, the rows will accumulate from start to finish
So for example if I have:
Row1
Row2
Row3
And then a new form gets submitted, it becomes:
Row1
Row2
Row3
Row1
Row2
Row3
Row4
This leads to a duplication of rows which I don't want.
My end goal is to achieve the following:
1) every time someone submits a new form, the answers come to the top; everything is sorted in ascending order (by Timestamp column) in both 'Form Responses' and 'Paste Values'
2) Add an on edit trigger so that each time a user submits a form, only the new row(s) are added to 'Paste Values', rather than all of the rows duplicating over and over again
3) Columns: A, O, P, Q, R, S, and T are columns that I want to be able to edit freely in 'Paste Values', meaning that every time a new row is added to 'Paste Values', the corresponding information in these columns move with that row, and are not affected by an On Edit trigger.
Here is the google sheet example: https://docs.google.com/spreadsheets/d/1QUzPxxPB6CDL7Y5Dh92w6nsEM0QFUAaGG9LomjnGgLM/edit?usp=sharing
Form Responses sheet is the data received by the google form. Paste Values 'this is the goal' sheet is what I would like it to become
code for the row manipulation:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var src = ss.getSheetByName("Form Responses");
var dst = ss.getSheetByName("Paste Values");
var values = src.getDataRange().getValues();
var header = values.splice(0, 1)[0].splice(0, 13);
var res = values.reduce(function(ar, e) {
var h = e.splice(0, 3);
h.unshift("");
for (var i = 0; i < 5; i++) {
var temp = e.splice(0, 10);
if (temp.filter(String).length == 0) continue;
if (temp.length < 10) temp.splice(temp.length, 10 - temp.length, "");
ar.push(h.concat(temp));
}
return ar;
}, []);
if (dst.getRange("A1").getValue() != "Status") res.unshift(["Status"].concat(header));
dst.getRange(dst.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
}
And code for sorting each row in ascending order by the Timestamp column:
// Sort Timestamp column from newest to oldest:
function Sort_Timestamp(event){
var spreadsheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses");
var editedCell = spreadsheet1.getActiveRange().getColumnIndex();
var columnToSortBy = 1;
var tableRange = "A:AZ";
if(editedCell == columnToSortBy){
var range = spreadsheet1.getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: false } );
}
}
Updated attempt to achieve the Row Manipulation into Paste Values (and return each row (splitting them) from each row of Form Responses):
function so55716140_01(event) {
// setup this function as an installable trigger OnFormSubmit
// set up spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourcename = "Form Responses";
var targetname = "Paste Values";
var sourcesheet = ss.getSheetByName(sourcename);
var targetsheet = ss.getSheetByName(targetname);
// get the response data - assumes 10 questions plus timestamp
var sourcerow = event.range.getRow();
// Logger.log("DEBUG: Response row = "+sourcerow); //DEBUG
var sourcerange = sourcesheet.getRange(sourcerow, 1, 1, 12); // getRange(source row, column #, number of rows, number of columns); so 13 goes to column N in form resonses "do you want to submit another form"
var sourcerange2 = sourcesheet.getRange(sourcerow, 13, 1, 10); //want to start at column 13 (col M)
var sourcerange3 = sourcesheet.getRange(sourcerow, 23, 1, 10); // third round column W
var sourcerange4 = sourcesheet.getRange(sourcerow, 33, 1, 10); // fourth round
var sourcerange5 = sourcesheet.getRange(sourcerow, 43, 1, 9); // fifth round
//Logger.log("DEBUG: Source range = "+sourcerange.getA1Notation()); //DEBUG
var sourcedata = sourcerange.getValues();
var sourcedata2 = sourcerange2.getValues();
var sourcedata3 = sourcerange3.getValues();
var sourcedata4 = sourcerange4.getValues();
var sourcedata5 = sourcerange5.getValues();
// setup the target
var Bvals = targetsheet.getRange("B1:B").getValues();
var Blast = Bvals.filter(String).length;
//Logger.log("DEBUG: Blast = "+Blast); //DEBUG
var targetrange = targetsheet.getRange(Blast + 1, 2, 1, 12); //you're starting at the next row. so if there is data in column B3 row 2, you'll start at column B3 row 3
// starting at column 2 in Paste Values (timestamp), only on that one row, and paste in the next 12 values (started at column 2)
var targetrange2 = targetsheet.getRange(Blast + 2, 4, 1, 10); //trying blast + 2, and you're only pasting 10 values
//Logger.log("DEBUG: Target range = "+targetrange.getA1Notation()); //DEBUG
var targetrange3 = targetsheet.getRange(Blast + 3, 4, 1, 10);
var targetrange4 = targetsheet.getRange(Blast + 4, 4, 1, 10);
var targetrange5 = targetsheet.getRange(Blast + 5, 4, 1, 9);
// paste the response to the target
targetrange.setValues(sourcedata);
targetrange2.setValues(sourcedata2);
targetrange3.setValues(sourcedata3);
targetrange4.setValues(sourcedata4);
targetrange5.setValues(sourcedata5);
}
Tanaike's code is a work of art, but I think it is based on an assumption that you would only run the script once.
You've said that users will fill out a Google Form. You then manipulate this so that rows with identical columns will be transferred to one column. But ironically you then disassemble this to produce the results on "Paste Values".
I suggest a far less complicated process:
OnFormSubmit' trigger
. Use the object data returned by the trigger to copy the relevant data to the last row (plus 1) of "Paste Values". You might consider adjusting the form so that the name of the Submitter is selected from a dropdown - to ensure consistent spelling.FormSubmit
trigger.This enables you to write your notes and other comments on Paste Values, and these will remain aligned with the relevant row after the sort.
CODE
Code for a form potentially having 5 sections