Copy Row and Delete - google-apps-script

I have 2 sheets - 'Form Responses 1' and 'Students'.
When I run the function below, it copies all data from 'Form Responses 1' to 'Students' where I'll need to massage the data further in the second sheet. After I copied, I want that particular row to be deleted from 'Form Responses 1'. The next round when I run the function again (when there is new data in 'Form Responses 1'), it will append to 'Students' accordingly.
Would very much appreciate if you could advise how can I amend my codes below, thanks!
function Copy()
{
var sss = SpreadsheetApp.openById('sheet ID'); //replace with source ID
var ss = sss.getSheetByName('Form Responses 1'); //replace with source Sheet tab name
var range = ss.getRange('A:V'); //assign the range you want to copy
var data = range.getValues();
var numRows = range.getNumRows();
var getRow = range.getRow();
var tss = SpreadsheetApp.openById('sheet ID'); //replace with destination ID
var ts = tss.getSheetByName('Students');
ts.getRange(1, 1, data.length, data[0].length).setValues(data);
/*delete function is missing*/
}

The following bit of code should achieve the desire result, otherwise it is a good place to start. The code is pretty simple, so I put all the explanations in the comments of the code.
To use this code you can create a Stand alone script. (Does not need to be bound to a spreadsheet.) Copy Primary and Secondary code into two seperate tabs. (See the attached picture.) Once you have changed the IDs in the two scripts, run the primary script and you should see the desired result. (Be aware the all data in the form responses will be cleared.)
Hope this helps, and feel free to ask if you are not sure. Just note at this point I will be directing you to the documentation instead of trying to explain how certain methods/calls work:
Primary Code
function copy_Delete(){
var ss, sheet;
var lastRow, lastColumn;
var responseData;
//Get Spreadsheet and Sheet name for Form Responses Sheet
ss = SpreadsheetApp.openById("YOUR_ID_HERE");
sheet = ss.getSheetByName("Form Responses 1");
//Gets a numerical value representing the last row and last column where data is entered.
lastRow = sheet.getLastRow();
lastColumn = sheet.getLastColumn();
//Get all the data in the From Responses Sheet and put it all in an array.
responseData = sheet.getRange(2, 1, lastRow -1, lastColumn).getValues();
//Call the destination function and pass the array to it. Then clear form responses of all data.
destination(responseData);
sheet.clear();
}
Secondary Code
function destination(responseData){
var ss, sheet, form;
var numRows, numColumns, lastRow;
//Get Spreadsheet and Sheet name for your destination sheet
ss = SpreadsheetApp.openById("YOUR ID HERE");
sheet = ss.getSheetByName("Destination Sheet");
//Get the dimensions of the array and the last row of the spreadsheet.
numRows = responseData.length;
numColumns = responseData[0].length;
lastRow = sheet.getLastRow();
//Using the dimensions above,we push our array from the previous function into our new sheet.
sheet.getRange(lastRow +1, 1, numRows, numColumns).setValues(responseData);
//Get form and delete all responses.
form = FormApp.openById('YOUR_FORM_ID_HERE');
form.deleteAllResponses();
}
Attached example

Related

apps script - copying manually selected, non-adjacent rows and pasting them below each other

I want to copy manually selected/highlighted non-adjacent rows and paste them directly below each other on another sheet ("fight list raw"). With the script below it works fine, as long as the rows are adjacent. If the rows are non-adjacent, only one row is pasted (the row which was selected lastly / where the cursor is in).
Has someone an idea how to manage it?
function copynonadjacent rows() {
SpreadsheetApp.flush();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.getActiveSpreadsheet();
var source_sheet = ss.getActiveSheet();
var source_range = source_sheet.getActiveRange();
var target_sheet = target.getSheetByName("fight list raw");
var last_row = target_sheet.getLastRow();
target_sheet.insertRowsAfter(last_row,1);
source_range.copyTo(target_sheet.getRange("A"+(last_row+1+":AA"+(last_row+1))),{contentsOnly:true});
}
Thanks a lot!
From your following reply,
I want to copy row number 2 and row number 4. When I select the two rows by clicking on the row numbers and run the script, only row number 4 is copied.
But if I select rows 2 and 3 (so no rows between them), the script copies both rows. In the destination sheet the rows are pasted below each other without a row between them. I want this the same way, when I copy row 2 and 4.
In your script, you use var source_range = source_sheet.getActiveRange();. I thought that this might be the reason for your issue. In this case, how about the following modification?
Modified script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Source sheet.
var source_sheet = ss.getActiveSheet();
var source_ranges = source_sheet.getActiveRangeList().getRanges();
var values = source_ranges.flatMap(r => r.getValues());
var len = values.length;
// Target sheet.
var target_sheet = ss.getSheetByName("fight list raw");
var last_row = target_sheet.getLastRow();
target_sheet.insertRowsAfter(last_row, len);
target_sheet.getRange(last_row + 1, 1, len, values[0].length).setValues(values);
}
When this script is run, the selected rows are retrieved, and copy the values to the target sheet.
I thought that you use {contentsOnly:true}. So, I thought that getValues and setValues might be able to be used.
Reference:
getActiveRangeList()

