Copying and Paste multiple rows into next empty Row on another sheet - google-apps-script

I have the following script:
function onEdit(event) {
// assumes source data in sheet named Needed
// target sheet of move to named Acquired
// test column with yes/no is col 5 or E
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "IN" && r.getColumn() == 7 && r.getValue() == "Y") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("ORDERS");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
}
This is the original post where i found the script:
https://support.google.com/docs/forum/AAAABuH1jm0hR40qh02UWE/?hl=en&gpf=%23!topic%2Fdocs%2FhR40qh02UWE
I want to make a few small adjustments to the code, but don't know where to start.
Presently, it copies the whole row when a "Y" is entered into column G and places the row contents on lastrow of ORDERS!.
What i want it to do is:
1) only copy columns B,C and E on lastrow of ORDERS!
2) delete values in E and F on IN! after code has run for that specific row (don't want it deleting rows that I haven't put a "Y" against)
3) Is there a way to have a button instead, that when the button is clicked it copies all the rows with "Y" at once?
Here's a link to my sheet if you want to have a play:
https://docs.google.com/spreadsheets/d/1Peo5_5QmkxVyL7j5bmgtMs9BL16cvsGhhOSuRV_TsAo/edit?usp=sharing
Best regards
manc

I believe your goal as follows.
When the column "G" is Y, you want to copy the values of the columns "B", "C" and "E" to the last row of the sheet ORDERS.
You want to copy all rows that the column "G" is Y when the script is run.
You want to delete the content of columns "E" and "F" of the copied rows in the sheet of IN, when the script is run.
You want to run the script by clicking a button on the sheet.
For this, how about this answer?
Modification points:
In your script,
When the script is run by clicking a button on the sheet, the event object cannot be used.
Your script copies one row of the active range.
The columns "E" and "F" of the copied rows are not deleted.
It is required to modify above modification points. When above points are reflected to the script, it becomes as follows.
Modified script:
Please copy and paste the following script to the script editor. And please prepare a button which is drawing and/or image, and assign the function run to the button. By this, when the button is clicked, the script is run. And the columns "B", "C" and "E" of all rows that the column "G" is Y are copied from the sheet "IN" to the last row of the sheet "ORDERS".
function run() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = ss.getSheetByName("IN");
var dstSheet = ss.getSheetByName("ORDERS");
// 1. Retrieve the values from "A2:G" of sheet "IN".
var srcValues = srcSheet.getRange("A2:G" + srcSheet.getLastRow()).getValues();
// 2. Create an object for putting values and deleting the contents of the columns "E" and "F".
var obj = srcValues.reduce((o, [,b,c,,e,,g], i) => {
if (g == "Y") {
o.values.push([b, c, e]);
o.ranges.push(`E${i + 2}:F${i + 2}`);
}
return o;
}, {values: [], ranges: []});
// 3. Copy the values to the sheet "ORDERS".
dstSheet.getRange(dstSheet.getLastRow() + 1, 1, obj.values.length, obj.values[0].length).setValues(obj.values);
// 4. Delete the contents of the columns "E" and "F" of sheet "IN".
srcSheet.getRangeList(obj.ranges).clearContent();
}
Note:
About the button for running the Google Apps Script, I think that this site is useful. Ref In your case, please create a button on the sheet "IN" and assign the function run to the button. By this, when the button is clicked, the script works.
Please use this script with V8.
References:
setValues(values)
clearContent()
reduce()

Related

Moving one row to bottom of a sheet after date has passed

