The following code will run very slow in my Google Sheets because my getRange is too large. Is there a way to only loop through the columns that are merged? I only want the for loop to get the number of columns in "yourRange" that are merged.
function getUpfrontCosts() {
var sheet = SpreadsheetApp.getActive().getSheetByName('LPB_COST');
var cl , count=0;
var yourRange = sheet.getRange("H13:UV13");
for (var i = 1; i < yourRange.getNumColumns()+1; i++)
{
cl=yourRange.getCell(1, i);
if (cl.isPartOfMerge()){
if (cl.offset(15, 0).getBackground() == "#ff8300" && cl.getMergedRanges()[0].getCell(1, 1).getValue()=='Upfront Costs') {
count = count + cl.offset(15, 0).getValue();
}
else {
}
} else {
}
}
return count;
};
The second code is how I am trying to turn a string to a range. I am getting "Cell reference out of range" error
How can I change cl to not be a string and be a range?
function getUpfrontCosts()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('LPB_COST');
var destSheet = SpreadsheetApp.getActive().getSheetByName('Top Level PN');
var cl , count=0;
var yourRange = sheet.getRange("I13:UZ13");
var mergedRanges = yourRange.getMergedRanges();
for (var i = 0; i < mergedRanges; i++){
}
var newRange = sheet.getRange(mergedRanges[i].getA1Notation());
Logger.log(newRange.getA1Notation());
for (var i = 0; i < newRange.getNumColumns()+1; i++){
cl=newRange.getCell(1, i);
Logger.log(newRange.getA1Notation());
if (cl.offset(15, 0).getBackground() == "#ff8300" && cl.getValue()=='Upfront Costs') {
count = count + cl.offset(15, 0).getValue();
}
else {
}
}
return count;
};
This is the line with the error
cl=newRange.getCell(1, i);
if you want to use merge cell range, you can do this:
function UntitledMacro1()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var cl , count=0 ;
var yourRange = sheet.getRange("I13:UZ13");
var bb = yourRange.getMergedRanges();
for (a=bb[0].getColumn();a<bb[0].getLastColumn()+1;a++)
{
//Your actual columns from I13, for first merge range, here your cl,
//but if your range is ("13:13"), you don't need
//-sheet.getRange("I13").getColumn()+1
cl=yourRange.getCell(1, a-sheet.getRange("I13").getColumn()+1);
//For your offset 15
Logger.log(cl.offset(15, 0).getValue());
//on so on
}
};
I need a quick function to loop through the rows of one of my sheets so I constructed this:
function getTotalsOf(name, type) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name);
var data = sheet.getDataRange().getValues();
var total = 0.00;
for (var i = 0; i < data.length; i++) {
if (data[i][0]== "") break;
if (data[i][2] == type) {
var temp = (Number(data[i][4]) + Number(data[i][5]) + Number(data[i][6])) * data [i][3];
total = Number(total) + total;
}
}
return total;
}
SpreadsheetApp.getActiveSpreadsheet() seems to return null when I try to execute the function. It also returns null when I try to get the spreadsheet by id. Am I missing something?
EDIT:
I retried using my spreadsheet id (https://docs.google.com/spreadsheets/d/STRINGFROMHERE/edit#gid=1235572150) with the same results.
function getTotalsOf(name, type) {
var sheet = SpreadsheetApp.openById("**STRINGFROMURL**").getSheetByName(name);
var data = sheet.getDataRange().getValues();
var total = 0.00;
for (var i = 0; i < data.length; i++) {
if (data[i][0]== "") break;
if (data[i][2] == type) {
var temp = (Number(data[i][4]) + Number(data[i][5]) + Number(data[i][6])) * data [i][3];
total = Number(total) + temp;
}
}
return total;
}
I think you just missed a few concepts with regard to looping through spreadsheets. Hope this demo will help and get you what you want. Always remember that rows and cols in spreadsheets starts with 1,1 not 0,0.
function loopThroughCells() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
Logger.log(data[0].length);
for(var i=0; i< data.length; i++){
for(var j=0; j<data[i].length; j++){
if(data[i][j] == "HELIOS"){
if (data[i][j]== "") break;
Logger.log("HELIOS data found in range "+ (i+1) + " "+(j+1));
}
}
}
Log
[17-07-07 21:45:17:157 HKT] HELIOS data found in range 3 3
I have a spreadsheet with multiple rows and columns. Two columns (column 3&4) are filled with text. I want to clean the text from this two columns and delete every specific characters (newlines, comma, exclamation point, quote,etc...). So I wrote the following script :
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
temp3 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp3.push(raw_data[i][4].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
temp4 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp4.push(raw_data[i][3].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
var toAddArray3 = [];
for (i = 0; i < temp3.length; ++i){
toAddArray3.push([temp3[i]]);
}
var toAddArray4 = [];
for (i = 0; i < temp4.length; ++i){
toAddArray4.push([temp4[i]]);
}
output.getRange(1, col_count-13,row_count,1).setValues(toAddArray3);
output.getRange(1, col_count-14,row_count,1).setValues(toAddArray4);
}
It's working but It's very complicated and confusing. I made it step-by-step so even myself have some difficulties to really explain it.
Is there a way to significantly improve it ?
Best,
Simon.
DRY! - Do not repeat yourself.
Another popular idiom should be UMNF - Use map not for.
Putting everything into its own function encapsulates functionality and puts the focus on what you want to do with the data at each level rather than bookkeeping indices and subscripts.
function cleanColumns() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var raw_data = input.getDataRange().getValues();
var columnsToClean = [3,4];
function cleanText(t) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
return t.toString().replace(punctRE, "").replace(spaceRE, " ");
};
function cleanColumn(col) {
return raw_data
.map(function(row) {return row[col];})
.map(cleanText)
.map(function(row) {return [row];})
};
function cleanAndWrite(col) {
var data = cleanColumn(col);
output.getRange(1, col + 1, data.length, 1).setValues(data);
}
columnsToClean.forEach(cleanAndWrite);
}
Dear Wonderful Scripters,
Apologies for not knowing all the lingo, I'm a novice at best but I've hit the wall. I am trying to hide/show columns based on two values in different cells.
I have a sheet named "Start" which has a value that changes (Year) in O2. This corresponds to a column on a sheet named "Subjects" (see pic). Subjects has a list of subjects and columns labelled "Prep, Year 1-2, Year 3-4 and Year 5-6". I would like to script a solution that checks the value on Start and then reads the column on Subjects for 1s and 0s and shows/hides columns on another sheet named "Reports".
For example, if O2 on Start says Year 1-2, then the script looks at Subjects (D1) and then shows or hides (1 or 0) columns on Reports that correspond with those subjects (eg Preps on have IPDIP so if the value is Year 1-2, then the column on Reports will be hidden. There is more than one column on Reports that will be hidden or shown.
I'm currently using this script:
function ShowHideSubjects() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Reports");
sheet.showColumns(1, sheet.getMaxColumns())
var condition = sheet.getRange("Subjects!C2").getValue();
if (condition = 1) {
sheet.showColumns(10,1)
}
var condition = sheet.getRange("Subjects!C2").getValue();
if (condition = 0) {
sheet.hideColumns(10,1)
}
}
Here's some pics to explain.
[Value on Start][1]
Subjects Sheet
Columns on Reports sheet
Your help would be greatly appreciated. This Google Spreadsheet currently saves our school $1000s a year and it would be awesome to get this sorted out.
Peace and thanks,
Wayne
The Column Chooser
Here's the code
function onOpen()
{
SpreadsheetApp.getUi().createMenu('My Tools')
.addItem('ShowHideSubjects','ShowHideSubjects')
.addToUi();
}
function ShowHideSubjects()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var reportsSheet = ss.getSheetByName('Reports');
var subjectsSheet = ss.getSheetByName('Subjects')
var startSheet = ss.getSheetByName('Start');
var startSubjectsRange = startSheet.getRange('O2');
var reportsSheetDataRange = reportsSheet.getDataRange();
var reportsSheetDataArray = reportsSheetDataRange.getValues();
var reportsSheetDataRangeLastRow = reportsSheetDataRange.getLastRow();
var reportsSheetDataRangeLastColumn = reportsSheetDataRange.getLastColumn();
for(var i = 0;i < reportsSheetDataRangeLastRow;i++)
{
for(var j = 0;j < reportsSheetDataRangeLastColumn;j ++)
{
if(reportsSheetDataArray[i][j] == 'IPDIP')
{
var ipdipRow = i + 1;
var ipdipCol = j + 1;
break;
}
}
}
var reportsNumColumns = reportsSheetDataRange.getLastColumn() - ipdipCol + 1
//check that its the right reports range
//reportsSheet.setActiveSelection(reportsSheet.getRange(ipdipRow, ipdipCol, 1 , reportsNumColumns));
var reportsHeaderRange = reportsSheet.getRange(ipdipRow, ipdipCol, 1 , reportsNumColumns);
var subjectsSheetDataRange = subjectsSheet.getDataRange();
var subjectsSheetDataArray = subjectsSheetDataRange.getValues();
var subjectsSheetDataRangeLastRow = subjectsSheetDataRange.getLastRow();
var subjectsSheetDataRangeLastColumn = subjectsSheetDataRange.getLastColumn();
for(var i = 0;i < subjectsSheetDataRangeLastRow;i++)
{
for(var j = 0;j < subjectsSheetDataRangeLastColumn;j ++)
{
if(subjectsSheetDataArray[i][j] == 'Subjects')
{
var subjectsRow = i + 1;
var subjectsCol = j + 1;
break;
}
}
}
//check that its the right subjects range
//subjectsSheet.setActiveSelection(subjectsSheet.getRange(subjectsRow, subjectsCol,subjectsSheetDataRange.getLastRow() - subjectsRow + 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1));
var subjectsShowHideHeaderRange = subjectsSheet.getRange(subjectsRow, subjectsCol, 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1);
var subjectsShowHideHeaderArray = subjectsShowHideHeaderRange.getValues();
var subjectsShowHideRange = subjectsSheet.getRange(subjectsRow, subjectsCol,subjectsSheetDataRange.getLastRow() - subjectsRow + 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1);
//checked subjectsShowHideRange
//subjectsSheet.setActiveSelection(subjectsShowHideRange);
var w = subjectsShowHideHeaderRange.getWidth();
var startString = startSubjectsRange.getValue();
for(var i = 0;i < w;i++)
{
if(subjectsShowHideHeaderArray[0][i] == startString)
{
var subjectsShowHideColumn = subjectsCol + i;
break;
}
}
//checked the subjectsShowHideColumn
//SpreadsheetApp.getUi().alert( startSubjectsRange.getValue() + ' is column ' + subjectsShowHideColumn + ' on the subjects page. And subjects is on column ' + subjectsCol + '.');
//Checked the subjectsShowHideRange
//subjectsSheet.setActiveSelection(subjectsShowHideRange);
var subjectsShowHideArray = subjectsShowHideRange.getValues();
var subjectsShowHideRangeHeight = subjectsShowHideRange.getHeight();
//for(var i = 0;i < subjectsShowHideRangeHeight;i++)
for(var i = subjectsShowHideRangeHeight -1;i >= 0;i--)
{
var subject = subjectsShowHideArray[i][0];
var show = subjectsShowHideArray[i][subjectsShowHideColumn-subjectsCol];
var showhidecolsS=reportsColumnHeaderMatch(ipdipRow,ipdipCol,reportsNumColumns,subject);
if(showhidecolsS)
{
var showhidecolsA=showhidecolsS.split(',');
if(showhidecolsA)
{
for(var j = 0; j < showhidecolsA.length; j++)
{
columnsShowHide(showhidecolsA[j],show);
}
}
}
}
}
function columnsShowHide(column, show)
{
var column = (typeof(column) !== 'undefined')? column: 0;
var show = (typeof(show) !== 'undefined')? show: 1;
if(column == 0)
{
SpreadsheetApp.getUi().alert('Error: The column parameter passed to columnsShowHide is undefined.');
return;
}
else
{
switch(show)
{
case 1:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').showColumns(column);
//SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').getRange(1,column,10,1).setBackground('yellow');
break;
case 0:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').hideColumns(column);
//SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').getRange(1,column,10,1).setBackground('white');
break;
default:
SpreadsheetApp.getUi().alert('Show parameter is out of range not 0 or 1 in function columnsShowHide');
}
}
}
function reportsColumnHeaderMatch(row, col, numcolumns, subject)
{
var sht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports');
var rng = sht.getRange(row, col, 1, numcolumns);
var rngA = rng.getValues();
var result = '';
var firsttime = true;
for(var i = 0;i < numcolumns;i++)
{
//var s = rngA[0][i].toString();
var s = rngA[0][i];
var re = new RegExp('^' + subject);
if(s.match(re))
{
if(!firsttime)result += ',';
result += col + i;
firsttime = false;
}
}
return result;
}
function dispStatus(title,html,width,height)
{
// Display a modeless dialog box with custom HtmlService content.
var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
var width = typeof(width) !== 'undefined' ? width : 250;
var height = typeof(height) !== 'undefined' ? height : 300;
var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
var htmlOutput = HtmlService
.createHtmlOutput(html)
.setWidth(width)
.setHeight(height);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
}
Slight Problem
I have a working version but I ran into a problem. I'm using a regular expression RegExp('^' + subject). What this allows me to do is to build the regular expression on the fly. When the subject is IPDIP the regular expression ^IPDIP matches all of the characters of the IPDIP column header and since the second row of Year 1-2 is 0 then column IPDIP is turned off but then the next subject is IPD and the regular expression ^IPD also matches IPDIP and the third row of Year 1-2 now turns off IPDIP which is probably a problem. I was planning on using this technique to match the rest of the columns because the subjects are only the first three letters of the rest of the column headers and that would be a great way to catch them. So I guess the question is do you want IPDIP on or off in for the Year 1-2 reports.
Are all of the Reports column header names six characters or greater? I could take advantage of that because IPDIP is only 5 characters. So I could apply my regular expression only to headers that are 6 characters or greater. But I need your input on that because I'm guessing that the actual Reports sheet is probably a little wider than the one I see.
I guess another solution could be to work my way up through from the bottom of the subjects column to the top then IPDIP would always be the 5 character match.
I just noticed that we have the same problem with ICT and ICTICT.
For now I decided to just reverse the order of going through the subjects column from bottom to top. As long as you always put the longest strings that have overlapping matches on the top you should be okay.
Just so that you know
One of things I did with this code is to make the origin of the tables be the location of the Subjects Header on the subjects page and the IPDIP header on the Reports pages. So this makes possible for you to move the tables (i.e. add columns to the left and above the current data). The program figures out where the data is based up these two key locations and readjusts itself automatically. Another way of saying that is to say that it doesn't assume that the first row/column in your table is row/column 1/A
Works exactly as requested, first try :-) Thanks to Cooper for the hard work.
function onOpen()
{
SpreadsheetApp.getUi().createMenu('My Tools')
.addItem('ShowHideSubjects','ShowHideSubjects')
.addToUi();
}
function ShowHideSubjects()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var reportsSheet = ss.getSheetByName('Reports');
var subjectsSheet = ss.getSheetByName('Subjects')
var startSheet = ss.getSheetByName('Start');
var startSubjectsRange = startSheet.getRange('O2');
var reportsSheetDataRange = reportsSheet.getDataRange();
var reportsSheetDataArray = reportsSheetDataRange.getValues();
var reportsSheetDataRangeLastRow = reportsSheetDataRange.getLastRow();
var reportsSheetDataRangeLastColumn = reportsSheetDataRange.getLastColumn();
for(var i = 0;i < reportsSheetDataRangeLastRow;i++)
{
for(var j = 0;j < reportsSheetDataRangeLastColumn;j ++)
{
if(reportsSheetDataArray[i][j] == 'IPDIP')
{
var ipdipRow = i + 1;
var ipdipCol = j + 1;
break;
}
}
}
var reportsNumColumns = reportsSheetDataRange.getLastColumn() - ipdipCol + 1
//check that its the right reports range
//reportsSheet.setActiveSelection(reportsSheet.getRange(ipdipRow, ipdipCol, 1 , reportsNumColumns));
var reportsHeaderRange = reportsSheet.getRange(ipdipRow, ipdipCol, 1 , reportsNumColumns);
var subjectsSheetDataRange = subjectsSheet.getDataRange();
var subjectsSheetDataArray = subjectsSheetDataRange.getValues();
var subjectsSheetDataRangeLastRow = subjectsSheetDataRange.getLastRow();
var subjectsSheetDataRangeLastColumn = subjectsSheetDataRange.getLastColumn();
for(var i = 0;i < subjectsSheetDataRangeLastRow;i++)
{
for(var j = 0;j < subjectsSheetDataRangeLastColumn;j ++)
{
if(subjectsSheetDataArray[i][j] == 'Subjects')
{
var subjectsRow = i + 1;
var subjectsCol = j + 1;
break;
}
}
}
//check that its the right subjects range
//subjectsSheet.setActiveSelection(subjectsSheet.getRange(subjectsRow, subjectsCol,subjectsSheetDataRange.getLastRow() - subjectsRow + 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1));
var subjectsShowHideHeaderRange = subjectsSheet.getRange(subjectsRow, subjectsCol, 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1);
var subjectsShowHideHeaderArray = subjectsShowHideHeaderRange.getValues();
var subjectsShowHideRange = subjectsSheet.getRange(subjectsRow, subjectsCol,subjectsSheetDataRange.getLastRow() - subjectsRow + 1 ,subjectsSheetDataRange.getLastColumn() - subjectsCol + 1);
//checked subjectsShowHideRange
//subjectsSheet.setActiveSelection(subjectsShowHideRange);
var w = subjectsShowHideHeaderRange.getWidth();
var startString = startSubjectsRange.getValue();
for(var i = 0;i < w;i++)
{
if(subjectsShowHideHeaderArray[0][i] == startString)
{
var subjectsShowHideColumn = subjectsCol + i;
break;
}
}
//checked the subjectsShowHideColumn
//SpreadsheetApp.getUi().alert( startSubjectsRange.getValue() + ' is column ' + subjectsShowHideColumn + ' on the subjects page. And subjects is on column ' + subjectsCol + '.');
//Checked the subjectsShowHideRange
//subjectsSheet.setActiveSelection(subjectsShowHideRange);
var subjectsShowHideArray = subjectsShowHideRange.getValues();
var subjectsShowHideRangeHeight = subjectsShowHideRange.getHeight();
//for(var i = 0;i < subjectsShowHideRangeHeight;i++)
for(var i = subjectsShowHideRangeHeight -1;i >= 0;i--)
{
var subject = subjectsShowHideArray[i][0];
var show = subjectsShowHideArray[i][subjectsShowHideColumn-subjectsCol];
var showhidecolsS=reportsColumnHeaderMatch(ipdipRow,ipdipCol,reportsNumColumns,subject);
if(showhidecolsS)
{
var showhidecolsA=showhidecolsS.split(',');
if(showhidecolsA)
{
for(var j = 0; j < showhidecolsA.length; j++)
{
columnsShowHide(showhidecolsA[j],show);
}
}
}
}
}
function columnsShowHide(column, show)
{
var column = (typeof(column) !== 'undefined')? column: 0;
var show = (typeof(show) !== 'undefined')? show: 1;
if(column == 0)
{
SpreadsheetApp.getUi().alert('Error: The column parameter passed to columnsShowHide is undefined.');
return;
}
else
{
switch(show)
{
case 1:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').showColumns(column);
//SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').getRange(1,column,10,1).setBackground('yellow');
break;
case 0:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').hideColumns(column);
//SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports').getRange(1,column,10,1).setBackground('white');
break;
default:
SpreadsheetApp.getUi().alert('Show parameter is out of range not 0 or 1 in function columnsShowHide');
}
}
}
function reportsColumnHeaderMatch(row, col, numcolumns, subject)
{
var sht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Reports');
var rng = sht.getRange(row, col, 1, numcolumns);
var rngA = rng.getValues();
var result = '';
var firsttime = true;
for(var i = 0;i < numcolumns;i++)
{
//var s = rngA[0][i].toString();
var s = rngA[0][i];
var re = new RegExp('^' + subject);
if(s.match(re))
{
if(!firsttime)result += ',';
result += col + i;
firsttime = false;
}
}
return result;
}
function dispStatus(title,html,width,height)
{
// Display a modeless dialog box with custom HtmlService content.
var title = typeof(title) !== 'undefined' ? title : 'No Title Provided';
var width = typeof(width) !== 'undefined' ? width : 250;
var height = typeof(height) !== 'undefined' ? height : 300;
var html = typeof(html) !== 'undefined' ? html : '<p>No html provided.</p>';
var htmlOutput = HtmlService
.createHtmlOutput(html)
.setWidth(width)
.setHeight(height);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, title);
}
I have a tremendous volume of sparse matrix data, where i want to programmatically set as active cell wherever there is (0) when I run the below snippet (function).
Which would ease me for manipulation of code labels
The data is purely random. The process has to begin from the current active cell and it has to loop again from beginning if end of the data is found.
I get unexpected results,
function getzero() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var Values = range.getValues();
for (var i = 0; i < Values.length; i++) {
for (var j = 0; j < Values[i].length; j++) {
if (Values[i][j] == 0) {
sheet.setActiveSelection(sheet.getRange(i + 1, j + 1));
break;
}
}
}
}
This should take care of finding all the zeros. Also added a menu for you to run the command from the sheets directly. Just paste code in the script editor and reload the sheet.
// This function addes a menu Zero and submenu getzero to access your function directly from spreadsheet
function onOpen(){
var ss = SpreadsheetApp.getActive()
var menu = [{name:"Find Zero",functionName: "getzero"}]
ss.addMenu("Zeroes", menu)
}
function getzero() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var Values = range.getValues();
var selectedRange = sheet.getActiveRange()
// find active cells row and column
var startRow = selectedRange.getRow() -1
var startCol = selectedRange.getColumn()
var notFoundZero = true
//Use the active cells row and column to start the loop
for (var i = startRow; i < Values.length; i++) {
if (i == startRow){
var j = startCol
}
else {
j =0
}
for (j ; j < Values[i].length; j++) {
// Using "===" makes sure the type is also match else blank is considered as zero too.
if (Values[i][j] === 0) {
Logger.log("Values Row X Col:" + i + " X " + j)
//The below line works as well as sheet.setActiveSelection
sheet.getRange(i + 1, j + 1).activate()
//Below code escapes the outer loop
i = Values.length;
// this boolean is used to runs or stops the next loop
notFoundZero = false;
// breaks inner loop
break;
}
}
}
if(notFoundZero){
for (var i = 0; i <= startRow; i++) {
if (i == startRow){
var runTill = startCol
}
else {
runTill = Values[i].length
}
for (var j=0 ; j < runTill; j++) {
if (Values[i][j] === 0) {
sheet.getRange(i + 1, j + 1).activate()
// same as above
i = Values.length;
//Used to alert if no more zeros found
notFoundZero = false;
break;
}
}
}
}
if(notFoundZero)
{
var ui = SpreadsheetApp.getUi()
ui.alert("No More zero Found")
}
}
This will check cell values after selection if no zeroes are found it will check above the selection. But after that it will stop at the selection and alert no zeroes found, this prevents a runaway loop.
Give it a go and let me know how it goes.
Edit: Below Code for searching in reverse
Below Code Has not been Tested, Might have errors. This was not the primary Question, hence did not check for errors.
function getzeroRev() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var Values = range.getValues();
var selectedRange = sheet.getActiveRange()
// find active cells row and column
var startRow = selectedRange.getRow() -1
var startCol = selectedRange.getColumn()
var notFoundZero = true
//Use the active cells row and column to start the loop
for (var i = startRow; i >=0; i--) {
if (i == startRow){
var j = startCol
}
else {
j =values[i].length
}
for (j ; j >=0; j--) {
// Using "===" makes sure the type is also match else blank is considered as zero too.
if (Values[i][j] === 0) {
Logger.log("Values Row X Col:" + i + " X " + j)
//The below line works as well as sheet.setActiveSelection
sheet.getRange(i + 1, j + 1).activate()
//Below code escapes the outer loop
i = Values.length;
// this boolean is used to runs or stops the next loop
notFoundZero = false;
// breaks inner loop
break;
}
}
}
if(notFoundZero){
for (var i = values.length; i >= startRow; i--) {
if (i == startRow){
var runTill = startCol
}
else {
runTill = 0
}
for (var j=0 ; j >= runTill; j--) {
if (Values[i][j] === 0) {
sheet.getRange(i + 1, j + 1).activate()
// same as above
i = Values.length;
//Used to alert if no more zeros found
notFoundZero = false;
break;
}
}
}
}
if(notFoundZero)
{
var ui = SpreadsheetApp.getUi()
ui.alert("No More zero Found")
}
}