I'm trying to create a script that will copy a range of data from one sheet to two other separate sheets when a user clicks "Yes" in the alert message. One of those two will be on a new spreadsheet created using a template. The data I want to copy is from a sheet called "data". The destination sheets are named "selected" and on the new spreadsheet, "csv". The new spreadsheet will be stored in a different folder. Found this [script][1] to be very helpful for me to get started.
The onEdit script is working fine for the "data" sheet and transfers the chosen row to the "selected" sheet when a user clicks the checkbox and the "Yes" button in the alert message.
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "data" && r.getColumn() == 16 && r.getValue() == "Yes") {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Are you sure you want to continue?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("selected");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
Logger.log('The user clicked "Yes."');
}
else if (response == ui.Button.NO) {
clearAnswer();
Logger.log('The user clicked "No" or the close button in the dialog\'s title bar.');
}
}
First issue I have is that the condition else if is not triggering the function "clearAnswer" when a user clicks NO in the alert message even though the function works when triggered in the script editor.
function clearAnswer() {
var app = SpreadsheetApp;
var clearSheet = app.getActiveSpreadsheet().getActiveSheet();
clearSheet.getRange("P2:P").clearContent();
}
Second issue is I don't know where to begin with the script that will copy the chosen row from the "data" sheet to the "csv" sheet on a new spreadsheet which will be created using a template. I found this script so far.
// Pull spreadsheet template
var ss = SpreadsheetApp.openById('TEMPLATEFILEID');
var newSS = ss.copy("Copy of " + ss.getName());
// Move to original folder
var targetFolder = DriveApp.getFileById('FOLDERFORNEWFILE');
var newSSFile = DriveApp.getFileById(newSS.getId());
originalFolder.addFile(newSSFile);
DriveApp.getRootFolder().removeFile(newSSFile);
}*/
I would appreciate any help you can give me or I hope you can point me to the right direction so I can figure things out faster.
You else if is nested outside of the popup event. Try like this:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "data" && r.getColumn() == 16 && r.getValue() == "Yes") {
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Are you sure you want to continue?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("selected");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
Logger.log('The user clicked "Yes."');
} else if (response == ui.Button.NO) {
clearAnswer();
Logger.log('The user clicked "No" or the close button in the dialog\'s title bar.');
}
}
}
}
Related
I'm new to the world of javascript & google apps script and I'm struggling to get a row of data to move from one spreadsheet to another. I have it moving a row from sheet to sheet within the same spreadsheet but not across spreadsheets.
I know I need to use SpreadsheetApp.openById("insertID") rather than SpreadsheetApp.getActiveSpreadsheet() but I can't seem to make it work.
Here is the code I have that's working based on moving sheet to sheet, how do I modify it to move to a new spreadsheet?
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Timeline Submit" && r.getColumn() == 117 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("WIP");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target, {contentsOnly:true});
} else if(s.getName() == "WIP" && r.getColumn() == 117 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getColumn();
var targetSheet = ss.getSheetByName("Timeline Submit");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target, {contentsOnly:true});
}
}
I couldn't figure out everything in the second section of your code but it had too many errors so I just guessed and some of it.
Don't forget to go create a trigger for this in the Script Editor Edits/Current Project Triggers.
function installableOnEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()=="Timeline Submit" && e.range.columnStart==117 && e.value==true) {
var ss=SpreadsheetApp.openById('id')
var tsh= ss.getSheetByName("WIP");
var trg=tsh.getRange(tsh.getLastRow()+1,1);
sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).copyTo(trg,{contentsOnly:true})
}else if(sh.getName()=="WIP" && e.range.columnStart==17 && e.value==false) {
var ss=SpreadsheetApp.openById('id')
var tsh=ss.getSheetByName('Timeline Submit');
var trg=sh.getRange(tsh.getLastRow()+1,1);
sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).copyTo(trg,{contentsOnly:true});
}
}
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 have two Sheets that I will be moving Data between frequently. On Sheet1, I have all my data and checkboxes are used to send that same data to Sheet2. When the data is sent over, empty rows are left behind so I know what positions are available when I rebuild the sheet at the end of the day.
The data on Sheet2 will be modified and at the end of the day I'd like to move everything back to Sheet1 taking the first available empty row. I have the first part working fine, but I cannot seem to get the data to move back to Sheet1 into the first available (empty Cell).
Currently the issue is when I uncheck the box to give the row a value of false, the data is removed from Sheet2 but not moved into Sheet1.
Here is what I have so far:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Foss Test 2" && r.getColumn() == 4 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Foss Test");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
} else if(s.getName() == "Foss Test" && r.getColumn() == 4 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Foss Test 2");
var target = targetSheet.getRange(targetSheet.getDataRange().getHeight() + 1, 1)
targetSheet.appendRow(target.getValues()[0]);
s.deleteRow(row);
}
}
I feel like my error is in the else block as currently no data is moved back to Sheet1.
Although you didn't define the term "source" I assume this is what you want.
function onEdit(e) {
e.source.toast('flag0');
var sh=e.range.getSheet();
if(sh.getName()=="Sheet1" && e.range.columnStart==4 && e.value=="TRUE") {
var targetSheet=e.source.getSheetByName("Sheet2");
var target=targetSheet.getRange(targetSheet.getLastRow() + 1,1);
sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).moveTo(target);
} else if(sh.getName()=="Sheet2" && e.range.columnStart==4 && e.value=="FALSE") {
var targetSheet=e.source.getSheetByName("Sheet1");
var vA=targetSheet.getDataRange().getValues();
for(var i=0;i<vA.length;i++) {
if(vA[i].join('').length==0) {
var target=targetSheet.getRange(i+1,1);
sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).moveTo(target);
break;
}
}
}
}
If that's not what you want please let me know.
I pretty much have the Apps Script file working as intended. However, each time it is triggered, it also adds a second line where the sessionEmail is not captured and is blank.
function onEdit() {
var sessionEmail = Session.getActiveUser().getEmail();
var spreadsheetTimeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var lastUpdatedString = Utilities.formatDate(new Date(), spreadsheetTimeZone, "MM/dd/yyyy' 'HH:mm:ss");
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Workload") { //checks that we're on the correct sheet
var r = s.getActiveCell();
if (r.getColumn() == 14) { //checks the column
var status = r.getValue();
var note = r.offset(0, -1);
var noteValue = note.getValue()
var delivery = r.offset(0, -5);
var deliveryValue = delivery.getValue()
}
// Validating fields are filled in
if (status == "Complete") {
var ui = SpreadsheetApp.getUi();
if (noteValue == '') { // if no note is entered, stop script with message box
var noStatus = ui.alert(
'Warning!',
'Please enter notation before choosing Complete.',
ui.ButtonSet.OK);
r.setValue('')
return;
}
// get destination range
var array = [lastUpdatedString, sessionEmail, deliveryValue, noteValue]
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pasteSheet = ss.getSheetByName("Historical Notes Sheet");
pasteSheet.appendRow(array)
// clear response row
note.setValue('')
r.setValue('')
}
}
}
Image of what the results look like:
If any of you have any ideas on how to resolve this, and only append 1 line that has all the values, I would really appreciate it.
Thanks!
Update:
Logging the variable produces the following (expected) results, where the e-mail address appeared in the string.
Results still populating 2 rows:
Thanks for helping me troubleshoot.
I went into View>Executions, and noticed that the script was running twice each time at about 2 milliseconds apart. I think the function name onEdit() was acting like an On Edit trigger, and causing the script to run with another On Edit trigger that I had set up for it.
I tried removing the trigger, and leaving it with the onEdit()name, but that was causing it to not grab the sessionEmail. Changing the code to the below, and adding the trigger back causes the code to run as expected.
function appendLine() {
var sessionEmail = Session.getActiveUser().getEmail().toString();
var spreadsheetTimeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var lastUpdatedString = Utilities.formatDate(new Date(), spreadsheetTimeZone, "MM/dd/yyyy' 'HH:mm:ss");
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Workload") { //checks that we're on the correct sheet
var r = s.getActiveCell();
if (r.getColumn() == 14) { //checks the column
var status = r.getValue();
var note = r.offset(0, -1);
var noteValue = note.getValue()
var delivery = r.offset(0, -5);
var deliveryValue = delivery.getValue().toString();
}
// Validating fields are filled in
if (status == "Complete") {
var ui = SpreadsheetApp.getUi();
if (noteValue == '') { // if no note is entered, stop script with message box
var noStatus = ui.alert(
'Warning!',
'Please enter notation before choosing Complete.',
ui.ButtonSet.OK);
r.setValue('')
return;
}
// get destination range
var array = [lastUpdatedString, sessionEmail, deliveryValue, noteValue]
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pasteSheet = ss.getSheetByName("Historical Notes Sheet");
pasteSheet.appendRow(array)
// clear response row
note.setValue('')
r.setValue('')
}
}
}
Thanks again to everyone for your help!
I would like to add a confirmation message box to appear before the script runs.
Here is the script:
function moveTo(e) {
// 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 try {
var sheetNameToWatch = "Active Discs";
var columnNumberToWatch = 15; // column A = 1, B = 2, etc.
var valueToWatch = "Completed";
var sheetNameToMoveTheRowTo = "CompletedShipped Projects";
var ss = e.source;
var sheet = ss.getActiveSheet();
var range = e.range;
if (sheet.getName() == sheetNameToWatch && range.columnStart == columnNumberToWatch && e.value == 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());
}
} catch (error) { Logger.log(error)
}
The message box would contain the following message set-up:
The message should read "Do you confirm to move Ocean Gil to Completed Shipped Projects Sheet?"
var app = UiApp.createApplication().setHeight(150).setWidth(250);
var msg = "Do you confirm to move " + "Active row cells A + B" + " to Completed Shipped Projects Sheet?";
app.setTitle("Please Confirm this Action");
app.add(app.createVerticalPanel().add(app.createLabel(msg)));
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
If the person choose yes, then the "moveTo" script executes. If no, then script does nothing and closes the prompt window.
Here is the shared Google Spreadsheet.
https://docs.google.com/spreadsheet/ccc?key=0Ag8NytPhOo00dER6WG1PQ3g3V1hCbnVUaTJUZDFZenc&usp=sharing
Any help with code would be much appreciated. Thanks in Advance.
It would probably be more easy and compact to use the Browser class in this case, see doc here with example code
EDIT : in you code you can use it like this for example :
function moveTo(e) {
// 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 try {
var sheetNameToWatch = "Active Discs";
var columnNumberToWatch = 15; // column A = 1, B = 2, etc.
var valueToWatch = "Completed";
var sheetNameToMoveTheRowTo = "CompletedShipped Projects";
try{
var ss = e.source;
var sheet = ss.getActiveSheet();
var range = e.range;
if (sheet.getName() == sheetNameToWatch && range.columnStart == columnNumberToWatch && e.value == valueToWatch) {
var confirm = Browser.msgBox('Do you want to move data to the other sheet ?', Browser.Buttons.YES_NO);
if(confirm!='yes'){return};// if user click NO then exit the function, else move data
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());
}
} catch (error) { Logger.log(error)}
}