I am looking for a macro that can help move a row of a sheet to the bottom of it once it passes a certain date. Basically this will be used for a meeting tracker and I'm trying to find a way to automatically move meetings to a "Completed" section once the date (located on Column F) passes.
I've created macros before to move things between sheets, but I'm unfamiliar with how to move things on the same sheet. Would anyone be able to help?
Here's the sheet: https://docs.google.com/spreadsheets/d/1EPueop9bdky_J8VgpFdSUzzsMRieRUreeCRIy18ScTY/edit#gid=0
I would like to move rows based on the date in Column F. Once it passes I would like it to move to the "Completed" section of the sheet. This is an active spreadsheet so the row "Completed" it's on could change as meetings are being added.
function moveActiveRowToBottom() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getActiveSheet();
const r = sh.getActiveRange().getRow();
const vs = sh.getRange(r,1,1,sh.getLastColumn()).getValues();
sh.getRange(sh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
sh.deleteRow(r);
}
I believe your goal is as follows.
You want to check the date of column "F" of the sheet. When the date of column "F" is smaller than today, you want to move the row to the last row.
You want to achieve this in the same sheet in a Google Spreadsheet. And, the sheet has a row of "Completed" in column "A", you want to check the date of the above rows of the "Completed" row.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. When you use this script, please run the function of myFunction().
function myFunction() {
const sheet = SpreadsheetApp.getActiveSheet(); // or const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet 1");
const row = sheet.getRange("A4:A" + sheet.getLastRow()).createTextFinder("Completed").findNext().getRow();
const now = new Date().getTime();
const moves = sheet.getRange("F4:F" + (row - 1)).getValues().reduce((ar, [f], i) => {
if (f && f.getTime() < now) {
const r = i + 4;
ar.push(sheet.getRange(`A${r}:F${r}`));
}
return ar;
}, []).reverse();
const len = moves.length;
if (len == 0) return;
const lastRow = sheet.getLastRow();
moves.forEach((r, i) => sheet.moveRows(r, lastRow - i + len - 1));
}
When this script is run, the column "F" of the rows from 4 to the "Completed" row is checked. And, when there are moving rows, the rows are moved to the last row of the sheet.
Note:
This sample script was tested using your provided Spreadsheet. When you change the Spreadsheet and/or your actual Spreadsheet is different from your provided Spreadsheet, this script might not be able to be used. Please be careful about this.
When I saw your sample Spreadsheet, it seems that the sheet name is Sheet 1. If you want to use the sheet using the sheet name, please be careful about this.
References:
reduce()
forEach()
moveRows(rowSpec, destinationIndex)

Copy & Delete Function on Sheets w/ Apps Script

After someone submits a Google Form response, their responses go to the DropRequests sheet (although the form is not currently linked for reasons).
What we want to do is after someone submits their form, and their responses go to the DropRequests sheet, that if the value in column C matches that of column F in the StudentMatches sheet, it is moved to the OldMatches sheet. We have started on the code below but it does not yet work. Any ideas on how to make this functional and fix the issue with the range in the last line?
function moveMatch(){
var oldmatches = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("OldMatches");
var droprequest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("DropRequests");
var currentmatches = SpreadsheetApp.openById('1dd9UhD2LpshCFVYizpf3OwI1XzPrq3AfqhMAO1iJ6Ns')
value1 = currentmatches.getRange("F:F").getDisplayValues();
value2 = droprequest.getRange("C:C").getDisplayValues();
for(var i in value1)
if(value2[0,i]=value1){
currentmatches.getDataRange.getRow(0,i).moveTo(oldmatches.getLastRow())
}
}
Thank you again.
I believe your goal is as follows.
There are 3 sheets DropRequests, StudentMatches, OldMatches in your Spreadsheet.
You want to retrieve the values of column "C" from DropRequests sheet, and want to compare these values with the values of column "F" of StudentMatches sheets.
When the values are matched, you want to move the row from the StudentMatches sheet to the 1st empty row of OldMatches sheet.
When moveTo is used, the moved row becomes the empty row. In your goal, you want this situation.
In this case, how about the following sample script?
Sample script:
function moveMatch() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet1 = ss.getSheetByName("DropRequests");
var srcSheet2 = ss.getSheetByName("StudentMatches");
var dstSheet = ss.getSheetByName("OldMatches");
var srcValues1 = srcSheet1.getRange("C2:C" + srcSheet1.getLastRow()).getValues().map(([c]) => c);
var [,...srcValues2] = srcSheet2.getDataRange().getValues();
var values = srcValues2.flatMap((r, i) => srcValues1.includes(r[5]) ? i + 2 : []);
if (values.length == 0) return;
var lastCol = srcSheet2.getLastColumn();
var lastRow = dstSheet.getLastRow();
values.forEach((r, i) => srcSheet2.getRange(r, 1, 1, lastCol).moveTo(dstSheet.getRange(lastRow + 1 + i, 1)));
}
In this modification, the values are retrieved from the column "C" of "DropRequests" and "StudentMatches". And, the values of the column "C" of "DropRequests" are compared with the column "F" of "StudentMatches" sheet. When the values are matched, the row is moved from "StudentMatches" to "OldMatches".
Note:
First, please check the sheet names, again.
This sample script is for your question. So, when the Spreadsheet is changed, this script might not be able to be used. Please be careful this.
References:
forEach()
moveTo(target)

