I have 2 scripts in the same project but it seems that only one is working, not specific but depending on the time I add the script, it is like the last script Im adding disabling the other.
these are the 2 scripts (I copied from google forum and updated according to my needs):
adding an auto time stamp to a cell when specified range is not empty:
function onEdit(event) {
var sp = SpreadsheetApp.getActiveSheet();
var c = sp.getActiveCell();
if (c.getColumn() < 9 && sp.getName()=='QUE') {
var celladdresp ='I'+ c.getRowIndex()
sp.getRange(celladdresp).setValue(new Date()).setNumberFormat("dd/mm/yy hh:mm");
}
};
copy a row to another sheet on the same file if checkbox is checked (=true):
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "QUE" && r.getColumn() == 12 && r.getValue() == true) { var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("QUE2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns-2).copyTo(target);
}
};
Your help understanding why they dont work together will be appreciated.
*BTW I tried to Enable/Disable new apps scriptspowered by chrome v8 but did not helped
Answer:
You can only have one onEdit(event) function per script. If you wish both functions to run on edit, you need to combine them.
More Information
It's programming 101 that all functions and variables have to have unique names - otherwise your code isn't going to know which function or variable you're referring to. The uniqueness is important as you're defining exactly what you want.
In this case, as you have two onEdit(event) functions, when the sheet is edited your script is only calling one of these functions. This makes sense - it has no reason to continue looking for more doGet()s if it's already found and executed one.
Merging Functions:
When merging, it's important not to replicate code that is unneccesary. Reducing the number of calls so you only do exactly what you need to is important for efficient-running code:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet()
var r = event.source.getActiveRange();
var c = sheet.getActiveCell();
if (c.getColumn() < 9 && sheet.getName() == 'QUE') {
var celladdresp = 'I' + c.getRowIndex()
sheet.getRange(celladdresp).setValue(new Date()).setNumberFormat("dd/mm/yy hh:mm");
}
if(sheet.getName() == "QUE" && r.getColumn() == 12 && r.getValue() == true) { var row = r.getRow();
var numColumns = sheet.getLastColumn();
var targetSheet = ss.getSheetByName("QUE2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(row, 1, 1, numColumns-2).copyTo(target);
}
}
Related
For starters, I am a complete beginner at using Apps Scripts for Google Sheets at my new workplace, and we do not have an IT department who can help us create this file. I am trying to create a shared file that can be accessed by our client, our service technicians, and our main office simultaneously, so I opted to create a Google Sheet.
I am hoping to automate this process to prevent users (except myself) from needing to manually edit, move and sort data across multiple sheets that might cause the file to break or become inconsistent. For this to work, I need users to only be able to create entries in our 'main' worksheet and only view the other sheets. From here, I'd like to automate the file to move rows to specific sheets named after each unit when it's marked "DONE", and also organize each unit's sheet by the date column. Our intention is for these sheets to provide us with a running history of all the work that has been done each unit.
NOTE: I have 54 units and counting and I currently will have to copy & paste the code multiple times and edit each one to match the unit numbers. I currently have a one unit set-up, but I think there's something wrong with the code or the triggers I have set-up as it does not automatically sort the destination sheet. Either way, I think there has to be a simpler way to do this.
Any advice would be appreciated!
Here's the code that I've used thus far:
function trailer27() {
// moves a row from a sheet to another when a magic value is entered in a column
// adjust the following variables to fit your needs
// see https://productforums.google.com/d/topic/docs/ehoCZjFPBao/discussion
var sheetNameToWatch = "WORKSHEET";
var columnNumberToWatch = 6;2 // column A = 1, B = 2, etc.
var valueToWatch = "Yes";"27"
var sheetNameToMoveTheRowTo = "27"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
SpreadsheetApp.flush()
}
}
function Sort27() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("27")
var range = sheet.getRange("A3:F1000");
// Sorts by the values in column 1 (J)
range.sort({column: 1, descending: false});
}
function SortWorksheet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("WORKSHEET")
var range = sheet.getRange("A3:F1000");
// Sorts by the values in column 10 (J)
range.sort({column: 1, descending: false});
}
function undoMove() {
// moves a row from a sheet to another when a magic value is entered in a column
// adjust the following variables to fit your needs
// see https://productforums.google.com/d/topic/docs/ehoCZjFPBao/discussion
var sheetNameToWatch = "27"
var columnNumberToWatch = 6; // column A = 1, B = 2, etc.
var valueToWatch = "CALLED"; "EMAIL"
var sheetNameToMoveTheRowTo = "WORKSHEET";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1, sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
SpreadsheetApp.flush()
}
}
If this is meant to be an onEdit function it's worth using the event object even considering the difficulty in debugging
function trailer27(e) {
const sheet = e.range.getSheet();
var sheetNameToWatch = "WORKSHEET";
var columnNumberToWatch = 6; 2 // column A = 1, B = 2, etc.
var valueToWatch = "Yes"; "27"
var sheetNameToMoveTheRowTo = "27"
if (sheet.getName() == sheetNameToWatch && e.range.columnStart == columnNumberToWatch && e.value == valueToWatch) {
var targetSheet = e.source.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(e.range.rowStart, 1, 1, sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(e.range.rowStart);
SpreadsheetApp.flush();
}
}
I'm trying to write a script which would allow me to copy a row into a new tab based on a specific cell value. In this case, it is a checkbox of being set to TRUE.
I have no issue with copying the row to a new sheet based on the cell value, but now I'm unsure as to how I can use insertCheckboxes to append 5 checkboxes to the copied row in the new sheet.
This is the code I have at the moment:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Client Database" && r.getColumn() == 9 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Referrals");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
}
Column 9 contains checkboxes which when set to true, copies the row from "Client Database" into my new tab ("Referrals").
I'm scratching my head over two things:
What do I need to change in the code to only copy columns 1 and 4 from the original sheet? (as it is currently copying all columns from the row).
Unless there is an easier workaround, how can I append checkboxes into the adjacent columns within the new sheet using insertCheckboxes? (Illustration below). This is simply to avoid having to manually insert the boxes each time (as I will not be the one using the sheet)
Any advice is greatly appreciated.
Checkboxes
Add to your script
var checkbox = SpreadsheetApp.newDataValidation().requireCheckbox().build();
targetSheet.getRange(targetRow,3,1,4).setDataValidation(checkbox).setValue("FALSE");
where targetRow is the row and targetSheet the sheet where you copy
code
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (s.getName() == "Client Database" && r.getColumn() == 9 && r.getValue() == true) {
var row = r.getRow();
var targetSheet = ss.getSheetByName("Referrals");
targetSheet.insertRowBefore(2)
var targetRow = 2
targetSheet.getRange(targetRow,1).setValue(s.getRange(row,1).getValue())
targetSheet.getRange(targetRow,2).setValue(s.getRange(row,4).getValue())
var checkbox = SpreadsheetApp.newDataValidation().requireCheckbox().build();
targetSheet.getRange(targetRow,3,1,4).setDataValidation(checkbox).setValue("FALSE");
}
}
This question already has an answer here:
Merging or Combining two onEdit trigger functions
(1 answer)
Closed 1 year ago.
Can someone point me in the right direction please?
I'm attempting to run two onEdit() which both send a range of cells to an archived sheet depending on whether a checkbox is ticked.
My code results in the entire row being moved and deleted rather than the specified cell range irregardless of which of the two checkboxes is selected as TRUE.
function onEdit(event) {
onEdit1();
onEdit2();
function onEdit1() {
// assumes source data in sheet named Active
// target sheet of move to named Found
// test column with yes/no is col 31
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "WORKSHOP" && r.getColumn() == 31 && r.getValue() == true) {
var row = r.getRow();
var numColumns = 11
var targetSheet = ss.getSheetByName("ARCHIVE-DEFECTS");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 23, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
function onEdit2() {
// assumes source data in sheet named Active
// target sheet of move to named Found
// test column with yes/no is col 10
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "WORKSHOP" && r.getColumn() == 10 && r.getValue() == true) {
var row = r.getRow();
var numColumns = 12
var targetSheet = ss.getSheetByName("ARCHIVE-INSP");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
}
Apologies I'm not very knowledgeable and am kind of learning by doing by readin threads in the forum. Cheers.
Try this
function onEdit(event) {
onEdit1(event);
onEdit2(event);
}
function onEdit1(event) {
_________
}
function onEdit2(event) {
_________
}
it seems that there is a lack og event parameter
I'm a beginner in coding and on SO, but I'm trying to understand what I'm doing and what is happening in the code.
I'm wanting to move a row between different spreadsheets.
I have a script in "CORE" Spreadsheet, which moves a row between the "Home" and "Finished" sheets Link to the spreadsheet:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (s.getName() == "Home" && r.getColumn() == 5 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Finished");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
else if (s.getName() == "Finished" && r.getColumn() == 5 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Home");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
I searched how to move the data located on "Finished" sheet to another spreedsheet called "DATA BASE" Link to the spreadsheet:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Finished");
var range = sheet.getRange("A1:E2");
var values = range.getValues();
var allvals = [];
for (var i = 0; i < values.length; i++) {
allvals.push(values[i]) ;
}
var dataLength = allvals.length;
// alert data
var ui = SpreadsheetApp.getUi();
// ui.alert( JSON.stringify(allvals) )
// copy to another Google Spreadsheet
var newSheet = SpreadsheetApp.openById('1Xn-hrPPr3tQwWMbKdWxHTXcazOqWu1bdHT6A5LZmlD8').getSheets()[0];
var tmp = "A1:E" + dataLength;
var newRange = newSheet.getRange(tmp);
newRange.setValues(values);
}
But I want to transfer the data from sheet "CORE"/"Finished" to sheet "DATA BASE"/ "DB" without rewriting the other rows already on the DB sheet. My idea is to make the spreadsheet "DATA BASE" a real database, where other sheets put data in it and other sheets use this data.
Is it possible to move rows between different spreadsheets like in the first code? I know its impossible to use the .openById() with the function onEdit(), but the most important thing is to move the rows without rewriting the other rows already in the target sheet (DB).
Moving a row to another spreadsheet with installable onEdit trigger
This is just an example of moving the data in a row from one spreadsheet to another with an installable onEdit Trigger. If you wish to play with it don't forget to add the target spreadsheet id.
function onMyEdit(e) {
//e.source.toast('Entry');
var sh=e.range.getSheet();
//Logger.log(JSON.stringify(e));
if(sh.getName()=='Sheet2' && e.range.columnStart==11 && e.value=="TRUE") {
//e.source.toast('Access');
e.range.setValue('FALSE');
var tss=SpreadsheetApp.openById('SSID');
var tsh=tss.getSheetByName('Sheet2');
var v=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()-1).getValues();
Logger.log(v);
tsh.getRange(tsh.getLastRow()+1,1,v.length,v[0].length).setValues(v);
sh.deleteRow(e.range.rowStart);
}
}
I am using 2 functions in a tracker that I have. 1 function is for sorting column C by date (earliest first) automatically when a cell in that column is edited. If the word 'done' or 'void' is typed into that cell then the entire row is copied onto the next sheet.
However my issue is that when I type 'done' or 'void' into this cell, Google sheets is sorting the list and also processing the move function and thus moving the wrong row (the resulting row number, after the sort). How can i fix or improve the code.
function movedonevoid(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
var value = r.getValue();
if(s.getName() == "tracker" && r.getColumn() == 3 && (value=="done" || value=="void" )) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("tracker2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
and
function sorttracker(event){
var sheet = event.source.getActiveSheet();
if(sheet.getName() == 'tracker'){
var editedCell = sheet.getActiveCell();
var columnToSortBy = 3;
var tableRange = "A2:D"; // What to sort.
if(editedCell.getColumn() == columnToSortBy) {
var range = sheet.getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}
}
}
I've inserted the above 2 bits of code as 2 different scripts and then used project triggers for both 'on edit'. Not sure if that is the best approach?
As you already noticed, having two different functions acting over the same range and being called by two different onEdit triggers isn't a good idea.
Instead of using two onEdit triggers, use only one to call an orchestral conductor function that will call the original two. The orchestral conductor function could be something like the following:
function onEdit(e) {
movedonevoid(e);
sorttracker(e);
}