Wayne G
Wayne G

Reputation: 11

Google Spreadsheet script to choose a column based on two values

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

Upvotes: 1

Views: 281

Answers (2)

Cooper
Cooper

Reputation: 64062

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

Upvotes: 1

Wayne G
Wayne G

Reputation: 11

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);
}  

Upvotes: 0

Related Questions