Search code examples
google-apps-scriptgoogle-sheetsrowcalculated-columns

Google script to allow selecting only 1 checkbox per row and 3 checkboxes per column


I want to make a Google Script on the following Google Sheet to allow only 1 checkbox selection per row, and 3 checkboxes selected per column as maximum, as described here.

If 2 checkboxes are selected on the same row, a pop-up window should be displayed, saying "Please select only 1 checkbox per row", and the last edit should be set to FALSE. Same if more than 3 checkboxes per column are selected (pop-up windows saying "This column has already 3 selections, please choose a different column", and set to FALSE the last edit).


Solution

  • This function imposes the restriction of only one check per row and 3 checks per column. You have to provide the arrayrange parameter A1Notation string and the sheet name. If you exceed the limits the last checkbox is returned to false and you get a warning in the format of a toast.

    function onEdit(e) {
      const sh=e.range.getSheet();
      if(sh.getName()=='You provide sheet name') {
        const mcpr=1;
        const mcpc=3;
        const arrayrange='A1:C10';//You provide A1Notation range string
        const arg=sh.getRange(arrayrange);
        const avs=arg.getValues();
        const ulr=arg.getRow();
        const ulc=arg.getColumn();
        const lrr=ulr+arg.getHeight()-1;
        const lrc=ulc+arg.getWidth()-1;   
        if(e.range.columnStart<=lrc && e.range.rowStart<=lrr && e.value=="TRUE") {
          let rc=avs[e.range.rowStart-ulr].filter(function(e){return e;}).reduce(function(a,v){ if(v){return a+1;} },0);
          if(rc>mcpr){e.range.setValue("FALSE");e.source.toast('Sorry maximum checks per row is ' + mcpr);};
          let cc=avs.map(function(r,i){return r[e.range.columnStart-ulc];}).filter(function(e){return e}).reduce(function(a,v){if(v){return a+1;}},0);
          if(cc>mcpc){e.range.setValue('FALSE');e.source.toast('Sorry maximum checks per column is ' + mcpc);};          
        }
      }
    }
    

    Animation:

    enter image description here

    Array Methods

    onEdit Event Block

    Your specific case:

    function onEdit(e) {
      const sh=e.range.getSheet();
      if(sh.getName()=='Sheet1') {
        const mcpr=1;
        const mcpc=3;
        const arrayrange='D3:AC7';
        const arg=sh.getRange(arrayrange);
        const avs=arg.getValues();
        const ulr=arg.getRow();
        const ulc=arg.getColumn();
        const lrr=ulr+arg.getHeight()-1;
        const lrc=ulc+arg.getWidth()-1;   
        if(e.range.columnStart<=lrc && e.range.rowStart<=lrr && e.value=="TRUE") {
          let rc=avs[e.range.rowStart-ulr].filter(function(e){return e;}).reduce(function(a,v){ if(v){return a+1;} },0);
          if(rc>mcpr){e.range.setValue("FALSE");e.source.toast('Sorry maximum checks per row is ' + mcpr);};
          let cc=avs.map(function(r,i){return r[e.range.columnStart-ulc];}).filter(function(e){return e}).reduce(function(a,v){if(v){return a+1;}},0);
          if(cc>mcpc){e.range.setValue('FALSE');e.source.toast('Sorry maximum checks per column is ' + mcpc);};          
        }
      }
    }
    

    Animation:

    enter image description here