【问题标题】:Google Spreadsheet script to choose a column based on two values谷歌电子表格脚本根据两个值选择一列
【发布时间】:2017-02-22 10:14:36
【问题描述】:

亲爱的出色的脚本家,

抱歉,我不知道所有的术语,我充其量只是一个新手,但我已经碰壁了。我正在尝试根据不同单元格中的两个值隐藏/显示列。

我有一个名为“开始”的工作表,它的值在 O2 中会发生变化(年份)。这对应于名为“主题”的工作表上的一列(见图)。 Subjects 有一个主题列表和标有“Prep, Year 1-2, Year 3-4 and Year 5-6”的列。我想编写一个解决方案,检查 Start 上的值,然后读取 Subjects 上的 1 和 0 列,并在另一个名为“Reports”的工作表上显示/隐藏列。

例如,如果开始时的 O2 显示第 1-2 年,则脚本会查看主题 (D1),然后在与这些主题对应的报告上显示或隐藏(1 或 0)列(例如 Preps 上具有 IPDIP,因此如果值为 1-2 年,则报表上的列将被隐藏。报表上将隐藏或显示多个列。

我目前正在使用这个脚本:

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

这里有一些图片来解释。

[开始时的值][1]

Subjects Sheet

Columns on Reports sheet

您的帮助将不胜感激。这个 Google 电子表格目前每年为我们学校节省 1000 美元,如果能解决这个问题,那就太棒了。

和平与感谢,

韦恩

【问题讨论】:

  • condition = 1 是赋值而不是比较。再往前走一点,看看你能不能自己解决。
  • 是的,到此为止 :) 删除了“”,它似乎工作了 :) 我仍然不明白我是如何得到它来检查起始表和主题表的。目前,该脚本仅检查主题中的单元格。如果我继续这样下去,我将需要制作同一张纸的四个不同副本。

标签: google-apps-script google-sheets


【解决方案1】:

列选择器

这是代码

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

小问题

我有一个工作版本,但我遇到了问题。我正在使用正则表达式 RegExp('^' + subject)。这允许我做的是动态构建正则表达式。当主题是 IPDIP 时,正则表达式 ^IPDIP 匹配 IPDIP 列标题的所有字符,并且由于第 1-2 年的第二行是 0,因此关闭 IPDIP 列,但下一个主题是 IPD 和正则表达式 ^ IPD 也与 IPDIP 匹配,并且第 1-2 年的第三行现在关闭 IPDIP,这可能是一个问题。我计划使用这种技术来匹配其余的列,因为主题只是其余列标题的前三个字母,这将是捕捉它们的好方法。所以我想问题是您希望在 1-2 年的报告中打开还是关闭 IPDIP。

所有报告列标题名称是否都包含六个或更多字符?我可以利用这一点,因为 IPDIP 只有 5 个字符。所以我只能将我的正则表达式应用于 6 个字符或更大的标题。但我需要您对此提供意见,因为我猜测实际的报告表可能比我看到的要宽一些。

我想另一种解决方案可能是从主题列的底部向上移动到顶部,然后 IPDIP 将始终是 5 个字符匹配。

我刚刚注意到我们在 ICT 和 ICTICT 方面存在同样的问题。

现在我决定将主题列从下到上的顺序颠倒过来。只要您始终将具有重叠匹配项的最长字符串放在顶部,就可以了。

让你知道

我对这段代码所做的一件事是使表格的来源成为主题页面上的主题标题和报告页面上的 IPDIP 标题的位置。因此,这使您可以移动表格(即在当前数据的左侧和上方添加列)。该程序根据这两个关键位置确定数据的位置,并自动重新调整。另一种说法是,它不假设表中的第一行/列是行/列 1/A

【讨论】:

  • 太棒了,这几乎是正确的。报告中的列是主题的前三个字母。例如,PLE(B5 on Subjects)对应于报告中以该代码开始的列。您可以在示例中看到 IPD 与 IPDSOC_PRE(K 列)到 IPDTEA(N 列)相关。它在一列和六列之间变化。我打算通过使用类似的东西来做到这一点: var condition = sheet.getRange("Subjects!C2").getValue(); if (condition = 1) { sheet.showColumns(10,1) sheet.showColumns(11,1) sheet.showColumns(12,1) etc. }
  • 好的,让我再考虑一下,然后我会回来总结我认为您想要的内容,您可以从那里进行调整。 ...我们可以使用正则表达式将 3 个字母前缀与 /^PLE/ 区分大小写的内容进行匹配,这将匹配前缀。使用 /^IPDIP/ 将匹配 IPDIP,这样应该可以正常工作。它开始变得有意义了。我今天有几件事要做,但我会尽快回来。
  • 伴侣,非常感谢任何帮助。 :)
  • 你好韦恩,我有一个工作版本,但我遇到了一个小问题,也许你可以帮助我。它在上面标题为“小问题”的部分中进行了解释。我确信它是可以解决的,但如果你能帮我看看它,我会很好。我需要再测试一下代码,然后我会发布它,我们都可以看到它。
  • 我已经创建了一个测试表 - docs.google.com/spreadsheets/d/… 我在运行脚本时收到了一些“显示参数超出范围而不是函数 columnsShowHide 中的 0 或 1”错误。否则效果很好。代码不是一成不变的,所以如果我们需要更改IPDIP和ICTICT的名称,我们可以。
【解决方案2】:

完全按照要求工作,首先尝试 :-) 感谢 Cooper 的辛勤工作。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 2015-01-25
    • 2011-05-29
    • 1970-01-01
    • 2019-02-06
    • 1970-01-01
    相关资源
    最近更新 更多