【问题标题】:Apps Script filter function not reproducing expected resultApps 脚本过滤器功能无法重现预期结果
【发布时间】:2020-03-10 20:11:08
【问题描述】:

我有这个包含 3 列的 Google 表格, data with three columns 这是数据: Data Source 我编写了一个脚本来过滤 A 列和 C 列何时满足某些条件 然后脚本在工作表“PharmacyV1”中生成结果。结果按预期生成,因为此工作表中有 14 行。

脚本的下一部分,我基本上过滤了与第一个条件完全相反的条件,基本上是抓取未过滤到工作表“Pharmacy V1”的数据并将其重写到原始工作表“V1”。

我的原始 V1 表包含 1,631 行数据(不包括标题)

我的 PharmacyV1 工作表过滤掉了 14 行数据

但 V1 结果以 1,575 行数据结束,但我应该预计 1631-14 = 1617 行。

有人能指出出现这种差异的原因或原因吗?

function S02_FilterPharmacy_Copy2NewSheet() {

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('V1');
  var firstRow = sheet.getRange(1,1,1,sheet.getLastColumn()).getValues();
  var C1 = firstRow[0].indexOf('TxnUser');
  var C2 = firstRow[0].indexOf('Location');

  // Filter for IV therapy and pharmacy users using filtered Range:
  var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
  var filteredRange = rangeVals.filter(function(val){
    return val[C2] === "IV THERAPY" && (val[C1] === "DEOK645"|| val[C1] === "JETH850" || 
      val[C1] === "JOON409"|| val[C1] === "THAM1452");
    });
  var targetSheet = ss.insertSheet('PharmacyV1');
  targetSheet.getRange(2,1,filteredRange.length,filteredRange[0].length).setValues(filteredRange);
  var sheet = ss.getSheetByName('V1');
  targetSheet.getRange(1,1,1,sheet.getLastColumn()).setValues(firstRow);
  
  
  //Filter and replace original V1
  var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
  var filteredRange = rangeVals.filter(function(val){
   return val[C2] != "IV THERAPY" && (val[C1] != "JOON409"|| val[C1] != "JETH850" || 
     val[C1] != "JOON409"|| val[C1] != "THAM1452");
     });
  
  var RANGE = sheet.getDataRange(); RANGE.clearContent();
  var newRange = sheet.getRange(1,1,filteredRange.length, filteredRange[0].length);
  newRange.setValues(filteredRange);
 
}

【问题讨论】:

    标签: google-apps-script google-sheets filter


    【解决方案1】:
    • 您想用val[C2] === "IV THERAPY" && (val[C1] === "DEOK645"|| val[C1] === "JETH850" || val[C1] === "JOON409"|| val[C1] === "THAM1452"); 过滤var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues(); 的值。
    • 您想要检索过滤后的值。 (在您的共享电子表格中,它是 14 行)
    • 您想要检索未过滤的值。 (在您的共享电子表格中,有 1617 行)
    • 您想知道当从1631 的总行中检索未过滤的值时,您的脚本没有返回1631 - 14 = 1617 行的原因。

    如果我的理解是正确的,那么这个答案呢?请认为这只是几个可能的答案之一。

    问题:

    首先,我想比较两个过滤器以检索filteredRange

    1. val[C2] === "IV THERAPY" && (val[C1] === "DEOK645"|| val[C1] === "JETH850" || val[C1] === "JOON409"|| val[C1] === "THAM1452")

      • 这将返回 14 行。
    2. val[C2] != "IV THERAPY" && (val[C1] != "JOON409"|| val[C1] != "JETH850" || val[C1] != "JOON409" || val[C1] != "THAM1452")

      • 这将返回 1576 行。这不是 1617,而是 1631 - 14 = 1617

    在这里,我认为对于第二个过滤器,DEOK645 应该是 JOON409。而当您想使用第一个过滤器创建相反的过滤器时,==!= 分别修改为 !===。而且,&&|| 分别修改为 ||&&。在您的脚本中,我认为后者是您问题的原因。

    解决方案和解决方法:

    使用您的共享电子表格时,以下 3 种模式返回 1617 行的值。

    模式一:

    在此模式中,使用了上述修改。请进行如下修改。

    从:
    //Filter and replace original V1
    var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
    var filteredRange = rangeVals.filter(function(val){
     return val[C2] != "IV THERAPY" && (val[C1] != "JOON409"|| val[C1] != "JETH850" || 
       val[C1] != "JOON409"|| val[C1] != "THAM1452");
       });
    
    到:
    //Filter and replace original V1
    var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
    var filteredRange = rangeVals.filter(function(val){
      return return val[C2] != "IV THERAPY" || (val[C1] != "DEOK645" && val[C1] != "JETH850" && val[C1] != "JOON409" && val[C1] != "THAM1452"); // Modified
    });
    

    模式2:

    在此模式中,使用第一个过滤器。请进行如下修改。

    从:
    //Filter and replace original V1
    var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
    var filteredRange = rangeVals.filter(function(val){
     return val[C2] != "IV THERAPY" && (val[C1] != "JOON409"|| val[C1] != "JETH850" || 
       val[C1] != "JOON409"|| val[C1] != "THAM1452");
       });
    
    到:
    //Filter and replace original V1
    var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
    var filteredRange = rangeVals.filter(function(val){
      return !(val[C2] === "IV THERAPY" && (val[C1] === "DEOK645"|| val[C1] === "JETH850" || val[C1] === "JOON409"|| val[C1] === "THAM1452")); // Modified
    });
    

    模式3:

    在此模式中,过滤值和未过滤值都在一个循环中检索。

    var rangeVals = sheet.getRange(1,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
    var filteredRange = rangeVals.reduce(function(obj, val){
      if (val[C2] === "IV THERAPY" && (val[C1] === "DEOK645"|| val[C1] === "JETH850" || val[C1] === "JOON409"|| val[C1] === "THAM1452")) {
        obj.filteredValue.push(val);
      } else {
        obj.noFilteredValue.push(val);
      }
      return obj;
    }, {filteredValue: [], noFilteredValue: []});
    
    • 在这种情况下,filteredRange.filteredValuefilteredRange.noFilteredValue 分别是过滤后的值和未过滤的值。

    参考资料:

    如果我误解了您的问题并且这不是您想要的结果,我深表歉意。

    【讨论】:

    • 非常感谢@Tanaike。作为一个编码新手,我非常感谢您提供的所有选项。模式 3 非常优雅。如果我可能会问,您引用的 reducer 方法是在 javascript 中。我知道 Google Apps Script 主要建立在较旧的 javascript 之上。那么 GAS 的语法和 Javascript 中的语法一样吗?我无法在 google sheet 参考资源link 中找到 reduce() 方法,但如果 GAS 和 Javascript 之间的语法相同,我将计划去 MDN Web Docs 进行参考
    • 我想问另一个与此过滤器语法相关的问题:过滤器的条件之一是' val[C2] === "IV THERAPY" ',这个运算符是精确的。如果我想过滤单元格值仅以“HERAPY”结尾的项目,而不是整个“IV THERAPY”怎么办。同样,过滤包含“HERAPY”的任何内容而不考虑文本的位置怎么办?在单元格中。我尝试了 'val[C2] === "HERAPY" ',但代码根本没有返回。有人能指出我解释这种语法的资源吗?
    • @Thien Pham 感谢您的回复。我很高兴你的问题得到了解决。关于您的其他问题,我已将其回复至your new question,因为我找到了。你能确认一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 2018-12-15
    • 2022-12-02
    • 2018-06-12
    • 1970-01-01
    相关资源
    最近更新 更多