I'm trying to post an array into column P daily. Because it's posting daily, I'd like it to also grab the last row.
I'm pulling from another workbook but don't know how to get the paste to work.
Function () {
var toCopy = [copies data from spreadsheet 1]
/* trying to paste into Aggregate tab in spreadsheet 2*/
var ss2=SpreadsheetApp.openById(‘spreadsheet 2’);
var tsh2=ss2.getSheetByName('Aggregate');
var tsh2.getLastRow(???
}
How do I paste var toCopy into column P? The array is 15 columns wide.
You want to append the values to the next row of the last row of column "P" in the sheet of "Aggregate".
The values are 2 dimensional array which has 600 rows and 15 columns.
The number of rows is changed every run.
The number of columns is not changed.
After the values are put, you want to retrieve the last row number.
I could understand like above. If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Flow:
Retrieve the last row number of the column "P".
From your question, I'm not sure whether the last row of the column "P" is the last row of the sheet. So the last row is checked for only column "P".
Append "toCopy" to the next row of the last row of column "P".
Retrieve the current last row number.
Modified script:
Please set the values of toCopy and the Spreadsheet ID.
function myFunction() {
var toCopy = [copies data from spreadsheet 1]
var ss = SpreadsheetApp.openById('###');
var sheet = ss.getSheetByName('Aggregate');
// Retrieve the last row of the column "P".
var lastRowOfColP = 0;
var valuesOfColP = sheet.getRange("P1:P").getValues();
for (var i = valuesOfColP.length - 1; i >= 0; i--) {
if (valuesOfColP[i][0]) {
lastRowOfColP = i + 1;
break;
}
}
// Put "toCopy" to the next row of the last row of column "P".
sheet.getRange(lastRowOfColP + 1, 16, toCopy.length, toCopy[0].length).setValues(toCopy);
// Retrieve the current last row number.
var currentLastRow = lastRowOfColP + toCopy.length;
Logger.log(currentLastRow)
}
This modified script supposes that toCopy is 2 dimensional array.
References:
setValues(values)
getRange(a1Notation)
getRange(row, column, numRows, numColumns)
Looks like Set a range's values is what you're after.
function () {
var values = [
// Copied data from spreadsheet 1
]
// Paste into Aggregate tab in spreadsheet 2
var ss2 = SpreadsheetApp.openById(‘spreadsheet 2’);
var sheet2 = ss2.getSheetByName('Aggregate');
var range = sheet2.getRange('P1:P15');
range.setValues(values);
// Grab last row
var lastRow = sheet2.getLastRow();
}
PS: Watch out for the formatting in your code. It looks like you might not be using a proper text editor. Your formatting made function be Function and the quotations 'spreadsheet 2' become ‘spreadsheet 2’. I use VS Code and Vim, for example.
Related
I have written this code with the purpose of cycling through a list of names. When the code finds the waitingName in the list it should replace the row that the name appears with a row of info. When I attempt to run this code it pastes the row of information at the top of the screen, not after row 17 where the list of names begins.
var waitingName = waitingSheet.getRange(6,13).getValue();
var edittedInfo = waitingSheet.getRange(6,3,1,12).getValues();
var waitingListNames = waitingSheet.getRange(17, 11, 105,1).getValues().flat();
var index = waitingListNames.indexOf(waitingName);
if (index > -1) {
waitingSheet.getRange(index + 1,1,1,12).setValues(edittedInfo);
}
Solution:
index takes values >=0, therefore index+1 takes values >=1. This
is why your code starts pasting from the first row.
If you want to paste the information after 17th row (including 17th row) then modify this:
waitingSheet.getRange(index + 1,1,1,12).setValues(edittedInfo);
to this:
waitingSheet.getRange(index + 17,1,edittedInfo.length,edittedInfo[0].length).setValues(edittedInfo);
since index can take values >=0, index + 17 takes values >=17 which is the desired starting row point.
Also, it is recommended to use .length instead, in case you want to change the size of edittedInfo down the road.
References:
getRange(row, column, numRows, numColumns)
length()
I am trying to write a script for google sheets which returns the date in the next cell when the user enters 'y' in the current cell. I have a script which does this already, but the problem with my script is that the columns which it is evaluating is based on the column index, which means if our data set ever grows then these columns always have to stay in the same index which is creating a lot of organizational issues.
My question is..
Is it possible to look for the column header title rather than the column index in my code, and if so, what changes would I need to make?
function onEdit(e) {
if ([19].indexOf(e.range.columnStart) == -1 || ['y', 'Y'].indexOf(e.value) == -1) return;
e.range.offset(0, 1)
.setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"))
}
This code currently looks at column index 19 and when either 'y' or 'Y' is entered into a cell in column index 19 it then outputs the date in the next cell in column 20.
How can I change the code to look for where the column header = 'Replied?' rather than index?
Goal:
If the following criteria is met:
Value is written into column 19 (S).
Header of column 19 (S) is 'Replied?'.
Value written is either 'Y' or 'y'.
Then write a date into the adjacent cell.
Code:
function onEdit(e) {
var sh = e.source.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
var value = e.value.toUpperCase();
var header = sh.getRange(1, col).getValue();
if (col === 19 && value === 'Y' && header === 'Replied?') {
sh.getRange(row, 20).setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"))
}
}
Explanation:
I've based everything on the event objects passed to your onEdit trigger. For var value I have used toUpperCase() so that we don't have to check for either 'Y' OR 'y', only 'Y' alone. Also, instead of using range.offset I have just specified column 20 specifically in the getRange().setValue().
References:
Event Objects
String.toUpperCase()
One possible way to do this is to name the column/ cell in google sheets. See this website on how to.
Basically:
Open a spreadsheet in Google Sheets.
Select the cells you want to name.
Click Data and then Named ranges. A menu will open on the right.
Type the range name you want.
To change the range, click Spreadsheet Grid.
Select a range in the spreadsheet or type the new range into the text box, then - click Ok.
Click Done.
You can then refer to that named cell in google scripts by creating a custom function
function myGetRangeByName(n) { // just a wrapper
return SpreadsheetApp.getActiveSpreadsheet().getRangeByName(n).getA1Notation();
}
Then, in a cell on the spreadsheet:
myGetRangeByName("Names")
I'd do this.
function onEdit(e) {
var editedColumn = e.range.columnStart;
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("This");//you only want onedits to the specific page
var data = ss.getDataRange().getValues();
var header = data[0][editedColumn];
if (header != "Replied") return;
if(e.value.toLowerCase() == "y"){
e.range.offset(0, 1)
.setValue(Utilities.formatDate(new Date(), "GMT-5", "MM-dd-yyyy"));}
}
You could also consider using a checkbox, that might be faster for your users.
I have a script that deletes empty rows at the bottom of about 15 sheets every night after work is done on the spreadsheet during the day. I run this because empty rows are left at the bottom very often (but not always) and this helps to clean it up automatically without me having to worry about it. It works perfectly fine when empty rows are left at the bottom, but when there aren't and the sheet is full of data all the way down, it gives me an error and won't continue to the next sheet. I assume it has to do with the
lastRow + 1
but I don't know how to change it to still run properly. My main question is, how can I still run this code as normal (deleting empty rows on listed sheets), but if there aren't any empty rows, it just goes to the next sheet instead of throwing up an error?
// DELETE EMPTY ROWS AT BOTTOM
function RemoveEmptyRows() {
var ss = SpreadsheetApp.openById('spreadsheetId');
var arrayOfSheetTabNames, i, L, sheet;
arrayOfSheetTabNames = [
"Sheet1",
"Sheet2",
"Sheet3",
"Sheet4",
"Sheet5",
"Sheet6",
"Sheet7",
"Sheet8",
"Sheet9",
"Sheet10",
"Sheet11",
"Sheet12",
"Sheet13",
"Sheet14",
"Sheet15"
]
L = arrayOfSheetTabNames.length;
for (i = 0; i < L; i++) {
sheet = ss.getSheetByName(arrayOfSheetTabNames[i]);
var maxRows = sheet.getMaxRows();
var lastRow = sheet.getLastRow();
sheet.deleteRows(lastRow + 1, maxRows - lastRow);
}
};
Thank you for any help!
You want to delete all empty rows below the data range for 15 sheets.
There are several sheets which has no empty rows.
If my understanding is correct, how about this modification? In your situation, for example, how about comparing lastRow with maxRows?
Modified script:
Please modify as follows and try again.
From:
sheet.deleteRows(lastRow + 1, maxRows - lastRow);
To:
if (lastRow < maxRows) {
sheet.deleteRows(lastRow + 1, maxRows - lastRow);
}
References:
getMaxRows()
getLastRow()
If I misunderstood your question and this was not the result you want, I apologize.
I want to select the range of 2 columns till the last row with a value. Now I use this code:
var test = declSheet.getRange('Potjes!A:B');
Form this sheet:
The result I get is this:
How can I select till the last row with value?
You can use Sheet.getDataRange function which:
Returns a Range corresponding to the dimensions in which data is
present.
It seems like you are only interested in column A and B so:
// var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// var sheet = spreadsheet.getActiveSheet();
var dataRange = sheet.getDataRange();
var desiredRange = sheet.getRange("A1:B" + dataRange.getLastRow());
// desiredRange will consist of A1:B5 in OP example
//create a copy for next week below in cell A31
function createWeek(){
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("Sheet1!A4:AN30");
source.copyTo (ss.getRange("Sheet1!A31"));
var numRows = SpreadsheetApp.getActiveSpreadsheet().getLastRow() + 1;
}
I want to copy the range A4:A30 into the next empty row (in this case, row 31) BUT I'd like to do it every week so I need this row to be variable, because the next week the row will change. I could count the rows (numRows) but I don't know how to change the destination range so it can take into consideration the changing row (Sheet1!A???). THANKS!!
Use .getLastRow() + 1 .getLastRow() returns the last row containing data then + 1 to get the next row which will be empty.