Copy Paste Script Google Sheets - google-apps-script

I work for a major Motor Manufacturer and I need some help with a google sheets script that I need to write (I assume a script is the way forward?)
I have a google sheets file that is used to monitor issues and planned improvements for multiple departments. The workbook has multiple tabs that I need to somehow copy and paste data around within it.
I have included a sample file to try and help explain it, it's quite a complicated file to try and explain...I will do my best. It sounds like I need to use a script but I am new to using scripts.
Link to Sheet
Explanation of file:
On a weekly basis I update the sheet with latest data into the "Master data" sheet, this sheet feeds the "electrical" sheet using a query.The dept owner for electrical updates updates the "electricalinput" sheet with his actions and timing and this feeds into the "electrical" sheet also. The "electrical" sheet in turn feeds the "improvement data" sheet which feeds the chart.
It is arranged like this so what when new issues are added and the order changes the comments follow on the "electrical" sheet, and the owner only needs to update the "electricalinput" sheet with comments that he hasn't already done.
What I would like try and do:
I would like to be able to run a script that filters or extracts anything in the electrical sheet with #N/A against it (which means the 3 cell combination hasn't been found in the input sheet) and copy and paste just those items into the "electricalinput" sheet at the next available line that isn't populated. In the actual file there are multiple depts so variations of the script will have to run to cover the different depts.

I've updated the spreadsheet that you shared with relevant code.
You can run the script via Add Ons->Master Data Utils->Clean Up Keys menu. The menu was created in the OnOpen function from this script.
Note that there are a couple of requirements as below for the script to work.(already taken care of in the shared ss)
Departments lists and details helpful for processing all the data as shown below.
There should be a NamedRange called Department_List which would be top left cell of the table shown above.
Column to Clean -> Action Summary
is the column we would be using to search of #N/A
Display Sheet Name -> Electrical
is where the #N/A would be.
Input Sheet Name -> Electricalinput
is the sheet name that would be updated.
Copy Cols From(Disp) -> B:D
the columns that would be copied over
Similar to d but this is where sata would be copied to
But at the moment the code doesn't use this and just pastes into first available cell in col B
Here's the code I attempted, let me know of any suggestions or alterations that would make it easier to use.
function cleanComponentList(curSS) {
Logger.log("Init script cleanComponentList 'Department_List'")
curSS = curSS || SpreadsheetApp.getActiveSpreadsheet()
var deptListStart = curSS.getRangeByName("Department_List")
if(deptListStart==null){
Logger.log("This script cannot be used without the named range 'Department_List'")
return
}
var dept = deptListStart.offset(1,0)
while( ! dept.isBlank() ){
Logger.log("Started processing " + dept.getDisplayValue() + " Dept.")
//Get Department Sheet
var deptSht = curSS.getSheetByName(dept.offset(0,1).getValue())
//Get Column that has Action Summary in department sheet
var actSummCol=deptSht.getRange(2, 1)
//Get Department Input Sheet (Target Sheet where we need to copy the final values to
var deptInputSht = curSS.getSheetByName(dept.offset(0,2).getValue())
//Find column with the "Column Header"/"Summary" in which we search #N/A
while( ! (actSummCol.getDisplayValue() === dept.offset(0,3).getDisplayValue())){
var tmp = actSummCol.getDisplayValue()
var actColRng = actSummCol.getA1Notation()
actSummCol=actSummCol.offset(0,1)
}
var actSummColAddress = actSummCol.getA1Notation();
Logger.log("Found key \"" + dept.offset(0,3).getDisplayValue() + "\" for " + dept.getDisplayValue() + " # " + actSummColAddress)
var errRows = []
//Get all rows that have error Action Summary
var lastRow = deptSht.getLastRow()
for(nRow=1;nRow<lastRow;nRow++){
//There should be a better of checking #N/A
if(actSummCol.offset(nRow,0).getDisplayValue().equals("#N/A")){
errRows.push(nRow+actSummCol.getRow())
}
}
Logger.log("Got " + errRows.length + " error rows for " + dept.getDisplayValue() + " Dept.")
//Get Cell where data append should start from.
var deptInputLastAvailableRow = deptInputSht.getRange("B1")
while(!deptInputLastAvailableRow.isBlank() || deptInputLastAvailableRow.isPartOfMerge()){
deptInputLastAvailableRow=deptInputLastAvailableRow.offset(1,0)
}
Logger.log(dept.getDisplayValue() + " Dept." + " Input will be updated from " + deptInputLastAvailableRow.getA1Notation())
//Copy CDE from the filtered rows to Department Input Sheet
var srcCols=deptSht.getRange(dept.offset(0,4).getDisplayValue())
//There should be a better way of iterating. for-of throws syntax error!!!
for(idx in errRows){
var row = errRows[idx];
var lc = srcCols.getLastColumn()
var fc = srcCols.getColumn()
var errKeyRangeAddress=srcCols.getCell(row,1).getA1Notation() + ":" + srcCols.getCell(row,lc-fc + 1).getA1Notation()
var errKeyRange=deptSht.getRange(errKeyRangeAddress)
errKeyRange.copyTo(deptInputLastAvailableRow)
deptInputLastAvailableRow=deptInputLastAvailableRow.offset(1,0)
}
Logger.log("Copied " + errRows.length + " entries to Sheet \"" + deptInputSht.getName() + "\"")
Logger.log("Finished Processing " + dept.getDisplayValue() + " Dept.")
dept=dept.offset(1,0)
}
}
function onOpen(){
//Choose which way you want your menu to appear.
//SpreadsheetApp.getActiveSpreadsheet().addMenu("Monitor", [{name:"Clean Up Keys",functionName:"cleanComponentList"}])
SpreadsheetApp.getUi().createAddonMenu().addItem("Clean Up Keys", "cleanComponentList").addToUi()
}

This is a simple copy script to help you get started. copyTo is documented here. The rest of the commands can be found in the same documentation.
After you've done a few of your own scripts you'll find it a lot easier to make up your own rather than spending all of your time copying scripts.
function copyPasteSelectedRows()
{
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName('Sheet2');
var sh0=ss.getSheetByName('Sheet1');
var rg0=sh0.getDataRange();
var vA=rg0.getValues();
for(var i=1;i<vA.length;i++)
{
if(vA[i][10]==1)//condition to meet to copy
{
var src=sh0.getRange(i+1,1,1,vA[i].length);//source range
var tar=sh1.getRange(sh1.getLastRow() + 1,1,1,vA[i].length);//target range
src.copyTo(tar);
}
}
}
This is Sheet1:
This is Sheet2 after the copy:

Related

Using Google Script to extract conditional formatting from a google sheet so I can reuse it

I am familiar with writing conditional formatting rules in Google script.
I have a Google sheet that I have inherited that has been developed over a long period and conditional formatting rules have been manually inserted.
I am looking to copy all of the conditional formatting out of that google sheet using google apps script. The sheet has around 50 columns with many drop downs, and each dropdown, or combination of dropdowns, applies formatting. I think there are over 100 rules.
It would be VERY useful if I could get the conditional formatting out in a format that I could modify as needed and apply other (similar) sheets.
Any suggestions?
Mark
SUGGESTION
Note: We normally do not code for you, but in this case I have a sample script that I can share with you that was derived from the samples of these Spreadsheet App classes listed below:
You can try using these Spreadsheet App classes in Apps Script:
getBooleanCondition()
withCriteria(criteria, args)
ConditionalFormatRuleBuilder
Class Ui
Sample Script
var ui = SpreadsheetApp.getUi();
function onOpen() { //Sets the custom menu
ui.createMenu('Extract Existing Conditional Formatting')
.addItem('Copy Conditonal Formatting', 'checkRangeSelection')
.addToUi();
}
function checkRangeSelection() { //checks the selected range & asks user if he/she wants to copy the range's conditonal formatting values to another sheet range
var rule = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getConditionalFormatRules()[0];
var ranges = rule.getRanges();
var selectedRange = SpreadsheetApp.getActiveSheet().getSelection().getActiveRange().getA1Notation();
var newCriteriaValue;
for (var i = 0; i < ranges.length; i++) {
if (selectedRange == ranges[i].getA1Notation()) {
var response = ui.alert("Selected Range: " + selectedRange +
"\n\nThis range has these criteria:\n" +
"\nTYPE: " + rule.getBooleanCondition().getCriteriaType() +
"\nVALUE: " + rule.getBooleanCondition().getCriteriaValues() + '\n\nDo you want to update it and apply it to a new sheet range?',
ui.ButtonSet.YES_NO);
if (response == ui.Button.YES) {
var valueNew = ui.prompt("Current Criteria Value is: " + rule.getBooleanCondition().getCriteriaValues() + "\n\n Type here to change it:\n");
valueNew.getResponseText() == '' ? newCriteriaValue = rule.getBooleanCondition().getCriteriaValues() : newCriteriaValue = valueNew.getResponseText();
var destSheet = ui.prompt("Type the \"Sheet Name\" where you would like to apply the conditional formatting:\n\n");
var newRange = ui.prompt("Type the \"Range\" (e.g. A1:A100) where you would like to apply the conditional formatting:\n\n");
try {
var destinationSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(destSheet.getResponseText());
var range = destinationSheet.getRange(newRange.getResponseText());
var copiedrule = rule.copy().withCriteria(rule.getBooleanCondition().getCriteriaType(), [newCriteriaValue.toString()]).setRanges([range]).build();
var rules = destinationSheet.getConditionalFormatRules();
rules.push(copiedrule);
destinationSheet.setConditionalFormatRules(rules);
} catch {
ui.alert('Double check Sheet Name and the Range you have used & try again.');
}
} else {
ui.alert('Cancelled');
}
} else {
ui.alert('Selected range \"' + selectedRange + '\" doesn\'t contain any criteria.');
return;
}
}
}
Demonstration
Note: On this demonstration, I have two sample sheets named the CURRENT (the main sheet that contains the conditional formatting rules) & DESTINATION
Save the script as a bound script in your spreadsheet file
Then, run the onOpen function once on the Apps Script editor to load the custom menu.
After that, you will see a custom menu named "Extract Existing
Conditional Formatting" on your spreadsheet as seen below:
You can highlight any range that contains the Conditional
Formatting that you'd like to copy to another sheet tab, then press the custom menu. It will show you the criteria type used and its value, as seen here (this sample was done on the CURRENT sheet) :
If you press the Yes button, you will be prompted to change these details below:
Update the Criteria Value Or you could use the default value by just pressing Ok to go to the next step:
Type the Destination Sheet name
Type the Range (in A1 Notation format) where you want to apply the copied Conditional Formatting
After that, on the DESTINATION sample sheet, the Conditional Formatting has been applied to the range.