How can i make several "drop down menu triggers" in one script in google scripts?

I have a google sheets with TWO sheets inside.
first page - collecting data from a form. second page - pulling specific data from page one. same specific cells from the Rows selected & adds the information on new rows in Sheet2.
in page one, on the first cell of each row i have a dropdown menu that suppose to trigger that Sendd script - that sends that data to the second sheet.
I figured out how to activate each of the dropdown menus as a trigger to activate the script. but i need to write a separate script for each one of the drop down menus separately.
Is it possible to make all of the drop down menus on Column A as a Triggers with one script?
Here's the script:
function onEdit(e) { //////menu trigers function
if (e.range.getA1Notation() == 'A9') { //////Menu cell
if (/^\w+$/.test(e.value)) {
var sheet = SpreadsheetApp.getActive().getSheetByName('ORDERS'); /////// those 2 lines make the cell
var cellname = sheet.getRange(9,1); /////// go back to "Quick Access"
eval(e.value)();
e.range.clear();
cellname.setValue('');
}
}
}
function SendClear() {
Sendd();
clear1();
}
function Sendd() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("ORDERS"); //Data entry Sheet
var datasheet = ss.getSheetByName("TakeAway"); //Data Sheet
//Input Values
var values = [[formSS.getRange("C9").getValue(),
formSS.getRange("J9").getValue(),
formSS.getRange("E9").getValue()]];
datasheet.getRange(datasheet.getLastRow()+1, 3, 1, 3).setValues(values); //inputs the data from "INPUT" into "DATA". (+1 = adds new line. 1 = offset starting cell
}
Thanks in advance
From It doesn't matter for me if it will a check box or a drop down menu. the main issue is that i need to write for each one of them an individual 'Send' Script. and what i would want to, if it's possible, is that that script will be able for the range of A9:A., how about the following sample script?
Sample script:
In this sample script, the checkbox is used for running the script. So please insert the checkboxes to the cells "A9:A". By this, when the checkbox is checked, the script works and when the script is finished, the checkbox is unchecked.
function onEdit(o) {
var range = o.range;
var sheet = range.getSheet();
if (sheet.getSheetName() != "ORDERS" || range.columnStart != 1 || range.rowStart < 9 || !range.isChecked()) return;
var [c,,e,,,,,j] = sheet.getRange(range.rowStart, 3, 1, 8).getValues()[0];
o.source.getSheetByName("TakeAway").appendRow([c, j, e]);
sheet.getRangeList([`C${range.rowStart}`, `E${range.rowStart}`, `J${range.rowStart}`]).clearContent(); // When you want to clear the cells of "C", "E", "J", after the values were copied, please use this line.
range.uncheck();
}
When the checkbox of "A9:A" is checked, the script is copied from the columns "C", "J", "E" in order (this is from your script.) to the destination sheet. The value is appended to the destination sheet.
Note:
In this sample script, the source sheet name and the destination sheet name are ORDERS and TakeAway. This is from your script. So when you change these sheet names, please modify the above script.
This script used the event object by running with OnEdit trigger. So when you directly run this script with the script editor, an error occurs. Please be careful this.
About some unclear points, I guessed as follows.
I couldn't understand the function clear1() in your script. So I guessed that you wanted to clear the cells of columns "C", "E" and "J", after the values were copied. So I added a script of sheet.getRangeList([C${range.rowStart}, E${range.rowStart}, J${range.rowStart}]).clearContent();. If my guess was not correct, please remove this.
Reference:
Event Objects
Thanks to Tanaike!
This is the Answer:
function onEdit(o) {
var range = o.range;
var sheet = range.getSheet();
if (sheet.getSheetName() != "ORDERS" || range.columnStart != 1 || range.rowStart < 9 || !range.isChecked()) return;
var [c,,e,,,,,j] = sheet.getRange(range.rowStart, 3, 1, 8).getValues()[0];
o.source.getSheetByName("TakeAway").appendRow([null,null,c, j, e]); sheet.getRangeList([`C${range.rowStart}`, `E${range.rowStart}`, `J${range.rowStart}`]).clearContent(); // When you want to clear the cells of "C", "E", "J", after the values were copied, please use this line.
range.uncheck();
}
to make a cell offset to th input information i changed this line:
o.source.getSheetByName("TakeAway").appendRow([c, j, e]);
to this:
o.source.getSheetByName("TakeAway").appendRow([null,null,c, j, e]);
Thank you Tanaike!

Google Apps Scripts - Sheets - Moving variable number of rows from one tab to another

To begin I know very little about writing code. I would like to move rows from one tab to another in a google sheets.
At the moment I am using the below script to move a single row when an action is done. When column 17 is marked "Completed" in the 'Work' tab, it copies the entire row, creates a row in the 'completed' tab, pastes the copied row into that new row, and then deletes the copied row. The information inputted into 'Work' is a query array from another tab, 'data', that itself uses the info from 'completed' with an arrayformula + vlookup to filter what shows up in 'Work'. So when an entry is completed and moves to that tab, it will not reappear in 'Work'.
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Work" && r.getColumn() == 17 && r.getValue() == "Completed") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("completed");
var target = targetSheet.getRange(2, 1);
targetSheet.insertRows(2)
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
ss.toast('Complete');
}
However I want to change this so that instead of being an onEdit function, it will be its own function that will detect any rows with column 17 marked "Completed" in 'Work', copy them, create the number of rows in 'completed' that were copied, pastes those rows in, and deletes them in 'Work'. Then I will attach this to an image I will be able to click to run it.
I have tried fiddling with the above code to achieve this, with no luck. Any direction on how to move a variable number of rows to a new tab would be greatly appreciated!
I believe your goal is as follows.
You want to check all values of the column "Q" on Work sheet and when the value of column "Q" is Completed, you want to move the row to completed sheet.
You want to achieve this without using onEdit.
In this case, how about the following modified script?
Modified script:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Work");
// 1. Values are retrieved from `Work` sheet.
var data = sheet.getDataRange().getValues();
// 2. Retrieve the rows including `Completed` at the column "Q" and the rows not including it.
var copiedData = data.reduce((o, r) => {
o[r[16] == "Completed" ? "copy" : "leave"].push(r);
return o;
}, {copy: [], leave: []});
// 3. Retrieve values from `completed` sheet and add the rows including `Completed` at the column "Q".
var targetSheet = ss.getSheetByName("completed");
var targetRange = targetSheet.getRange(2, 1, targetSheet.getLastRow() - 1, targetSheet.getLastColumn());
var targetValues = targetRange.getValues();
var newValues = copiedData.copy.concat(targetValues);
// 4. Clear `completed` sheet and put the new values.
targetRange.clearContent();
targetSheet.getRange(2, 1, newValues.length, newValues[0].length).setValues(newValues);
// 5. Clear `Work` sheet and put the rows not including `Completed` at the column "Q".
sheet.clearContents();
sheet.getRange(1, 1, copiedData.leave.length, copiedData.leave[0].length).setValues(copiedData.leave);
ss.toast('Complete');
}
The flow of this modification is as follows.
Values are retrieved from Work sheet.
Retrieve the rows including Completed at the column "Q" and the rows not including it.
Retrieve values from completed sheet and add the rows including Completed at the column "Q".
Clear completed sheet and put the new values.
Clear Work sheet and put the rows not including Completed at the column "Q".
When you assign the above function to an image on Spreadsheet, you can run the script by clicking the image button.
References:
reduce()
clearContent() of Class Range
clearContents() of Class Sheet
setValues(values)

Automatically Add a Note Based on Dynamic Cell in Google Sheets

I am trying to modify a Script in Google Sheets that creates a Note that contains the content of the Cell it lives in. I think I'm almost there- however, the script I have below only references a static cell. I need it to create a note within each cell in Column C, with each note referencing the text in the specific cell it is assigned.
For example:
C1 contains "TEST", C1 Note shows "TEST"
C2 contains "HELLO", C2 Note shows "HELLO"
C3 contains "WORLD", C3 Note shows "WORLD"
Here is the script that I have currently:
function addNote() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var targetCell = sheet.getRange("C3");
var sourceCell = sheet.getRange("C3");
var noteText = sourceCell.getValue();
targetCell.setNote(noteText);
}***
Appreciate any help that can be provided- also, would be great if this could update the content of the note when the spreadsheet is updated, if anyone knows how to append that.
You want to set the values of column "C" to the notes of the same column.
The values for the notes are the same with the values of cells of column "C".
For example, when the cell "C1" has "TEST", you want to set "TEST" to the note.
When the values of column "C" in 1st tab of active Spreadsheet is edited, you want to update the notes.
You want to achieve this using Google Apps Script.
From your question and your replying comments, I could understanding like above. If my understanding is correct, how about this sample script? Please think of this as just one of several answers.
In this sample script, I used a simple trigger. By this, when the column "C" of the 1st tab is edited, the script is run and the notes of column "C" are updated using the values of column "C".
Sample script:
Please copy and paste the following script and save the script. When you edit the cell of the column "C" in the 1st tab of active Spreadsheet, the script is run and the notes are set with the values of column "C".
function onEdit(e) {
var sheet = e.source.getSheets()[0];
if (e.range.getSheet().getSheetName() === sheet.getSheetName()) {
var range = sheet.getRange("C1:C" + sheet.getLastRow());
var values = range.getValues();
range.setNotes(values);
}
}
References:
Simple Triggers
Event Objects
getValues()
setNotes(notes)
The following script will create a note using the text from the cell that is being edited. The cell must be in the third column ("C"). To change the column that can be edited, change the 3 to the correct column number (A=1,B=2,C=3,etc...)
function onEdit(e){
var range = e.range;
if (range !== 3) return;
range.setNote(e.value);
}
You may want to go a step further and clear the cell after creating the note. Here is an example of that:
function onEdit(e){
var range = e.range;
if (range.getColumn() !== 3) return;
range.setNote(e.value);
range.clearContent();
}
I have done something like this before and found it useful to be able to keep adding notes by entering values into the cell. Here's how you can do that:
function onEdit(e){
var range = e.range;
var newNote = '';
var cellValue = e.value;
if (range.getColumn() !== 3) return;
var previousNote = range.getNote() ? range.getNote() : '';
if (previousNote) {
newNote = cellValue + '\n\n' + previousNote;
} else {
newNote = cellValue;
}
range.setNote(newNote);
range.clearContent();
}