I've spent hours trying to get this to work so any help is much appreciated I've got the code below copying from my main sheet to logs. However the code I'm trying to alter looks to column 10 for the sheet name. I'd like this just to default to the sheet logs any idea what needs changing to make this happen? Thanks in advance
function onEdit(e) {
// see Sheet event objects docs
// https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
var ss = e.source;
var s = ss.getActiveSheet();
var r = e.range;
// to let you modify where the action and move columns are in the form responses sheet
var actionCol = 9;
var nameCol = 10;
var target = SpreadsheetApp.openById('18L5-RGHBx41sMtvC1-7AoVCo6y3imvtELQFjkhPXtoY')
var targetsheet = target.getSheetByName('logs');
// Get the row and column of the active cell.
var rowIndex = r.getRowIndex();
var colIndex = r.getColumnIndex();
// Get the number of columns in the active sheet.
// -1 to drop our action/status column
var colNumber = s.getLastColumn()-1;
// if our action/status col is changed to yes do stuff
if (e.value == "Yes" && colIndex == actionCol) {
// get our target sheet name - in this example we are using the priority column
var targetSheet = s.getRange(rowIndex, nameCol).getValue();
// if the sheet exists do more stuff
if (ss.getSheetByName(targetSheet)) {
// set our target sheet and target range
var targetSheet = ss.getSheetByName(targetSheet);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
// get our source range/row
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
// new sheets says: 'Cannot cut from form data. Use copy instead.'
sourceRange.copyTo(targetRange);
// ..but we can still delete the row after
r.setValue("Logged")
// or you might want to keep but note move e.g. r.setValue("moved");
}
}
}
It looks like you are trying to get a sheet by it's name.
The following code will return the sheet named Logs.
var targetSheet = SpreadsheetApp.getActive().getSheetByName('Logs');
Google Apps Script Documentation: getSheetByName(name)
Related
I have a similar situation to the one described on this question: two worksheets, with input data coming into the Feed sheet using the importxml function and a Data sheet where new rows get copied thanks to a script set to run daily.
However, the current script is creating daily duplicates. As such, I would like to adapt the answer provided on the question above so that the script checks the IDs on column F and only copies the rows with new IDs.
How should I update the section below that creates a hash to one that looks for the IDs on column F instead? Also my rows are consistent, so is it correct to assume I can just remove the relevant code lines towards the end?
The sample Google Sheet is available here.
function appendUniqueRows() {
var ss = SpreadsheetApp.getActive();
var sourceSheet = ss.getSheetByName('Get Data');
var destSheet = ss.getSheetByName('Final Data');
var sourceData = sourceSheet.getDataRange().getValues();
var destData = destSheet.getDataRange().getValues();
// Check whether destination sheet is empty
if (destData.length === 1 && "" === destData[0].join('')) {
// Empty, so ignore the phantom row
destData = [];
}
// Generate hash for comparisons
var destHash = {};
destData.forEach(function(row) {
destHash[row.join('')] = true; // could be anything
});
// Concatentate source rows to dest rows if they satisfy a uniqueness filter
var mergedData = destData.concat(sourceData.filter(function (row) {
var hashedRow = row.join('');
if (!destHash.hasOwnProperty(hashedRow)) {
// This row is unique
destHash[hashedRow] = true; // Add to hash for future comparisons
return true; // filter -> true
}
return false; // not unique, filter -> false
}));
// Check whether two data sets were the same width
var sourceWidth = (sourceData.length > 0) ? sourceData[0].length : 0;
var destWidth = (destData.length > 0) ? destData[0].length : 0;
if (sourceWidth !== destWidth) {
// Pad out all columns for the new row
var mergedWidth = Math.max(sourceWidth,destWidth);
for (var row=0; row<mergedData.length; row++) {
for (var col=mergedData[row].length; col<mergedWidth; col++)
mergedData[row].push('');
}
}
// Write merged data to destination sheet
destSheet.getRange(1, 1, mergedData.length, mergedData[0].length)
.setValues(mergedData);
}
I'm a novice in this world of Google Apps scripts, so do please let me know if I'm missing any crucial information. Thanks in advance for the help.
You want to copy the values from "Feed" sheet to "Data" sheet.
When the values are copied, you want to copy only new values which are not included in "Data" sheet.
You want to choose the new values using the values of column "F".
If my understanding for your question is correct, how about this modification? In this modification, I modified the script in your shared spreadsheet.
Modification points:
In your script, all values of "Feed" sheet are copied to "Data" sheet. So in order to choose only new values, I used the following flow.
Retrieve the values from column "F". This is used for choosing the new values.
Retrieve the new values using the values from column "F".
Put the new values to "Data" sheet.
The script which reflected above flow is as follows.
Modified script:
From:
This is your script in the shared spreadsheet. Please modify this script to below one.
function Copy() {
var sss = SpreadsheetApp.openById('#####'); // this is your Spreadsheet key
var ss = sss.getSheetByName('Feed'); // this is the name of your source Sheet tab
var range = ss.getRange('A3:H52'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('#####'); //replace with destination ID
var ts = tss.getSheetByName('Data'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+1, 1,50,8).setValues(data);// 49 value refers to number of rows, 8 to columns
}
To:
function Copy() {
var sss = SpreadsheetApp.openById('#####'); // this is your Spreadsheet key
var ss = sss.getSheetByName('Feed'); // this is the name of your source Sheet tab
var range = ss.getRange('A3:H52'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('#####'); //replace with destination ID
var ts = tss.getSheetByName('Data'); //replace with destination Sheet tab name
// Below script was added.
var values = ts.getRange("F3:F").getValues().filter(String);
var copiedValues = data.filter(function(e) {return !values.some(function(f){return f[0] == e[5]}) && e.filter(String).length > 0});
ts.getRange(ts.getLastRow() + 1, 1, copiedValues.length, copiedValues[0].length).setValues(copiedValues);
}
I have a script to move a Google Sheets row from one sheet to another based on the value of a cell. What I'm now trying to accomplish is cherry picking column placement.
For example 'Client' in Column one gets moved from Leads to Opportunities in the corresponding column one, and 'Client Phone' in Column Two gets moved from leads to column five in opportunities, and 'Source' in column three just gets skipped all together, then repeat with following columns.
Any thoughts on how to achieve this? Thanks in advance!
Here is the code I have for moving rows.
function onEdit() {
// moves a row from a sheet to another when a magic value is entered in a column
var sheetNameToWatch = "Leads";
var columnNumberToWatch = 9;
var valueToWatch = "Opportunity";
var sheetNameToMoveTheRowTo = "Opportunities";
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());
}
}
An "object literal" can be used to make user settings that will determine the source and destination.
Example:
function onEdit() {
var mySettings,thisSheet;//Define variables without assigning a value
// USER INPUT
mySettings = {//make settings here
"targetSheetOne":{//First sheet to get data
"columnToColumnMap":{//source column to be put in target column
"column1":"column5",//source column1 will be copied to target column5
"column2":"column2",
"column3":"column3"
}
}
}
// END OF USER INPUT
for (key1 in mySettings) {//Loop through all target sheets in settings
thisSheet = SpreadsheetApp.getSheetByName(key1);
innerObject = mySettings[key1];
for (key2 in innerObject) {
//Write column data to correct column
}
}
}
Any help is greatly appreciated.
I am trying to get form responses to move over to another sheet if cell in row 5 is greater than 0. The code I am using below moves it over but adds it under the last cell that has a formula in it. Is there a modified version of this code that i can tell it to ignore formula's in cell. Also only copy over rows A:E. Thanks
function moveToAppropriateSheet(e) {
// assumes source data in sheet named Form Responses 1
// target sheet of move to named TR Requested
// test column with yes/no is col 11 or K
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Query');
var r = s.getRange(s.getLastRow(),1,1,20);
var data = r.getValues();
if(data[0][4] >0) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Pending");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
targetSheet.getRange(targetSheet.getLastRow()+1,1,1,20).setValues(data);
s.deleteRow(row);
}
};
Edited in light of new information:
You want to copy only the first 5 columns of the row you copy in "Query" to the sheet "Pending".
You already have entries in "Pending", in columns F, G, H, ... You wish to add your copied row under the last entry in columns A:E
I've also assumed for simplicity's sake that you always copy 5 columns so I can check only column A to find the last row (in the subset A:E).
I also note that this is essentially a duplicate of this answer by Mogsdad.
If my assumptions are correct, then:
function moveToAppropriateSheet(e) {
// assumes source data in sheet named Form Responses 1
// target sheet of move to named TR Requested
// test column with yes/no is col 11 or K
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Query');
var r = s.getRange(s.getLastRow(),1,1,5); // Change 20 to 5 to copy only cols A:E
var data = r.getValues();
var targetSheet = ss.getSheetByName("Pending");
var lastRowIgnoringFormulae = 0;
var targetSpace = targetSheet.getRange("A:A").getValues();
var lastRow = targetSpace.filter(String).length;
if(data[0][4] >0) {
var row = r.getRow();
var numColumns = s.getLastColumn();
targetSheet.getRange(lastRow+1,1,1,5).setValues(data); // +1 to convert into R1C1 notation
s.deleteRow(row);
}
};
I hope I've helped.
I have a sheet that will update based on new articles in an RSS feed using importfeed() and the URLs are analyzed with importxml(). Problem is the data is always changing and I would like to archive old data from the importfeed() function. I'd just like to move the most updated data from one sheet to another without overwriting anything.
Here is the sample code from: https://stackoverflow.com/users/650206/jeremy:
function myFunction() {
// Get Spreadsheets
var source = SpreadsheetApp.openById("spreadsheetKeySource");
var target = SpreadsheetApp.openById("spreadsheetKeyTarget");
// Set Sheets
var source_sheet = source.getSheetByName("Sheet1");
var target_sheet = target.getSheetByName("Sheet1");
// Get target last row
var last_row = target_sheet.getLastRow();
// Set Ranges
var source_range = source_sheet.getRange("A1:B1");
var target_range = target_sheet.getRange("A"+(last_row+1)+":B"+(last_row+1));
// Fetch values
var values = source_range.getValues();
// Save to spreadsheet
target_range.setValues(values);
}
Problem with the above code is it only selects one row when I need it to select an entire range (e.g. A1:G55) and paste that data below the old data in another sheet.
Any help would be much appreciated!
EDIT
The error I'm getting when I change:
var source_range = source_sheet.getRange("A1:B1");
var target_range = target_sheet.getRange("A"+(last_row+1)+":B"+(last_row+1));
to:
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1));
is "Incorrect range height, was 5 but should be 1 (line 21, file "Code")"
which is this piece of code:
target_range.setValues(values);
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+1));
The lines above attempt to copy 25 rows of data and paste that into one row. I'm surprised that the error message says "was 5 but should be 1". I'd have expected it to say "was 25 but should be 1".
Try this instead:
var source_range = source_sheet.getRange("A1:G25");
var target_range = target_sheet.getRange("A"+(last_row+1)+":G"+(last_row+25));
I have a google form which populates a google spreadsheet (source sheet). I located and customized a script to pull certain columns -in their entirety- from the source sheet into a new tab/sheet. Apparently there has to be the same number of rows in both sheets for the script to run properly. If not, it turns back an error. Every time a new form is submitted, a row is added to the source sheet, putting the two sheets out of sync and breaking the script.
I'd like help figuring out what function I need to add to the existing script (or what changes I can make to it) so when a new row appears in the source sheet (because a form has been submitted), a blank row appears in the target sheet.
Do I need to tweak my script or add a new function?
function importFunction(a) {
var ss = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var sourceSheet = ss.getSheets()[0];
var ss2 = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var targetSheet = ss2.getSheets()[1];
var values1 = sourceSheet.setActiveSelection("C:C").getValues();
var values2 = sourceSheet.setActiveSelection("AD:AD").getValues();
var values3 = sourceSheet.setActiveSelection("D:E").getValues();
var values4 = sourceSheet.setActiveSelection("AE:AE").getValues();
var values5 = sourceSheet.setActiveSelection("F:H").getValues();
var values6 = sourceSheet.setActiveSelection("N:U").getValues();
targetSheet.setActiveSelection("A:A").setValues(values1);
targetSheet.setActiveSelection("B:B").setValues(values2);
targetSheet.setActiveSelection("C:D").setValues(values3);
targetSheet.setActiveSelection("E:E").setValues(values4);
targetSheet.setActiveSelection("F:H").setValues(values5);
targetSheet.setActiveSelection("I:P").setValues(values6);
}
Per the suggestion below, I tried to change script to the following, but I get an error - Cannot find method appendRow(). How do I fix that?
function importFunction(a) {
var ss = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var sourceSheet = ss.getSheets()[0];
var ss2 = SpreadsheetApp.openById("0ApTaY3v27-UqdElwZTBvanNpaC1UckpxaTJRZS1XNWc");
var targetSheet = ss2.getSheets()[1];
var targetMax = targetSheet.getMaxRows();
var values1 = sourceSheet.setActiveSelection("C:C").getValues();
var values2 = sourceSheet.setActiveSelection("AD:AD").getValues();
var values3 = sourceSheet.setActiveSelection("D:E").getValues();
var values4 = sourceSheet.setActiveSelection("AE:AE").getValues();
var values5 = sourceSheet.setActiveSelection("F:H").getValues();
var values6 = sourceSheet.setActiveSelection("N:U").getValues();
if(targetMax == values1.length) {
targetSheet.setActiveSelection("A:A").setValues(values1);
targetSheet.setActiveSelection("B:B").setValues(values2);
targetSheet.setActiveSelection("C:D").setValues(values3);
targetSheet.setActiveSelection("E:E").setValues(values4);
targetSheet.setActiveSelection("F:H").setValues(values5);
targetSheet.setActiveSelection("I:P").setValues(values6);
}
else
targetSheet.appendRow();
}
You could simply check the number of available rows in sheet SS2 before writing the values using getMaxRows() and compare it to the length of your data arrays value1.length, then, depending on this comparison add the rows you need using appendRow() eventually in a for next loop.
EDIT : following your EDIT, I tested a bit further and it appears that appendRow() doesn't work as I thought, it appends Rows at the begining of an empty sheet... so I tried this :
if(targetMax < values1.length) {
var RowsToAdd = values1.length-targetMax
for(nn=0;nn<RowsToAdd;++nn){targetSheet.insertRowAfter(targetMax)}
}
Just place it right after var value6=...
sorry for this little error ;-)