Maintaining "table status" when fetching Google Sheets values

I have a list of people that I need to send a schedule to every week. The schedule, and the list of emails for the people it needs to go to, are on a Google Sheet. I'd like to create a script that (a) gets the schedule, and (b) sends it to the list of emails.
My problem, right now, is my Google Apps Script code only sends the schedule as a string (e.g. "role1, person1, role2, person2, role3, person3"), instead of "keeping" its formatting as a table,
I've considered a loop that would grab the values of every row and add a "\n" value at the end, which would break the string after each person. That's not an unworkable solution, but I'd prefer to keep the table because it's more readable.
I suspect that I need to create an HTML table within Google Apps Script, populate it with values from my spreadsheet, and set that HTML table as my email body. That seems odd, because it's already a table (in the spreadsheet).
Is there a way to fetch values while maintaining their "table status"? If not, what are the bare-bones of creating/populating an HTML table?
Here's my code so far, for reference:
function WeeklyReminder() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // this directs the script to the spreadsheet
var sheet = ss.getSheetByName("Automated WVS Weekly Reminder Email"); // this directs the script to the right sheet
var schedule_values = sheet.getRange("D2:E").getDisplayValues(); // this gets the schedule values; "display values" because we want "what's seen," and not the function that's used to populate the cell
Logger.log("schedule_values = " + schedule_values);
var test_email = "o...#...org";
var volunteer_values = sheet.getRange("B2:B").getDisplayValues();
Logger.log("volunteer_values = " + volunteer_values);
MailApp.sendEmail({
to: test_email,
subject: 'WVS Weekly Reminder',
htmlBody: schedule_values.toString(),
});
}
Note: I'm aware my htmlBody sends...toString() at the moment, that's what I'm looking to change.
Building the html table
function WeeklyReminder() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getSheetByName("Automated WVS Weekly Reminder Email");
var vs=sheet.getRange(1,4,sheet.getLastRow(),2).getDisplayValues();
var html='<style>td,th{border:1px solid black;}</style><table>';
vs.forEach(function(r,i){
if(i==0) {
html+=Utilities.formatString('<tr><th>%s</th><th>%s</th></tr>',r[0],r[1]);//I changed the range so that it included the headers
}else{
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td></tr>',r[0],r[1]);
}
html+='</table>';
});
var test_email="o...#...org";
var volunteer_values=sheet.getRange(2,2,sheet.getLastRow()-1,1).getDisplayValues();
MailApp.sendEmail({to: test_email,subject: 'WVS Weekly Reminder',htmlBody:html});
}

Copying Data Sheet1 to Sheet2 so you can sort & edit both sheets (google apps script?)

I am working in goggle sheets and think I need to use a google apps script to do what I want, but I am a psychologist at a non-profit University hospital trying to do some good and not a programmer (which probably shows) and I am desperately in need of help. I am trying to set up a series of spreadsheets to track participation in workshops for our treatment method.
1) I have a sheet “Participant_Registration” where basic information is entered
2) I want to transfer information from only the first four columns (A:D) of “Participant_Registration” to a second sheet “Learning_Sessions_Attendance”
3) I am also transferring the same information to a third sheet 'Consultation1_Attendance' – but I need to first filter and select only those people assigned to that group.
Here is a link to a copy of my spreadsheet.
https://docs.google.com/spreadsheets/d/17d0bT4LZOx5cyjSUHPRFgEZTz4y1yEL_tO3gtSJ4UJ8/edit?usp=sharing
More generically this is what I am trying to do. Is this possible in google app scripts? It seems it should be.
1) I have original data in sheet1
2) I want the first four columns (A:D) to transfer to sheet2 (it is fine if I need a trigger variable)
3) I want them to transfer in such a way that if you sort either sheet, the data are still fine (still linked to the right line).
4) Ideally if there is a change to the data in the source sheet (Sheet1) the same change will be made in Sheet2.
5) Ideally this would all happen automatically without human intervention through a script.
Any ideas?? I so need your help. I have been all over the forum, git hub, and done a ton of searches and tried following a lot of examples I saw but nothing works. I really need help.
Here are my sample scripts each with a problem:
//The following code copies a range from sheet1 to sheet2 as I wanted. A problem occurs if after if we copy the data from sheet1 we add data to other columns on sheet2. Later if we sort on some variable (which people are bound to do) if the function is deployed again it will overwrite data meaning the data from sheet1 are not connected to the right individual on sheet2
function CopyRange() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Participant_Registration");
var range = sheet.getRange("A14:D");
var values = range.getValues();
var target = ss.getSheetByName("Learning_Sessions_Attendance");
var target_range = target.getRange("A10:D");
range.copyTo(target_range);
}
So I tried again. This time I tried to just copy the last edited row from sheet1 to sheet2. This function does not appear to work for me.
function CopyRow2() {
// Get Spreadsheets
var source = SpreadsheetApp.openById("1egn6pnRd6mKMGuQxX_jtgwYDtkuMUv2QJItLdh7aIEs");
var target = SpreadsheetApp.openById("1egn6pnRd6mKMGuQxX_jtgwYDtkuMUv2QJItLdh7aIEs");
// Set Sheets
var source_sheet = source.getSheetByName("Participant_Registration");
var target_sheet = target.getSheetByName("Learning_Sessions_Attendance");
var rowIdx = source_sheet.getActiveRange().getRowIndex();
var rowValues = source_sheet.getRange(rowIdx,1,1,source_sheet.getLastRow()).getValues();
Logger.log(rowValues);
var destValues = [];
destValues.push(rowValues[0][0]);// copy data from col A to col A
destValues.push(rowValues[0][1]);//copy data from col B to col B
destValues.push(rowValues[0][2]);//copy data from col C to col C
destValues.push(rowValues[0][3]);//copy data from col D to col D
var dest=source.getSheets()[4];
dest.getRange(dest.getLastRow()+1,1,1,destValues.length).setValues([destValues]);//update destination sheet with selected values in the right order, the brackets are there to build the 2D array needed to write to a range
}
So I tried again and again. I have lots of examples but none seem to work.
Thanks so much.
Chandra
For that to happen automatically (one sheet's change updating another sheet), you will surely need an "event/trigger" to run a script whenever you change a cell. (that is the "onEdit()" function).
But since scripts are likely to fail sometimes (even when they are perfect, that's because of some Google issues), it's not guaranteed that the sheets will always contain the same data.
But, if I could suggest another way, do not let ID be optional. If that is a real ID (like the person ID card number), create another ID exclusively for working with the sheet.
I have edited your second sheet showing a suggestion of how to do it without using scripts. The only things you must be aware of are:
Do not create two people with the same ID.
You have to insert (only) the ID manually in the second sheet.
The VLOOKUP forumla will search for that ID in the first sheet and return the data in the same line. You can sort any sheet in whatever way you like. As long as you don't change people's IDs.
So, in sheet 2, use this in the First Name, Last Name and Email address:
=vlookup(A10,Participant_Registration!$A:$D,2,false)
=vlookup(A10,Participant_Registration!$A:$D,3,false)
=vlookup(A10,Participant_Registration!$A:$D,4,false)
Just extend this formula downwards
I hope this helps. I would avoid scripting for that at any cost. It would be my last resort. (Scripts also need to be changed if you want to rearrange your sheet, and if not, they might cause trouble, write over existing data...)
I also added a button (insert - drawing) and put a script in it (right button, click down arrow, "transfer? script" -- translated from Portuguese).
If you lock all four columns in sheet2 and lock the ID column in sheet 1, people will not be able to chang IDs and cause mess. They can edit people in sheet 1 and not change the formula in sheet2. Script is not affected by sorting or empty spaces (it adds the person in the first empty row it finds).
I added "named ranges" for the four column headers. (With named ranges, the script can refer to names instead of coordinates, which enables you to rearrange the sheet inserting and deleting columns, or moving them with CUT and paste - but the VLOOKUP formula will need manual update if you rearrange columns).
Here is the code: (it could get better if you manage to create dialog boxes and ask for the person's data inside that dialog, then you could lock everything - and you would need an edit button besides the add).
function AddPerson()
{
var S1Name = "Participant_Registration";
var S2Name = "Learning_Sessions_Attendance";
var ID1Name = "regID";
var ID2Name = "learnID";
//these vars are not used in this script
var FN1Name = "regFirstName";
var FN2Name = "learnFirstName";
var LN1Name = "regLastName";
var LN2Name = "learnLastName";
var Email1Name = "regEmail";
var Email2Name = "learnEmail";
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var Sheet1 = sSheet.getSheetByName(S1Name);
var Sheet2 = sSheet.getSheetByName(S2Name);
var ID1 = getRangeByName(sSheet, Sheet1.getName(), ID1Name);
var ID2 = getRangeByName(sSheet, Sheet2.getName(), ID2Name); Logger.log("ID2: " + ID2.getValue());
var Empty1 = getFirstEmpty(ID1);
var Empty2 = getFirstEmpty(ID2);
var Biggest1 = getBiggestID(ID1); Logger.log("Biggest 1: " + Biggest1);
var Biggest2 = getBiggestID(ID2); Logger.log("Biggest 2: " + Biggest2);
if (Biggest1 !== Biggest2)
Browser.msgBox("Warning: there are IDs in one sheet that are not in the other sheet");
var Biggest;
if (Biggest1 > Biggest2) Biggest = Biggest1;
else Biggest = Biggest2;
Biggest++;
Empty1.setValue(Biggest);
Empty2.setValue(Biggest);
}
function getFirstEmpty(Header)
{
while (Header.getValue() !== "")
{
Header = Header.offset(1,0);
}
return Header;
}
function getBiggestID(Header)
{
var Sheet = Header.getSheet();
var LastRow = Sheet.getLastRow();
var Values = Sheet.getRange(Header.getRow(), Header.getColumn(), LastRow - Header.getRow() + 1).getValues();
var len = Values.length;
var MaxID = 1;
for (var i = 0; i < len; i++)
{
var val = Number(Values[i]);
if (!isNaN(val) && val > MaxID)
MaxID = val;
}
return MaxID;
}
function getRangeByName(spreadSheet, sheetName, rangeName)
{
Logger.log("Trying range: " + "'" + sheetName + "'!" + rangeName);
return spreadSheet.getRangeByName("'" + sheetName + "'!" + rangeName);
}

GAS - Ranged Cells Protection

I noticed there is quite a number of questions here regarding protection on cells in a spreadsheet.
But there seems to be no viable solution.
For example, column 'A' can only be edited by person1#email.com, and column 'B' can only be edited by person2#email.com.
There seems to be an issue tracker on google site since 2013...but Google has not come up with an API for it yet.
Does anyone have a workaround?
The code below only works for entire page protection..
sheet.setSheetProtection(permissions);
Use an onEdit() function that checks what user is editing the Sheet, then check what column is being edited. Have an object of user names, and what columns they can edit. If a user is not allowed to edit, undo the change.
You can only undo the change if you have a way of knowing what the last cell value was. There is no undo method in Apps Script, or other built in way to get the old value with Apps Script. But there is a way to configure the data to achieve a way to undo the edit.
Have a central sheet with all formulas referring to other sheets. In other words, the data that people view is a copy of the stored data in another sheet. Divide the data into sheets according to who can edit what. The code will write data to the correct sheet when a cell is edited.
Basically, you would have sheets that are the database where the data is stored. Those sheets could even be hidden, and of course they would be protected.
The viewing and editing would be done in a separate sheet from the sheets that are the official data storage.
So, the sheet that people are viewing and editing is the "User Interface"; it's the "Front End" of the "App". The sheets that are the official data storage are the "Back End".
function onEdit(e){
Logger.log("e.value: " + e.value);
Logger.log("e.range.getRow: " + e.range.getRow());
Logger.log("e.range.getColumn: " + e.range.getColumn());
var objWhoCanEditWhat = {"user1":"[A,B]", "user2":"[A]"};
//Get this user
var thisUserIs = Session.getActiveUser().getEmail();
Logger.log('thisUserIs: ' + thisUserIs);
Logger.log('Index of #: ' + thisUserIs.indexOf("#"));
thisUserIs = thisUserIs.substring(0, thisUserIs.indexOf("#"));
Logger.log('thisUserIs: ' + thisUserIs);
var whatColumnCanEdit = objWhoCanEditWhat[thisUserIs];
Logger.log('whatColumnCanEdit: ' + whatColumnCanEdit);
var editedColumn = e.range.getColumn();
var editedRow = e.range.getRow();
Logger.log('editedColumn: ' + editedColumn)
var ss = SpreadsheetApp.getActiveSpreadsheet();
//There must be a way to determine what sheet needs to be accessed, and that sheet name
//is set dynamically.
var objColumnEditedToSheetName = {"ColA":"Sheet6TY", "ColB":"SheetColumnB"};
var whatSheetToUse = objColumnEditedToSheetName[editedColumn];
if (whatColumnCanEdit != editedColumn) { //If the column this user can edit is not the same as
//the column that just was edited, then
//Undo the change with this code
//Retrieve the old official data from the data storage sheet
var sheet = ss.getSheetByName(whatSheetToUse);
} else {
//If the user is allowed to edit this column, write the data to the official data storage sheet
var sheet = ss.getSheetByName(whatSheetToUse);
};
//Always put a formula back into the cell that was just edited in order
//to show data from the back end data source
var viewSheet = ss.getSheetByName("SheetForEditingAndViewing");
//You know the row and column of the cell that was just edited, so use that to
//reference what cell to put the formula back into.
viewSheet.getRange(editedRow, editedColumn).setFormula("Sheet1!A3");
};

Moving rows to another google spreadsheet based on a condition

I'd like to know if its possible to move automatically rows to another Google spreadsheet based on a condition in editing (onEdit) the specific column entry that can be text, date, null or specific number.
I tried many times without being able to solve this puzzle.
Source (shared):
https://docs.google.com/spreadsheets/d/1Of4NUdvcxvCUWNSwpbkC4X8nqHpBetHCvyyiGqUPaJk/edit?usp=sharing
Destination (scripts) (shared):
https://docs.google.com/spreadsheets/d/1J7ChXoodQNg47LOrnp_GF-KLR1jKHxdDGmfAErVTP_U/edit?usp=sharing
Any help is appreciated. vagner
I'm getting an error on line 10 of your code:
This is what your current code looks like:
function onEdit(){
Logger.log("it ran!");
var ss = SpreadsheetApp.openById("1Of4NUdvcxvCUWNSwpbkC4X8nqHpBetHCvyyiGqUPaJk").getActiveSheet();
var ssd = SpreadsheetApp.openById("1J7ChXoodQNg47LOrnp_GF-KLR1jKHxdDGmfAErVTP_U").getActiveSheet();
Logger.log("ss: " + ss);
Logger.log("ssd: " + ssd);
var sheet1 = ss.getSheetByName('Source');
var sheet2 = ssd.getSheetByName('Destination');
Logger.log("sheet1: " + sheet1);
Logger.log("sheet2: " + sheet2);
There is a problem with these two lines:
var ss = SpreadsheetApp.openById("1Of4NUdvcxvCUWNSwpbkC4X8nqHpBetHCvyyiGqUPaJk").getActiveSheet();
var ssd = SpreadsheetApp.openById("1J7ChXoodQNg47LOrnp_GF-KLR1jKHxdDGmfAErVTP_U").getActiveSheet();
You should remove .getActiveSheet().
var ss = SpreadsheetApp.openById("1Of4NUdvcxvCUWNSwpbkC4X8nqHpBetHCvyyiGqUPaJk");
var ssd = SpreadsheetApp.openById("1J7ChXoodQNg47LOrnp_GF-KLR1jKHxdDGmfAErVTP_U");
That error was not showing up until I ran the code from inside of the code editor. And I needed to authorize some things for it to run for the first time.
I ran it in Debug mode.
When you chain the .getActiveSheet() method on the end, it returns the SHEET class, NOT the SPREADSHEET class. There are hierarchies of classes. The SHEET class is a lower level under the SPREADSHEET class. So, you were trying to use a method for the SPREADSHEET class, on a variable that contained a SHEET return type.