简体   繁体   中英

Assign a list of items a number (up to 50) in Google Apps Script

I have a list of items in column C that I would like to assign a different number value. An example list would look like:

Column C (Before) Column C (After)
Apple 0
Apple 0
Apple 0
Apple 0
Orange
Apple 0
Apple 0
Apple 0
Orange
Apple 0
Apple 0
Apple 0
Apple 0
Apple 0
Apple 0
Apple 0
Apple 0
Orange
Orange

It will assign "1" up until it reaches a maximum of 50 in the list.

For example, if there is under 50 "Apple 0" it will just do "Apple 1". But if there is more than 50, it will split evenly, "Apple 1" and "Apple 2".

In other words:

  • If less than 50 zeros are found, it automatically assigns the value "1" (Apple 0 --> Apple 1).

  • If greater than 50 but less than 100 zeros are found, it automatically assigns the values "1" and "2" evenly (Apple 0 --> Apple 1 x 50, Apple 2 x 50).

  • If greater than 100 but less than 150 zeros are found, it automatically assigns the values "1" "2" and "3" evenly.

  • If greater than 150 but less than 200 zeros are found, it automatically assigns the values "1" "2" "3" and "4" evenly, and so on.

I am trying to trigger this function from the menu with:

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

        }
    }

}

Error: Exception: The parameters (null,number) don't match the method signature for SpreadsheetApp.Sheet.getRange.

The result is skipping numbers rather than assigning properly. See console log results:

May 13, 2021, 5:21:59 PM Debug Case No: 2
May 13, 2021, 5:21:59 PM Debug AppleCount: 52
May 13, 2021, 5:21:59 PM Debug [ 26, 26 ]
May 13, 2021, 5:21:59 PM Debug Print Apple 1 at 6
May 13, 2021, 5:21:59 PM Debug Print Apple 1 at 8
May 13, 2021, 5:21:59 PM Debug Print Apple 1 at 10
May 13, 2021, 5:21:59 PM Debug Print Apple 1 at 12
May 13, 2021, 5:21:59 PM Debug Print Apple 1 at 14
etc... ...

We're almost there, it's just jumping 6, 8, 10 etc. -- but it's splitting batches equally which is a good sign.

Thank you!

Please note that as @doubleunary states, this is a simple enough task and spreadsheet formulas can do the magic. But if your case is something more than what you described then here is something to start with:

  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 ...

I have used this answer's method to equally distribute the no between your said cases(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;
}

and then you just need to print:

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

Obviously, you can use a lot of one-liner functions for most of the code mentioned above. The above code is just to maintain readability.

If I misunderstood your question or this is not what you wanted, I apologize.

Edit After Comment

  • Apple 1 in Adjacent Column: I am using sheet.getRange(i+2,2).setValue('Apple 1'); for your understanding so that the adjacent column gets the value.

You can simply change the col address in getRange() to (i+2,3) //or whatever your column index is.

  • printAppleCount() : This function is to print the values into required parts. You have equalSplits (an array of [37,38,38] ) and also have the lineAddresses(the row no. which had 'Apple 0') . You can loop through the values to print the Apple 1/2/3 with the exact count. And, The appleLineAddress will take care of the mixed data ie Apple, Orange, Strawberry, and then again Apple,...

Code:

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

Also, please refer to the Google Apps Script Documentation for better understanding. Cheers!

maybe:

=INDEX(IF(COUNTIFS(A:A, "Apple 0")<50, SUBSTITUTE(A:A, "Apple 0", "Apple 1"), 
 IF((COUNTIFS(A:A, "Apple 0")>=50 )*(COUNTIFS(A:A, "Apple 0")<100)*(A:A="Apple 0"), "Apple "&1+INT((COUNTIFS(A:A, A:A, A:A, "Apple 0", ROW(A:A), "<="&ROW(A:A))-1)/(COUNTIFS(A:A, "Apple 0")/2)), 
 IF((COUNTIFS(A:A, "Apple 0")>=100)*(COUNTIFS(A:A, "Apple 0")<150)*(A:A="Apple 0"), "Apple "&1+INT((COUNTIFS(A:A, A:A, A:A, "Apple 0", ROW(A:A), "<="&ROW(A:A))-1)/(COUNTIFS(A:A, "Apple 0")/3)), 
 IF((COUNTIFS(A:A, "Apple 0")>=150)*(COUNTIFS(A:A, "Apple 0")<200)*(A:A="Apple 0"), "Apple "&1+INT((COUNTIFS(A:A, A:A, A:A, "Apple 0", ROW(A:A), "<="&ROW(A:A))-1)/(COUNTIFS(A:A, "Apple 0")/4)), A:A)))))

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM