首页 > 解决方案 > 在 Google Apps 脚本中为项目列表分配一个数字(最多 50 个)

问题描述

我在 C 列中有一个项目列表,我想分配一个不同的数值。示例列表如下所示:

C 列(之前) C 列(之后)
苹果 0
苹果 0
苹果 0
苹果 0
橙子
苹果 0
苹果 0
苹果 0
橙子
苹果 0
苹果 0
苹果 0
苹果 0
苹果 0
苹果 0
苹果 0
苹果 0
橙子
橙子

它将分配“1”直到列表中的最大值为 50

例如,如果“Apple 0”少于 50 个,它只会执行“Apple 1”。但如果超过 50 个,就会平分“Apple 1”和“Apple 2”。

换句话说:

我正在尝试从菜单中触发此功能:

function onInstall(e) {
    onOpen(e);
}

function onOpen() {
    var ui = SpreadsheetApp.getUi();

    ui.createMenu('Assign Values')
        .addItem('Assign Numbers to Zeroes (Max. 50)', 'assignNumbers')
        .addToUi();
}


function assignNumbers() {
    const sheet = SpreadsheetApp.getActiveSheet();
    var colC = sheet.getRange("C:C");
    var colCValues = colC.getValues();

    var appleCount = 0; // to store the apple count
    var appleLineAddress = []; // to store the row-no of Apple 0's

    // get the total count and and its row-no

    for (let i = 0; i < colCValues.length; i++) {
        if (colCValues[i][0] == "") continue;
        if (colCValues[i][0].toString().includes('Apple 0')) {
            appleCount++;
            appleLineAddress.push(i);
        }
    }

    // Check apple count and divide 

    if (appleCount < 50) {

        for (let i = 0; i < appleLineAddress.length; i++) {
            sheet.getRange(i + 5, 3).setValue('Apple 1');
        }

    } else if (appleCount > 50 && appleCount <= 100) {
        printAppleCount(2, appleCount, appleLineAddress);

    } else if (appleCount > 100 && appleCount <= 150) {
        printAppleCount(3, appleCount, appleLineAddress);

    } else if (appleCount > 150 && appleCount <= 200) {
        printAppleCount(4, appleCount, appleLineAddress);

    } else if (appleCount > 200 && appleCount <= 250) {
        printAppleCount(5, appleCount, appleLineAddress);

    } else if (appleCount > 250 && appleCount <= 300) {
        printAppleCount(6, appleCount, appleLineAddress);
    }

}



function printAppleCount(caseNo, appleCount, appleLineAddress) {

    const sheet = SpreadsheetApp.getActiveSheet();
    var splitInteger = function numParts(num, parts) {
    var val;
    var mod = num % parts;
    if (mod == 0) {
        val = num / parts;
        retData = Array(parts).fill(val);
    } else {
        val = (num - mod) / parts;
        retData = Array(parts).fill(val);
        for (i = 0; i < mod; i++) {
            retData[i] = retData[i] + 1;
        }
        retData.reverse()
        //Comment the above line to unreverse the result.
    }
    return retData;
}

    console.log("Case No: " + caseNo);
    console.log("AppleCount : " + appleCount);
    var equalSplits = splitInteger(appleCount, caseNo);

    console.log(equalSplits);

    // for the applecount: 113(suppose), the var equalSplits will log [37,38,38].
    // You can print the data now with the equalSplits and appleLineAddress

    var k = 0;
    for (var i = 0; i < equalSplits.length; i++) {

        for (var j = 0; j < equalSplits[i]; j++) {
            console.log('Print Apple ' + (i + 1) + ' at ' + appleLineAddress[k++]);
            sheet.getRange(appleLineAddress[k++], 3).setValue('Apple ' + (i + 1));

        }
    }

}

错误:异常:参数 (null,number) 与 SpreadsheetApp.Sheet.getRange 的方法签名不匹配。

结果是跳过数字而不是正确分配。查看控制台日志结果:

2021 年 5 月 13 日下午 5:21:59 调试 案例编号:2
2021 年 5 月 13 日下午 5:21:59 调试 苹果数:52
2021 年 5 月 13 日下午 5:21:59 调试 [ 26, 26 ]
2021 年 5 月 13 日下午 5:21:59 调试 在 6 点打印 Apple 1
2021 年 5 月 13 日下午 5:21:59 调试 8 点打印 Apple 1
2021 年 5 月 13 日下午 5:21:59 调试 10 点打印 Apple 1
2021 年 5 月 13 日下午 5:21:59 调试 12 点打印 Apple 1
2021 年 5 月 13 日下午 5:21:59 调试 在 14 点打印 Apple 1
ETC... ...

我们快到了,它只是跳跃 6、8、10 等等——但它正在平均分配批次,这是一个好兆头。

谢谢!

标签: javascriptgoogle-apps-scriptgoogle-sheets

解决方案


请注意,正如@doubleunary 所说,这是一项非常简单的任务,而电子表格公式可以做到这一点。但是,如果您的情况超出了您所描述的范围,那么可以从以下内容开始:

  var colA = sheet.getRange("A:A"); 
  var colAValues = colA.getValues();
  
  var appleCount = 0;         // to store the apple count
  var appleLineAddress = [];  // to store the row-no of 'Apple 0's.

  // get the total count and and its row-no
  for(let i=0; i<colAValues.length; i++){
    if(colAValues[i][0] == "") continue;
    if(colAValues[i][0].toString().includes('Apple'))
    {
      appleCount++;
      appleLineAddress.push(i);
    }
  } 
  
  // Check apple Count and Divide 
  if(appleCount < 50)
  {
    for(let i = 0; i<appleLineAddress.length; i++)
    {
      sheet.getRange(i+2,2).setValue('Apple 1');
    }
  } 
  else if(appleCount >= 50 && appleCount <100)
  {
    printAppleCount(2,appleCount,appleLineAddress);    
  } 
  else if(appleCount >= 100 && appleCount <150)
  {
    printAppleCount(3,appleCount,appleLineAddress)
  } 
  else if(appleCount >= 150 && appleCount <200)
  {
    printAppleCount(4,appleCount,appleLineAddress);
  }
  else ...

我已使用此答案的方法在您所说的案例(1,2,3,4,...)之间平均分配否

var splitInteger = function(num, parts) {
   var val;
  var mod = num % parts;
  if(mod == 0){
    val = num/parts;
    retData = Array(parts).fill(val);
  } else {
    val = (num-mod)/parts;
    retData = Array(parts).fill(val);
    for(i=0;i<mod;i++){
      retData[i] = retData[i] + 1;
    }
    retData.reverse()
    //Comment the above line to unreverse the result.
  }
  return retData;
}

然后你只需要打印:

function printAppleCount(caseNo, appleCount, appleLineAddress){
  console.log("Case No: "+caseNo);
  console.log("AppleCount : "+appleCount);
  var equalSplits = splitInteger(appleCount, caseNo);
  
  console.log(equalSplits);
  // for the applecount : 113(suppose), the var equalSplits will log [37,38,38].

  // You can print the data now with the equalSplits and appleLineAddress
  .
  .
  .
}

显然,对于上面提到的大多数代码,您可以使用很多单行函数。上面的代码只是为了保持可读性。

如果我误解了你的问题或者这不是你想要的,我很抱歉。

评论后编辑

  • 相邻列中的 Apple 1:我正在使用sheet.getRange(i+2,2).setValue('Apple 1');以供您理解,以便相邻列获得值。

您可以简单地更改col address in getRange()(i+2,3) //or whatever your column index is.

  • printAppleCount():此函数用于将值打印到所需部分。您拥有equalSplits (an array of [37,38,38] )并且也拥有lineAddresses(the row no. which had 'Apple 0'). 您可以遍历这些值以打印具有精确计数的 Apple 1/2/3。并且,appleLineAddress将处理混合数据,即 Apple、Orange、Strawberry,然后是 Apple,...

代码:

var k = 0;
for(var i=0; i<equalSplits.length; i++){
 for(var j=0; j<equalSplits[i]; j++)
 {
  console.log('Print Apple '+(i+1)+' at'+appleLineAddress[k++]);
  sheet.getRange(appleLineAddress[k++],3).setValue('Apple '+(i+1)); 
 }
}

此外,请参阅Google Apps 脚本文档以获得更好的理解。干杯!


推荐阅读