Google sheets group script error when only 1 line

I have a script that copies the data from one sheet into another which acts as an archive. I have it so when it pastes the data into the archive sheet, it will group and collapse the data. However, when it is only 1 row I don't want it to group the data. This is causing an error:
"Exception. Invalid argument"
which is in reference to this line:
ts.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
I think a solution to this might be to incorporate an if array where if the range of data copied has 1 row do nothing, 2 rows will offset by 1 row then group then collapse, and 3 or more rows will run the same code I have below.
Here is the code that selects the data, groups, and then collapse it:
ts.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.UP).activate();
ts.getCurrentCell().offset(1, 0).activate(); //offset by 1 row for the header
var currentCell = ts.getCurrentCell();
ts.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
ts.getActiveRange().shiftRowGroupDepth(1).collapseGroups();
Full script:
function CopyRangeSoldTest() {
var sss = SpreadsheetApp.openById('1vT4R-_xPx3Z7bOYWgpOp2JCypL2yODxcJ'); //replace with source ID
var ss = sss.getSheetByName('Sold'); //replace with source Sheet tab name
var range = ss.getDataRange(); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('1srDDle9R81Qlh'); //replace with destination ID
var ts = tss.getSheetByName('Sold History'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+2,1,ss.getLastRow(),5).setValues(data)
ts.getRange(ts.getLastRow(),1,ts.getLastRow(),5).activate();
ts.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.UP).activate();
ts.getCurrentCell().offset(1, 0).activate();
var currentCell = ts.getCurrentCell();
ts.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
ts.getActiveRange().shiftRowGroupDepth(1).collapseGroups();//.shiftRowGroupDepth(1).collapseGroups();//you will need to define the size of the copied data see getRange()
var sss = SpreadsheetApp.openById('1vT4R-_xPx3Z7bOYWgpOp2JCypL2yODx'); //replace with source ID
var ss = sss.getSheetByName('Received'); //replace with source Sheet tab name
var range = ss.getDataRange(); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('1srDDle9R81Qlh'); //replace with destination ID
var ts = tss.getSheetByName('Received History'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+2,1,ss.getLastRow(),5).setValues(data)
ts.getRange(ts.getLastRow(),1,ts.getLastRow(),5).activate();
ts.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.UP).activate();
ts.getCurrentCell().offset(1, 0).activate();
var currentCell = ts.getCurrentCell();
ts.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
ts.getActiveRange().shiftRowGroupDepth(1).collapseGroups();//.shiftRowGroupDepth(1).collapseGroups();//you will need to define the size of the copied data see getRange()
}
Explanation:
I understand you recorded a Macro to generate this code. However, if you do some research on the official documentation you will be able to write your own code and achieve the same result in way less lines but also generalize it so it could work for multiple projects.
However, a direct solution to your problem might be the following:
You can get the values of the selection and check if the length of this array is larger than 1 or in other words, the selected data contains more than 1 rows:
var nrows = ts.getSelection().getActiveRange().getValues().length;
and then use an if condition to check whether the data contains more than 1 row: if(nrows>1).
Solution:
Try this:
ts.getCurrentCell().getNextDataCell(SpreadsheetApp.Direction.UP).activate();
ts.getCurrentCell().offset(1, 0).activate(); //offset by 1 row for the header
var currentCell = ts.getCurrentCell();
var nrows = ts.getSelection().getActiveRange().getValues().length;
if (nrows>1){
ts.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
ts.getActiveRange().shiftRowGroupDepth(1).collapseGroups();
}

Google Sheets - Sending email based on specific sheet in a spreadsheet

