复制到新的 sheet 自身倍增,并且不过滤我的结果

Copy to new sheet multiply itself loads of times, and dosent filter my result

我的代码确实会自我复制,结果中有超过 999 行行 sheet,而实际上应该只有几行。

当我创建过滤器并勾选 F 列中的“777”时,它仍然会出现在过滤结果中。

: 是什么导致了这种行为,我该如何解决才能使其只复制一次,并且只复制过滤后的结果?

以下是更多详细信息:

完整代码:

 var partner_list = SpreadsheetApp.openByUrl(url);
var SS = partner_list.getSheetByName("Sheet 1");
var targetSheet = partner_list.getSheetByName("result");

 if (SS.getFilter() != null && SS.getFilter().toString()=='Filter') {
   console.log("have populated filter..", SS.getFilter());
var Avals_pre_D = SS.getFilter().getRange();
var Avals_pre = SS.getFilter().getRange().getValues();

    if (targetSheet) {
        partner_list.deleteSheet(targetSheet);
    } 
       targetSheet = partner_list.insertSheet();
       targetSheet.setName("result"); 
  

console.log("DATA:",Avals_pre);


Avals_pre_D.copyTo(
    targetSheet.getRange('A2:R'),
    SpreadsheetApp.CopyPasteType.PASTE_NORMAL,
    false);
var SS = SpreadsheetApp.openByUrl(same_url).getSheetByName("result"); // aka same.. but the result sheet.
var Avals_pre = targetSheet.getRange("A2:R").getValues();    
} else {
  console.log("no filter..");
 var Avals_pre = SS.getRange("A2:R").getValues(); 
}

console.log(Avals_pre.length);

尝试复制 Avals_pre 时出现以下错误:

TypeError: Avals_pre.copyTo is not a function

avals_pre的输出结果如下:

   DATA: [ 
    [ '','','','','','test','','','','','','','','','','','','','','','','','','','','' ],
    [ 1,2,3,4,5,666,'','','',100,'','','','','','','','','','','','','','','','' ],
    [ 4,23,43,44,5,777,'','','',100,'','','','','','','','','','','','','','','','' ],
    [ 43,65,54,65,65,888,'','','',100,'','','','','','','','','','','','','','','','' ],]

(这包括我不想要的结果)

如果我采用 Avals_pre_D 并复制它,它的行为就像疯了一样。 其中 console.log(Avals_pre.length); 等于 999。

结果图片sheet:

修改点:

  • 我认为您的问题可能是由于以下原因造成的。

    • 当使用SS.getFilter().getRange()作为范围时,
      • copyTo一起使用时,检索过滤后的值。通过这种方式,Avals_pre_D.copyTo(targetSheet.getRange('A2:R'), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false); 适用于具有过滤结果的值。似乎在这种情况下,范围内的显示值被复制了。
      • 当它与 getValues 一起使用时,将检索所有值。这样,第一个 var Avals_pre = SS.getFilter().getRange().getValues(); 适用于没有过滤结果的值。
    • 我认为这可能是当前的规范。
  • 而且,当我看到你的脚本时,使用了var Avals_pre = targetSheet.getRange("A2:R").getValues(); 。在这种情况下,范围是“A2:R”。通过这种方式,值由 sheet 中的最大行检索。我认为这可能是您 If i take Avals_pre_D and copy that, it behaves like crazy. where console.log(Avals_pre.length); equals 999..

    问题的原因
  • 如果您想直接检索 sheet 上过滤结果的值,我认为 this thread 可能会有用。

当以上几点反映到你的脚本中,就变成了下面这样。

修改后的脚本:

function myFunction() {
  // var url = "###"; // I'm not sure about your "url" and "same_url". So please set these variables.
  // var same_url = url;

  var partner_list = SpreadsheetApp.openByUrl(url);
  var SS = partner_list.getSheetByName("Sheet 1");
  var targetSheet = partner_list.getSheetByName("result");
  if (SS.getFilter() != null && SS.getFilter().toString() == 'Filter') {
    console.log("have populated filter..", SS.getFilter());
    var Avals_pre_D = SS.getFilter().getRange();

    // --- I added below script.
    var url2 = `https://docs.google.com/spreadsheets/d/${partner_list.getId()}/gviz/tq?tqx=out:csv&gid=${SS.getSheetId()}`;
    var res = UrlFetchApp.fetch(url2, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}});
    var Avals_pre = Utilities.parseCsv(res.getContentText());
    // ---

    if (targetSheet) {
      partner_list.deleteSheet(targetSheet);
    }
    targetSheet = partner_list.insertSheet();
    targetSheet.setName("result");
    console.log("DATA:", Avals_pre);
    Avals_pre_D.copyTo(
      targetSheet.getRange('A2:R'),
      SpreadsheetApp.CopyPasteType.PASTE_NORMAL,
      false);
    var SS = SpreadsheetApp.openByUrl(same_url).getSheetByName("result"); // aka same.. but the result sheet.
    var Avals_pre = targetSheet.getRange("A2:R" + targetSheet.getLastRow()).getValues();  // Modified
  } else {
    console.log("no filter..");
    var Avals_pre = SS.getRange("A2:R" + SS.getLastRow()).getValues();  // Modified
  }
  console.log(Avals_pre.length);
}

注:

  • 在上面修改的脚本中,通过下面添加的脚本,过滤后的值直接检索到Avals_pre.

      var url = `https://docs.google.com/spreadsheets/d/${partner_list.getId()}/gviz/tq?tqx=out:csv&gid=${SS.getSheetId()}`;
      var res = UrlFetchApp.fetch(url, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}});
      var Avals_pre = Utilities.parseCsv(res.getContentText());
    
  • 如果你可以使用这个脚本,我想你也可以按如下方式修改你的脚本。

      var partner_list = SpreadsheetApp.openByUrl(url);
      var SS = partner_list.getSheetByName("Sheet 1");
      var Avals_pre;
      if (SS.getFilter() != null && SS.getFilter().toString() == 'Filter') {
        console.log("have populated filter..", SS.getFilter());
        var url2 = `https://docs.google.com/spreadsheets/d/${partner_list.getId()}/gviz/tq?tqx=out:csv&gid=${SS.getSheetId()}`;
        var res = UrlFetchApp.fetch(url2, {headers: {authorization: `Bearer ${ScriptApp.getOAuthToken()}`}});
        Avals_pre = Utilities.parseCsv(res.getContentText());
      } else {
        console.log("no filter..");
        Avals_pre = SS.getRange("A2:R" + SS.getLastRow()).getValues();
      }
      console.log(Avals_pre.length);
    

参考文献:

  • getLastRow()
  • 相关话题
    • How to get filtered values from Filter after using setColumnFilterCriteria?

已添加:

关于以下你的附加问题,

do you know how i can get the row number? etg if 3 is filtered out, i would get 1,2,4?

在这种情况下,不能直接使用上面的方法。因此,作为一个简单的示例脚本,我添加了一个示例脚本来检索隐藏行号和显示行号。

示例脚本:

function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet()
  var result = {hiddenRow: [], showedRow: []};
  for (var r = 1; r <= sheet.getLastRow(); r++) {
    result[sheet.isRowHiddenByFilter(r) ? "hiddenRow" : "showedRow"].push(r);
  }
  console.log(result)
}
  • 在此示例脚本中,返回活动 sheet 的隐藏行号和显示行号。

参考: