【问题标题】:Value minus 1 for each row IF每行 IF 的值减 1
【发布时间】:2021-10-26 16:59:22
【问题描述】:

我的编码经验非常有限,使用 Google Apps 脚本更是如此。我已经有一个包含一些功能的脚本,我从论坛中整理出来......对我来说,下一步是(如果可能的话)在某一列中为每一行做-1(例如,让我们假设我的值在 C 列)。

具体来说:

  • 如果该行的值高于上一行:保留该值并跳到下一行。或
  • 如果 this 的值 = 1:也保留该值并跳到下一行。
  • ELSE 我希望它执行高于 -1 的行的值。

因此,如果 C 列具有以下值: 5 5 5 5 5 3 3 3 1 2 2

输出应该是 5 4 3 2 1 3 2 1 1 2 1

它可以从 C3 开始,因为 C1 是标题,C2 也应该保持原样。是的,它可以完全覆盖 C 列中的数据,因为它已经是 B 列的副本,我已经完成了这个小代码:

function copytestdata() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Output');
  sheet.getRange("B2:B").copyTo(sheet.getRange("C2:C"), {contentsOnly:true});
 }

如果你知道如何做 G 应用程序,可能很容易制作。任何可以提供帮助的人:)?

【问题讨论】:

  • 你的代码对我来说运行得很好。

标签: javascript google-apps-script iteration


【解决方案1】:

你可以做这样的事情。我没有做你所有的条件,但我想你会想自己弄清楚。

function copytestdata() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName('Output');
  const vs = sh.getRange(2,2,sh.getLastRow() - 1).getValues();
  let vo = vs.map((r,i) => {
    //I just subtracted one
    if(r[0] > 1) {
      return [r[0] - 1];
    }
  })
  sh.getRange(2,3,vo.length,vo[0].length).setValues(vo);
}

COL2 是我的数据,COL3 是我的输出

COL2 COL3
2 1
10 9
16 15
14 13
16 15
14 13
12 11
9 8
4 3
17 16
19 18
2 1
8 7
12 11
7 6
12 11
7 6
4 3
11 10
7 6

【讨论】:

  • 感谢您的编辑。我不明白为什么它看起来这么奇怪。
【解决方案2】:

解释:

您的描述有两种不同的解释,因此我提供了两种解决方案,以便您选择最适合您的。

每次迭代后,您需要检查上一行中的值,但上一行中的值可能是原始值(C列中的值)或在上一次迭代中计算出来的

解决方案 1 - 在上一次迭代中计算的上述行的值:

function copytestdata() {
  const ss = SpreadsheetApp.getActive();
  const sheet = ss.getSheetByName('Output');
  const vs = sheet.getRange("C3:C"+sheet.getLastRow()).getValues().flat();
  const res = [[vs[0]]];
  let temp;
  for(i=1;i<vs.length;i++){
      temp = vs[i]>res[i-1] || vs[i]==1 ? vs[i] : res[i-1]-1;
      res.push([temp]);
  }
  sheet.getRange(3,4,res.length,res[0].length).setValues(res);
}

解决方案 2 - 上面行的值是 C 列的原始值

function copytestdata() {
  const ss = SpreadsheetApp.getActive();
  const sheet = ss.getSheetByName('Output');
  const values = sheet.getRange("C3:C"+sheet.getLastRow()).getValues().flat();
  const res = [];
  values.forEach((v,i)=>{
    if(i>0){
      if(v>values[i-1] || v==1){
         res.push([v]);
      }
      else{
         res.push([values[i-1]-1]);
      }
    }
    else{
         res.push([v]);
    }
  })
  sheet.getRange(3,4,res.length,res[0].length).setValues(res);
}

您的示例存在问题:

在这两种情况下,您提供的示例似乎都与您的解释不符。

假设你的序列是5 5 5 5...

根据方案2,第一个值为5(因为5之前没有值),第二个是4,因为前两个值相等。但是剩下的也是 4 个,因为你只有 5 个。

如果我们考虑第一个解决方案,那么您的值是 5 和 4,但第三个值是 5,因为 5 大于 4,依此类推。

【讨论】:

    【解决方案3】:

    感谢两位的回复!

    我实际上以某种方式设法创建了一个解决方案。我现在看到我的解释可能是错误的,因为我最终为我想要的结果做了一个 IF,上面的行的值 = 1。不是我在案例中陈述的 IF。

    我的代码可能与最佳实践相去甚远,并且可能在许多方面更好,更压缩,但它似乎正在工作..所以这就是我想出的:

      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Output');
      sheet.getRange("B2:B").copyTo(sheet.getRange("C2:C"), {contentsOnly:true});
      sheet.getRange("C1:C1").setValue("Header");
    
    var colc = "C";  
    
    var rovernr = 2;
    var thisnr = 3;
    var lastnr = sheet.getLastRow();
    
    var rowabove = colc+rovernr;
    var thisrow = colc+thisnr;
    
    var valueabove = sheet.getRange(rowabove).getValue();
    var thisvalue = sheet.getRange(thisrow).getValue();
    
    while (thisnr <= lastnr) {
    
    if(valueabove == 1) {
    sheet.getRange(thisrow).setValue(thisvalue);
    }
    
    else {
    sheet.getRange(thisrow).setValue(valueabove-1);
    }
        rovernr = rovernr+1;
        thisnr = thisnr+1;
        rowabove = colc+rovernr;
        thisrow = colc+thisnr;
    
      valueabove = sheet.getRange(rowabove).getValue();
      thisvalue = sheet.getRange(thisrow).getValue();
    
    }
    

    因此,对于每次迭代,我都“手动”在行号上,并为当前行和 x 上方的行获取新的单元格值)这是输入和输出:

    输入 2 2 4 4 4 4 1 3 3 3

    输出 2 1 4 3 2 1 1 3 2 1

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-12
      • 1970-01-01
      • 2013-06-19
      • 2011-02-19
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多