function dailyprofit() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Matt");
var profit = SpreadsheetApp.getActiveSheet().getRange('O2').getValue();
sheet.appendRow([,,,profit ]);
}
Hello, i'm attempting to use appendrow to put my variable into the last blank cell of row D, however appendRow does the entre row rather than just column D.
i would like the "profit" to be appended to row 362 rather than row 363 -> see example here
Thanks!
You can use this sample code to get the last row of Column D:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Matt");
var profit = SpreadsheetApp.getActiveSheet().getRange('O2').getValue();
var colValues = sheet.getRange("D1:D").getValues();
var count = colValues.filter(String).length
sheet.getRange(count+1,4).setValue(profit);
What it does?
Get all the column D values using sheet.getRange("D1:D").getValues()
Filter the array with string values and get its length/count. Empty cells will not be counted.
Increment the column D count by 1 and use Sheet.getRange(row,column) to get the cell below the non-empty cell in Column D. Use Range.setValue(value) to set the cell value.
Sample Output:
NOTE:
This will only work assuming you don't have an empty row in Column D.
If you have empty rows in your Column D, you might need to add few more offsets when incrementing the count.
Example:
I have 2 empty header rows (rows 1 and 2). Therefore, the offset of row count should be +3.
Sample Code:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Matt");
var profit = SpreadsheetApp.getActiveSheet().getRange('O2').getValue();
var colValues = sheet.getRange("D1:D").getValues();
var count = colValues.filter(String).length
sheet.getRange(count+3,4).setValue(profit);
Related
function DYNAMIC(){
var s = SpreadsheetApp.getActiveSpreadsheet(), ss = s.getSheetByName("Snippet Gen"),
dd = s.getSheetByName("dv snip"), column = 1, lastc = dd.getLastColumn(),
lastr = dd.getLastRow(), time = ss.getRange(2,1), name = ss.getRange(4,1),
time_v = time.getValue(), tp = dd.getRange(1,1,1,lastc),
nm = dd.getRange(2,column,lastr,1), match = dd.getRange(1,column).getValue();
var rule_tp = SpreadsheetApp.newDataValidation().requireValueInRange(tp,false).build();
time.setDataValidation(rule_tp);
for(; column < lastc; column++){
if(match = time_v){
var rule_nm = SpreadsheetApp.newDataValidation().requireValueInRange(nm,false).build();
name.setDataValidation(rule_nm);
}
}
}
Sheet 1: Snippet Gen
Sheet 2: dv snip
The result is the correct DV in A2 but a continuous Loading… DV in A4. And then when I go into the DV panel, the range is set as 'dv snip'!$A$2:$A$8 which is an invalid range. How do I set the range correctly?
if(match = time_v){ is an assignment not a comparison try this instead if(match == time_v){
You're most probably getting an invalid range because of this method:
nm = dd.getRange(2,column,lastr,1);
Please notice that the method getRange(row, column, numRows, numColumns) takes the number of rows as the third parameter, not the index of the last row in the range.
Because of this, here you are getting a range that:
Starts at row 2.
Its number of rows equals the index of the last row.
With these settings, the last row in this range doesn't exist. Therefore, you get an invalid range.
To fix this, you would have to substract the first row index to the third parameter in the method. One option would define the parameters and the method in this way:
var firstRow = 2;
var column = 1;
var numRows = dd.getLastRow() - firstRow + 1;
var numCols = dd.getLastColumn() - column + 1;
var nm = dd.getRange(firstRow, column, numRows, numCols);
Also, as Cooper said, you should use a comparison operator, not an assignment one in here:
if(match == time_v){
Reference:
getRange(row, column, numRows, numColumns)
Comparison operator
I hope this is of any help.
so as the title says I would like to find the empty or undefined cells in a row while iterating row until my lastrow. But it says "TypeError: Cannot read property "0" from undefined." Since it cant read undefined values and check it. You can see my code below. Thanks!
for (var row = startRow; row <= endRow; row++) {
var rangeA = "A" + row;
var rangeB = "H" + row;
var range = rangeA + ":" + rangeB;
var values = sheet1.getRange(range).getValues(); // get all data in one call
for ( var ct = 0; ct <= 7; ct++) {
if (values[ct][0]) = "")
runloop = false;
}
Cause:
Arrays are indexed by rows first and then columns. For example, A1:H1 contains 1 row and 8 columns or 1 inner array and 8 elements in that 1 inner array[[A1,B1,C1,D1,E1,F1,G1,H1]]. Therefore, values[1] will be undefined( since there's only 1 inner array whose index is 0). The script is looping through inner array instead of looping through elements of the inner array.
Solution:
Loop through the elements instead
Snippet:
if (values[0][ct] === "")
I have a script to move a row of data in an employee schedule spreadsheet (thanks to help from the Sheets reddit) it is working but has stopped finding one part of the data.
Spreadsheet here: https://docs.google.com/spreadsheets/d/10yLJ_NyFasGhlRt2LsXO2CC804Zf5JLvwUisgytQOhM/edit?usp=sharing
Once the Finished column 63 is set to "YES" it copies the data (only from the required columns), locates the employee's name based on whose week is marked "x" and moves them to the Finished Sheet.
The code used to work fully but now it isn't finding "x" or grabbing the employee's name.
I've had to update the column numbers in the script a few times as we've gotten more employees, it's possible I've broken it doing that.
(Any blank columns do have data in my real spreadsheet I've just left them blank here as it's not relevant to the script)
Would really appreciate any advice! Thank you!
[Full code in spreadsheet]
if (ecol == 63 && ssh.getName() == 'SCHEDULE' && rng.getValue() == 'YES') { //if Schedule!63 is YES
var data = []; //output data
var rowN = rng.getRow();
var rowV = ssh.getRange(rowN,1,1,63).getDisplayValues();
var row = rowV[0]; //get edited row
var colX = row.indexOf('x')+1; //find X
var offset = colX - ((colX-2) % 5 ) // offset to the first column
var emp = ssh.getRange(1,offset).getValue(); //get employee name
var dd = Utilities.formatDate(new Date(), "GMT+10", "dd/MM/yyyy") //generate date finished
data.push(row[1],row[2],row[3],dd,row[5],emp); //get row
dsh.appendRow(data); //move row
ssh.deleteRow(e.range.rowStart); //delete from schedule
}
}
I believe this var offset = colX - ((colX-2) % 5 ) // offset to the first column
should be this var offset = colX - ((colX+2) % 5 ) // offset to the first column
This is what's causing you to not find employees because the employees are in a merge group of cells which always puts it's value in the left most cell for horizontal merging.
I have a google spreadsheet that is populated with end of day portfolio data in my 'portfolio history' sheet, so I require to delete rows where there is duplicate data in column B & C while keeping the first row with the oldest data.(eg duplicate data '123' in column B row 19,20,21 & '4567' column C row 19,20,21. I only require first entry in this case for row 19,rows 20, 21 to be deleted).The rows need to be checked sequentially for duplicates in column B & C. How would I do this? Thanks!!!
Image https://photos.app.goo.gl/7Ufowk4r7K9Gdpsw1
Try this:
function removeDupesInBAndC(){
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('portfolio history');
var rg=sh.getDataRange();
var vA=rg.getValues();
var dupesA=[];
var delA=[];
for(var i=0;i<vA.length;i++){
var s=vA[i][1].toString() + vA[i][2].toString();
var idx=dupesA.indexOf(s);
if(idx>-1){
delA.push(idx);
}else{
dupesA.push(s);
}
}
for(var i=delA.length-1;i>-1;i--){
sh.deleteRow(i+1);
}
}
I have an array of data that looks roughly like this:
header row | header row | header row | header row
project | date | LastName, FName | hours
project | date | LastName, FName | hours
project | date | LastName, FName | hours
header row | header row | header row | header row
project | date | LastName, FName | hours
project | date | LastName, FName | hours
project | date | LastName, FName | hours
I'd like to strip the header rows out of the array. I thought I'd use ArrayLib.filterByDate to do this, thinking that any rows that did not contain a valid date in my timeframe would be stripped out.
Here's the code I tried:
function removeHeaders(projectRange){
var tmpProjectRange = [];
tmpProjectRange = ArrayLib.filterByDate(projectRange, 1, new Date(2013-01-01), new Date(2015-01-01))
return tmpProjectRange;
}
I get an error: "the selected column should only contain dates". So this method appears not to be an option.
Now, I'm trying to use ArrayLib.filterByText to compare column 2 to an array of valid data:
function removeHeaders(projectRange){
var tmpEmployeeRange = [];
var tmpEmployeeList = [];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var shtEmp = ss.getSheetByName("Employees");
var empLastRow = shtEmp.getLastRow();
var strRange = "A2:A" + empLastRow;
//should contain a list of all the employees:
tmpEmployeeList = shtEmp.getRange(strRange).getValues();
tmpEmployeeRange = ArrayLib.filterByText(projectRange, 2, tmpEmployeeList);
return tmpEmployeeRange;
}
But for some reason this is not working either. The only rows coming back in the tmpEmployeeRange are rows that have a name that does not have a comma (these rows have TBD rather than Last Name, First Name.) So I'm not really sure what is going on there, but I'm thinking that there has to be an easier way to do this. I guess I could just iterate through the entire thing and strip out the rows I don't want. Any other ideas?
If we assume that the logic of looking for rows with valid dates is correct, then it is very easy to iterate over the range and remove headers.
Here, I'm borrowing the isValidDate() function from Detecting an "invalid date" Date instance in JavaScript. I'm also keeping the first header row - you can get rid of that by removing the check for row == 0.
// Iterate over all rows, keeping the first header row and
// any row with a valid date in the second column.
function removeHeaders(projectRange){
var tmpProjectRange = [];
for (row in projectRange) {
if (row == 0 || isValidDate(projectRange[row][1])) {
tmpProjectRange.push(projectRange[row]);
}
}
return tmpProjectRange;
}
// From https://stackoverflow.com/questions/1353684
// Returns 'true' if variable d is a date object.
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}