I would like to do this in G column : If Cell 'G8' is Blank Then (=K8) for example. My difficulty is to make reference of same row in K of empty cell in G.
I've tryed to adapt this script but I get a shift at some point and I don't know why.
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange()
var source = sheet.getRange('G1:G13').getDisplayValues()
var index = []
for (var i = 1; i<source.length; i++){
if (source[i][0] == ""){
index.push(i+1)
}
}
index.push(range.getLastRow()+1)
Logger.log(index)
for(var i = 0;i<index.length-1;i++){
var rangetomodify = sheet.getRange(index[i],7,1,1)
var l = index[i+1]-index[i]-1
rangetomodify.setFormulaR1C1("=R["+l+"]C[4]")
}
}
As another approach, how about the following modification?
Modification points:
About I've tryed to adapt this script but I get a shift at some point and I don't know why., in your script, "=R[" + l + "]C[4]" is used with var l = index[i + 1] - index[i] - 1. In this case, when l is not 0, the other row is used. I thought that this might be the reason for your issue. In your script, I think that it is not required to use var l = index[i + 1] - index[i] - 1. When your script is simply modified, it becomes as follows.
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange();
var source = sheet.getRange('G1:G13').getDisplayValues();
var index = [];
for (var i = 1; i < source.length; i++) {
if (source[i][0] == "") {
index.push(i + 1);
}
}
index.push(range.getLastRow() + 1);
for (var i = 0; i < index.length - 1; i++) {
var rangetomodify = sheet.getRange(index[i], 7, 1, 1);
rangetomodify.setFormulaR1C1("=R[0]C[4]");
}
}
But, in this case, getRange and setFormulaR1C1 are used in a loop. In this case, the process cost becomes high.
When your script is modified by reducing the process cost, how about the following modification?
Modified script:
function updatewithformula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var source = sheet.getRange('G2:G13').getDisplayValues();
var ranges = source.reduce((ar, [g], i) => {
if (!g) ar.push(`G${i + 2}`);
return ar;
}, []);
sheet.getRangeList(ranges).setFormulaR1C1("=R[0]C[4]");
}
By RangeList, the process cost can be reduced a little.
References:
reduce()
getRangeList(a1Notations)
setFormulaR1C1(formula) of Class RangeList
There are better, easy and short methods to do it, I have used offset here.
The below works for me
function updatewithformula(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet 1');
var range = sheet.getDataRange()
var source = sheet.getRange('G1:G13').getValues();
Logger.log(source);
var index = [];
for (var i in source){
if(source[i][0] == ""){
var j = +i;
index.push(("G"+(j+1)));
}
}
for (var i in index){
var TEMP = sheet.getRange(index[i]);
var TEMP1 = TEMP.offset(0,4).getA1Notation();
const formula = `=${TEMP1}`;
TEMP.setFormula(formula);
}
}
References - OFFSET
Getting an TypeError: Cannot read property '0' of undefined (line 35)
I am trying to find a cell value in google sheets and then return the cell value into another cell.
I dont get why I am getting a TypeError and I have tried all forms of toString methods or what not.
Please help
function hiearchyRoleGenerator() {
Logger.log("Setting spreasheets up")
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var generatorSheet = sheets[0];
var primeSheet = sheets[1];
var ecsSheet = sheets[2];
var cloudSalesSheet = sheets[3];
var salesDevSheet = sheets[4];
Logger.log("Setting cells up")
var businessUnit = generatorSheet.getRange("A2").getValue();
var startPoint = generatorSheet.getRange("B2").getValue();
var endPoint = generatorSheet.getRange("C2").getValue();
var separator = generatorSheet.getRange("D2");
var concat = generatorSheet.getRange("E2");
var target = startPoint.toString();
Logger.log(target)
//Logger.log("Finding Start Point")
//Logger.log(startPointResult)
//Logger.log(String(startPointResult))
if (businessUnit == "Prime") {
var lastRow = primeSheet.getLastRow();
var data = primeSheet.getRange(1,1,lastRow,7).getValues();
var dataResult = []
var i,j;
for (var i = 0; i <= lastRow ;i++) {
//Logger.log(values[i][0])
for (var j = 0; j<7; j++){
//Logger.log(values[i][j])
if(data[i][j] == startPoint){ //[i] row [j] column ERROR IS HERE
dataResult.push(data[[i][j]]);
}
}
}
concat.setValue(dataResult);
}
}
Can you try something like this?
var range = sheet.getRange(1,1,lastRow,7);
var values = range.getValues();
for (var row in values) {
for (var col in values[row]) {
if(values[row][column] == startPoint){ //[i] row [j] column ERROR IS HERE
dataResult.push(values[row][column]);
}
}
Also row and Column are relative to range so may be using var i,j starting with 0 might be an issue. you might have to use 1 instead
I am trying to loop over a specific column and look for values. When a cell value = 0, I want to copy other columns in that row to another sheet.
function selectCopy() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Intake');
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Service Pending');
var sheet3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Service Complete');
var sheet4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('To Reissue');
var sheet5 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Discovery');
var lastRow1 = sheet1.getLastRow();
var lastRow2 = sheet2.getLastRow();
var lastRow3 = sheet3.getLastRow();
var lastRow4 = sheet4.getLastRow();
var lastRow5 = sheet5.getLastRow();
var startRow = 2;
var range = sheet2.getRange(2,1, lastRow1-startRow+1,1);
var numRows2 = range.getNumRows();
var case_number_values = range.getValues();
range = sheet2.getRange(2,2, lastRow1-startRow+1,1);
var name_values = range.getValues();
var range = sheet2.getRange(2,6, lastRow2-startRow+1,1);
var days_left_values = range.getValues();
var selection = sheet2.getDataRange();
range = sheet2.getRange(2,7, lastRow2-startRow+1,1);
var sent_to_server_values = range.getValues();
range = sheet2.getRange(2, 4, lastRow2-startRow+1,1);
var issue_date_values = range.getValues();
range = sheet2.getRange(2, 5, lastRow2-startRow+1,1);
var service_deadline_values = range.getValues();
range = sheet2.getRange(2,8, lastRow2-startRow+1,1);
var service_date_values = range.getValues();
for (var i=0; i<= numRows2-1; i++){
var days_left = days_left_values[i][0];
if (days_left === 0){
var case_number = case_number_values[i][0];
var name = plaintiff_name_values[i][0];
var service_date = service_date_values[i][0];
var issue_date = issue_date_values[i][0]
var service_deadline = service_deadline_values[i][0];
var sent_to_server = sent_to_server_values[i][0];
sheet4.getRange(lastRow4+1,1).setValue(case_number);
sheet4.getRange(lastRow4+1,2).setValue(name);
sheet4.getRange(lastRow4+1,4).setValue(service_deadline);
}
}
}
It is sort of working but it is only copying the last row that has a cell = 0. So If I have three rows in column 6, whos value = 0, I want to copy all three rows, this code is only copying the last row.
does this run insanely slow? you could gain a lot of time if you rewrote this a little bit. you really only need to read the data once and then write once per row.
function selectCopy() {
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Service Pending');
var sheet4 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('To Reissue');
}
var data = sheet2.getDataRange().getValues();
for (var i=1; i< data.length; i++){
var days_left = data[i][5];//column 6 is days left
if (days_left === 0){
var case_number = data[i][0];//column 1 is case number
var name = data[i][1];//column 2 is plaintiff names
var service_date = data[i][7];// column 8
var issue_date = data[i][3]//column 4
var service_deadline = data[i][4];//column 5 is deadlines
var sent_to_server = data[i][6];//column 7
sheet4.appendRow([case_number,name,"",service_deadline]);
}
}
When I run my (messy) script it seems to run one extra time than required. i.e. below the last row it creates a pdf and marks a cell as processed.
The second issue is that the URLs don't seem to line up correctly with the name that it should be.
I appreciate the code is very messy but I'm happy to explain the reasoning for any part if it doesn't make sense.
Thanks in advance for any help!
The spreadsheet can be found here:
https://docs.google.com/spreadsheets/d/1nq5RRcwAKk9sFm6jVypFT_qJWcOGxFDZRv6ZpB-QClw/edit#gid=1194576382
and the code that's not working as expected is:
var ss = SpreadsheetApp.getActiveSpreadsheet()
var rawData = "rawData"
var practicePivot = "practicePivot"
var querySheet = "querySheet"
var pdfSheet = "pdfSheet"
var contactList = "contactList"
function createPDF(){
var sourceSheet = ss.getSheetByName("querySheet")
var pdfList = ss.getSheetByName("practicePivot")
var contactList = ss.getSheetByName("contactList")
var sourceRow = sourceSheet.getLastRow()
var sourceColumn = sourceSheet.getLastColumn()
var sourceStartRow = 4 //skips the headers and only pulls query data
var sourceStartColumn = 1
var sourceRange = sourceSheet.getRange(sourceStartRow, sourceStartColumn, sourceRow, sourceColumn)
var sourceValues = sourceRange.getValues()
var pdfLastRow = pdfList.getLastRow()
var storePracticeName = sourceSheet.getRange("A2").getValues()
var newSpreadsheet = SpreadsheetApp.create("Summary of Patients for" +storePracticeName)
sourceSheet.copyTo(newSpreadsheet, {contentsOnly: true})
newSpreadsheet.getSheetByName("sheet1").activate()
newSpreadsheet.deleteActiveSheet()
var pdfURLtemp = DriveApp.getFileById(newSpreadsheet.getId()).getAs("application/pdf")
var pdf = DriveApp.createFile(pdfURLtemp)
var pdfURL = pdf.getUrl()
Logger.log(pdfURL)
return pdfURL
}
function createQuery()
{
//Duplication check
var pdfCreated = "pdfCreated";
var pdfEmailed = "pdfEmailed";
var sheet = ss.getSheetByName("practicePivot");
var startRow = 2;
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var dataRange = sheet.getRange(startRow, 1, lastRow, lastColumn) ;
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i)
{
var row = data[i];
var practiceName = row[0]
var pdfCheck = row[2]
var copySelection = sheet.getRange(startRow + i, 1)
var copyData = copySelection.getValues()
var copyLocation = ss.getSheetByName("querySheet")
var copyCell = copyLocation.getRange("A2")
if (pdfCheck != pdfCreated)
{
var pdfURL = createPDF()
copyCell.copyTo(copyData)
sheet.getRange(startRow + i, 4).setValue(pdfURL)
sheet.getRange(startRow + i, 3).setValue(pdfCreated)
SpreadsheetApp.flush()
}
}
}
Your start row is 2:
var startRow = 2;
Your loop is looping until the count of the last row. So if there were 10 rows, and the data starts in row 2, then you need the loop to run 9 times. But your loop is running 10 times.
So you need to adjust the stop for the loop.
var L = data.length - 1;//The number of rows in the data - not the sheet
for (var i = 0; i < L; ++i)
I've just started using Google Apps script to manage some sheets for a project i'm working on, I am new to Javascript so please go easy if there are any howlers in my code!.
We have and app called forms2mobile that captures data and drops it into a Google spreadsheet. It actually drops different data into different sheets depending on which part of the app you use.
I've hacked together a script that pulls all data from one sheet (source), and drops only certain columns into a second sheet (destination). It then deletes all rows from the source, and any blank rows from the destination.
The problem I have is with deleting blank rows from the destination. Typically the destination will have empty rows at the bottom, and the code I have will only delete empty rows within the range that contains data. So i'm always left with empty rows at the bottom.
The destination sheet will then be used as a data source for forms2mobile, which of course isn't happy with empty rows.
I've found the class getMaxRows() but i'm not sure how to implement it. If anyone could make any suggestions that would be great.
Cheers
Paul
function NEW_copyColumnNumbers( ) {
var spreadsheet_source = SpreadsheetApp.openById('1a89ZIUcy-8168D1damCV3Q9Ix0arQn9jGS6pgp');
var spreadsheet_target = SpreadsheetApp.openById('1GQiLt9utSH_6CV__oJwmcLOkI4E9iNIRPWU7Xr');
var range_input = spreadsheet_source.getRange("A2:CC407");
var range_output = spreadsheet_target.getRange("A"+(spreadsheet_target.getLastRow()+1));
var keep_columns = [66,66,10,11,12,13,14,23,26,31,69,71,74,75,80];
copyColumnNumbers(range_input, range_output, keep_columns);
clearEmptyRows();
clearSourceData();
}
function copyColumnNumbers( range_input, range_output, columns_keep_num ) {
// Create an array of arrays containing the values in the input range.
var range_values = range_input.getValues();
// Loop through each inner array.
for ( var i = 0, row_count = range_values.length; i < row_count; i++ ) {
// Loop through the indices to keep and use these indices to
// select values from the inner array.
for ( j = 0, col_keep_count = columns_keep_num.length; j < col_keep_count; j++ ) {
// Capture the value to keep
var keep_val = range_values[i][columns_keep_num[j]];
// Write the value to the output using the offset method of the output range argument.
range_output.offset(i,j).setValue(keep_val);
}
}
}
function clearEmptyRows() {
var ss = SpreadsheetApp.openById('1GQiLt9utSH_6CV__oJwmcLOkI4E9iNIRPWU7Xr');
var s = ss.getActiveSheet();
var values = s.getDataRange().getValues();
nextLine: for( var i = values.length-1; i >=0; i-- ) {
for( var j = 0; j < values[i].length; j++ )
if( values[i][j] != "" )
continue nextLine;
s.deleteRow(i+1);
}
//I iterate it backwards on purpose, so I do not have to calculate the indexes after a removal
}
function clearSourceData() {
var ss = SpreadsheetApp.openById('1a89ZIUcy-8168D1damCV3Q9Ix0arQn9jGS6pgp');
var s = ss.getActiveSheet();
var data = s.getDataRange().getValues();
for(var n =data.length+1 ; n<0 ; n--){
if(data[n][0]!=''){n++;break}
}
s.deleteRows(2, (s.getLastRow()-1));
}
This is how it works :
function removeEmptyRows(){
var sh = SpreadsheetApp.getActiveSheet();
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
Note : you can handle columns the same way if necessary using getMaxColumn(), getLastColumn() and deleteColumns(number, howMany)
EDIT
by the way, here is also another way to delete empty rows in a spreadsheet... if you combine both it will "clean" your sheet entirely !
function deleteEmptyRows(){
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues();
var targetData = new Array();
for(n=0;n<data.length;++n){
if(data[n].join().replace(/,/g,'')!=''){ targetData.push(data[n])};
Logger.log(data[n].join().replace(/,/g,''))
}
sh.getDataRange().clear();
sh.getRange(1,1,targetData.length,targetData[0].length).setValues(targetData);
}
Demo sheet in view only - make a copy to use
Script to removeEmptyRows and removeEmptyColumns in Google Sheets. It puts together everything Serge and apptailor mentioned previously. Here is a sample sheet with the script included File > Make a copy... to edit a copy of the sheet. Also a video that shows you how to use this sheet.
//Remove All Empty Columns in the Entire Workbook
function removeEmptyColumns() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxColumns = sheet.getMaxColumns();
var lastColumn = sheet.getLastColumn();
if (maxColumns-lastColumn != 0){
sheet.deleteColumns(lastColumn+1, maxColumns-lastColumn);
}
}
}
//Remove All Empty Rows in the Entire Workbook
function removeEmptyRows() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var maxRows = sheet.getMaxRows();
var lastRow = sheet.getLastRow();
if (maxRows-lastRow != 0){
sheet.deleteRows(lastRow+1, maxRows-lastRow);
}
}
}
Just a quick note, I added this "if" statement to keep Serge insas's code from throwing an error if there is no empty bottom row when you are trying to remove empty rows.
Place this if around the last line function removeEmptyRows() and it
will not throw an error:
if (maxRows-lastRow != 0){
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
Removing all empty lines (bottom-up)
before
after
function isEmptyRow(row){
for (var columnIndex = 0; columnIndex < row.length; columnIndex++){
var cell = row[columnIndex];
if (cell){
return false;
}
}
return true;
}
function removeEmptyLines(sheet){
var lastRowIndex = sheet.getLastRow();
var lastColumnIndex = sheet.getLastColumn();
var maxRowIndex = sheet.getMaxRows();
var range = sheet.getRange(1, 1, lastRowIndex, lastColumnIndex);
var data = range.getValues();
sheet.deleteRows(lastRowIndex+1, maxRowIndex-lastRowIndex);
for (var rowIndex = data.length - 1; rowIndex >= 0; rowIndex--){
var row = data[rowIndex];
if (isEmptyRow(row)){
sheet.deleteRow(rowIndex + 1);
}
}
}
function removeEmptyLinesFromAllSheets(){
SpreadsheetApp.getActive().getSheets().forEach(removeEmptyLines);
}
Removing only empty lines from below and above the data
before
after
function isEmptyRow(row){
for (var columnIndex = 0; columnIndex < row.length; columnIndex++){
var cell = row[columnIndex];
if (cell){
return false;
}
}
return true;
}
function getFirstNonBlankRowIndex(data){
for (var rowIndex = 0; rowIndex < data.length; rowIndex++){
var row = data[rowIndex];
if (!isEmptyRow(row)){
return rowIndex;
}
}
return 0;
}
function removePaddedEmptyLines(sheet){
var lastRowIndex = sheet.getLastRow();
var lastColumnIndex = sheet.getLastColumn();
var maxRowIndex = sheet.getMaxRows();
var range = sheet.getRange(1, 1, lastRowIndex, lastColumnIndex);
var data = range.getValues();
var firstRowIndex = getFirstNonBlankRowIndex(data);
sheet.deleteRows(lastRowIndex+1, maxRowIndex-lastRowIndex);
sheet.deleteRows(1, firstRowIndex);
}
function removePaddedEmptyLinesFromAllSheets(){
SpreadsheetApp.getActive().getSheets().forEach(removePaddedEmptyLines);
}
I have tried this piece of code and it works good, you may take a look and try it:
function DeleteBlankRows(){
var sh = SpreadsheetApp.getActiveSheet();
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
for (var Raw = 1; Raw < sh.getLastRow() ; Raw++)
{
if( sh.getRange('A'+Raw).getValue() == '')
{
sh.deleteRow(Raw) //deleteRows(lastRow+1, maxRows-lastRow);
}
}
This works perfectly for me.
function removeEmptyRows(){
var spreadsheet = SpreadsheetApp.openById("IDOFYOURSPREADSHEETFOUNDINURL");
var sh = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
var maxRows = sh.getMaxRows();
var lastRow = sh.getLastRow();
sh.deleteRows(lastRow+1, maxRows-lastRow);
}
This version allows you to specify top rows you don't want removed and also to ignore columns after ignoreAfterCol in case you don't want some columns considered when you are looking for blanks:
function removeEmptyLines(sheet,ignoreFirstRows,ignoreAfterCol){
sheet=ss.getSheetByName('Sheet12')
//get data and boundaries
var allData = sheet.getRange(1,1,sheet.getMaxRows(),ignoreAfterCol).getValues();
var sheetLength = allData.length;
while(allData[allData.length-1].toString().replace(/,/g,'')=='') allData.pop();
var lastPopulatedRow = allData.length;
//delete empty rows from end
var rowsToDeleteFromEnd = sheetLength - lastPopulatedRow;
if(rowsToDeleteFromEnd > 0) sheet.deleteRows(lastPopulatedRow+1,rowsToDeleteFromEnd);
//iterate through rows and delete blanks one by one
for(var i=lastPopulatedRow-1; i>ignoreFirstRows; i--){
if(allData[i].toString().replace(/,/g,'')=='') sheet.deleteRow(i+1);
}
}
this will help to delete exactly what you want:
Plus point:
you can check as many columns as you want to identify if a row is empty
this will also delete blank rows that contain formula
improve performance: this script deletes directly the empty rows according to their position without iteration through all the rows.
function deleteBlankRows(start_row=4) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//temporarily insert last column to avoid affecting existing data
sheet.insertColumnsAfter(sheet.getMaxColumns(),1);
var lastRow = findLastRow();
var lastCol = sheet.getMaxColumns()
var temp_col = sheet.getRange(start_row,lastCol,lastRow-start_row,1)
//insert formula to show row position if any row is blank from column A to N (can adjust if needed)
sheet.getRange(start_row,lastCol).setFormula('=if(countif(A'+start_row+':N'+start_row+',"*?")=0,row(),0)').copyTo(temp_col)
//get a reversed list of rows position excluded non-empty rows
var rowsPosition = temp_col.getValues().filter(x => x != 0).reverse()
//delete empty rows from bottom to top
rowsPosition.forEach(function(rowPosition){
if (Number(rowPosition) > start_row) {
sheet.deleteRow(Number(rowPosition))
}
})
//finally, delete the temporary column
sheet.deleteColumn(lastCol)
}
function findLastRow() {
const sh = SpreadsheetApp.getActive().getActiveSheet();
const data = sh.getRange("A:L").getValues();
const mR = sh.getMaxRows();
const indexes = [];
data[0].forEach((_, ci) => {
let col = data.map(d => d[ci]);
let first_index = col.reverse().findIndex(r => r != '');
if (first_index != -1) {
let max_row = mR - first_index;
indexes.push(max_row);
}
});
last_row = indexes.length > 0 ? Math.max(...indexes) : 0;
return last_row;
}
function deleteblankRw(){
var sheet=SpreadsheetApp.getActive().getSheetByName('test')
var e=sheet.getRange('A'+sheet.getMaxRows()).getNextDataCell(SpreadsheetApp.Direction.UP).getRow()
for (k=2;k<=e;k++) {
if(sheet.getRange('A'+k).getValue()=='') {
sheet.deleteRow(k);
k=2;e--
if(k==e){break};
SpreadsheetApp.flush();
}
}
}