New to Google Scripts so I'm bumping my head on this entry level code. I want to send an email based on a specific sheet in a spreadsheet. The tab or sheet is named 'Test 2'. Currently this is my code.
/* Sends emails with data from the current spreadsheet.*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = getRange(startRow, 1, numRows, 2); // Fetch the range of cells A2:B6
var data = dataRange.getValues(); // Fetch values for each row in the Range.
for (var i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'THIS IS A TEST';
MailApp.sendEmail(emailAddress, subject, message);
}
}
And right now it's throwing this error.
ReferenceError: "getRange" is not defined. (line 8, file "Code")
How can I get it to run while referencing that sheet 'Test 2'?
Thanks!
You want to avoid the error of "getRange" is not defined..
You want to retrieve the values from the cell "A2:B6" of the sheet Test 2.
If my understanding is correct, how about the following modification?
From:
var dataRange = getRange(startRow, 1, numRows, 2);
To:
var dataRange = sheet.getSheetByName("Test 2").getRange("A2:B6");
Note:
In this case, at first, retrieve the sheet object of Test 2 and use the method of getRange for the sheet object.
I thought that a1Notation might be suitable for your situation.
Reference:
getSheetByName()
getRange(a1Notation)
If I misunderstood your question and this was not the direction you want, I apologize.

How to find a column value within an active row

How do I find the data in a column within an active row that is already defined in Google Apps Script?
I have an on edit function that sends an email when a column f is edited to a specific value. I need to find out the value in column b in order to include the value in the body of the message.
I have tried to use a range, but I am not understanding how i can define the second column for the active range that is already defined in the row variable. Here is what my code looks like. var called Values is the row of code I need help with. The row var is looking at the correct row. Any help is greatly appreciated.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var values = row.getcell()[0,2].getvalue().toString();
var recipients = "kel...#trafficbuilders.us";
var message = '';
if(cellvalue === '✔'){
message = 'All Items have been received for .';
var subject = 'All Items have been received for ' ;
var body = message + ' Visit ' + ss.getUrl() + ' to view the changes';
MailApp.sendEmail(recipients, subject, body);
}
}
To fetch a certain data/value from a certain cell, here's what you can do:
First identify the cell where data is located using getRange(). There are several ways to use getRange.
Sample from the docs:
// Get a range A1:D4 on sheet titled "Invoices"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("Sheet!A1:D4");
// Get cell A1 on the first sheet
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("A1");
To actually fetch the content/data, use getValues() or getValue()
sample snippets:
// The code below gets the values for the range C2:G8
// in the active spreadsheet. Note that this is a JavaScript array.
var values = SpreadsheetApp.getActiveSheet().getRange(2, 3, 6, 4).getValues();
Logger.log(values[0][0]);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Passing only two arguments returns a "range" with a single cell.
var range = sheet.getRange(1, 1);
var values = range.getValues();
Logger.log(values[0][0]);

Copy a range from last row to new sheet

I want to take the last response from a Google Form and copy it to the same range on another sheet.
The second sheet has some data in columns A & B (a login and password) that I want to assign as somebody completes the registration form.
I want the data from column B to H from the form response sheet to be copied to column C to I on the sheet that contains the login/password columns when a response is received.
I know I am missing the code to take the range from the last row, but I know NO coding at all and my current script is compiled from things I've found around the web and the reference material.
Any advice would be greatly appreciated.
function onEdit(e) {
var spreadsheet = SpreadsheetApp.openById("sheetid");
var sheet = spreadsheet.getSheets()[0];
var lastrow = sheet.getLastRow();
var range = sheet.getRange(2,2,1,7);
values = range.getValues();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var SSsheet = ss.getSheets()[1];
var ssRange = SSsheet.getRange(2,3,1,7);
ssRange.setValues(values);
}
Try using copyTo(destination). It copies the data from a range of cells to another range of cells. Both the values and formatting are copied.
// The code below will copy the first 5 columns over to the 6th column.
var sheet = SpreadsheetApp.getActiveSheet();
var rangeToCopy = sheet.getRange(1, 1, sheet.getMaxRows(), 5);
rangeToCopy.copyTo(sheet.getRange(1, 6));
}
You can also try using copyValuesToRangecopyValuesToRange.
For additional code samples, you may also refer to this forum.
function onEdit(e) {
var spreadsheet = SpreadsheetApp.openById("ID");
var sheet = spreadsheet.getSheets()[0];
var lastRow = sheet.getLastRow();
var range = sheet.getRange("A"+(lastRow)+":G"+(lastRow));
var values = range.getValues();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var SSsheet = ss.getSheets()[1];
var getRow = SSsheet.getLastRow() + 1;
var ssRange = SSsheet.getRange(getRow, 1, values.length, values[0].length);
ssRange.setValues(values);
Try with this,
this code copies the last value you want from a certain range and pastes it in the last available row of the other sheet.
The code it's the same only in the place where you are going to copy it, specify it to be the size of what I want to copy. I hope it helps you :D