0
votes

I've been creating inventory spreadsheets to help my dad's employees with year end inventory. A user filling out inventory will enter data into a few cells in a sheet titled "Form", and will then select "SUBMIT" from a dropdown box located on the form. The script then uses the form to make the following changes to a sheet titled "MSPL":

  • Inserts a new row in a specific location, based on data entered in the form
  • Copies data from the form into the cells of the new row

This works 95% of the time. However, sometimes the script seems to run parts of itself a second time. I have watched the spreadsheet changes being made in real time and it seems to: add a new row, copy data into the first 3 cells, create a 2nd row above the 1st one created, copy the entire data into this row. With there being only 1 "insertRowAfter" line in the code, I can't figure out why the code would be inserting two.

function msplFormSubmit() {

  var form = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MSPL Form");
  var mspl = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MSPL");
  var formWIP = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MSPL WIP Form");
  var msplWIP = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MSPL WIP");
  var Pricing = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Pricing")

  if (form.getRange("E2").getValue() == "SUBMIT") {

    var sectionName = form.getRange("C5").getValue() + '"' + " " + form.getRange("C3").getValue() + " - SUBTOTAL";
    var rowSearch = mspl.getRange("B:B").getValues();
    var rowID = 0
    var unitCost = Pricing.getRange("B3:D").getValues();

    form.getRange("E2").clearContent();
    form.getRange("C10").clearContent();
    form.getRange("B10").setValue("Processing ...")

    for (i = 0; i < mspl.getLastRow(); i ++) {
      if (rowSearch[i] != sectionName) {
        rowID += 1
      } else {
        break;
      }
    }

    mspl.insertRowAfter(rowID)

    rowID += 1 //rowID now points to the newly added row, in order to populate it

    if (mspl.getRange(rowID - 1, 2, 1, 1).getBackground() === "#ffffff") {
      mspl.getRange(rowID, 2, 1, 10).setBackground("#dcdcdc")
    }
    if (mspl.getRange(rowID - 1, 2, 1, 1).getBackground() === "#dcdcdc") {
      mspl.getRange(rowID, 2, 1, 10).setBackground("#ffffff")
    }

    mspl.getRange(rowID, 2, 1, 1).setValue(form.getRange("C2").getValue()); //Tag #
    mspl.getRange(rowID, 3, 1, 1).setValue(form.getRange("C3").getValue()); //Description
    mspl.getRange(rowID, 4, 1, 1).setValue(form.getRange("C4").getValue()); //Quantity
    mspl.getRange(rowID, 5, 1, 1).setValue(form.getRange("C5").getValue()); //Thickness
    mspl.getRange(rowID, 5, 1, 1).setNote(mspl.getRange(rowID-1, 5, 1, 1).getNote()); //Thickness Note
    mspl.getRange(rowID, 6, 1, 1).setValue(form.getRange("C6").getValue()); //Width
    mspl.getRange(rowID, 7, 1, 1).setValue(form.getRange("C7").getValue()); //Length
    mspl.getRange(rowID, 8, 1, 2).setFormulasR1C1(mspl.getRange(rowID-1, 8, 1, 2).getFormulasR1C1()); //Area and Weight Formulas
    mspl.getRange(rowID, 11, 1, 1).setFormulasR1C1(mspl.getRange(rowID-1, 11, 1, 1).getFormulasR1C1()); //Cost Formula

    for (i = 0; i < unitCost.length; i ++) {
      if (unitCost[i][0] == form.getRange("C3").getValue() && unitCost[i][1] == form.getRange("C5").getValue()) {
        mspl.getRange(rowID, 10, 1, 1).setValue(unitCost[i][2]);
        break;
      }
    }

    mspl.getRange(rowID, 10 ,1, 1).setNumberFormat("$0.0000")

    form.getRange("C2:C7").clearContent();
    form.getRange("B10").clearContent();
    form.getRange("C10").setValue("READY");
    }
}
2
What do you mean by select "SUBMIT" from a dropdown box located on the form? Is this data validation? How do msplFormSubmit() is called? - Rubén
There is a data validation box on the form sheet, which contains only "SUBMIT" as an option. the msplFormSubmit() is linked to an onEdit trigger, so every time the spreadsheet is edited the script runs (and checks if cell E2 on form says submit). Not very elegant. - Nosliw
I don't see any logging or error handling code in your code. This is basically a debugging question at this point. You need to isolate where the problem is coming from by debugging your code. Read the troubleshooting guide. Link to Apps Script troubleshooting guide Information about try/catch Link to Try/Catch info - Alan Wells

2 Answers

0
votes

Instead of using data validation together with an edit installable trigger, use a custom menu or a clickable image. For details see Custom menus in Google Sheets.

Another alternative could be to change the value of the cell with the data validation immediately after (form.getRange("E2").getValue() == "SUBMIT") is evaluated / before any other change be made by the script.

0
votes

I noticed that you specified a range in the following way:

var unitCost=Pricing.getRange("B3:D").getValues();

I'm thinking it might be that sometimes this range may go well beyond your data so perhaps you can specify it like this:

var unitCost=Pricing.getRange(3,2,Pricing.getLastRow(),4);

Note: I'm not saying that this is the problem I'm just going through your code and seeing how I might write the same thing.

Note:

for (i=0;i<unitCost.length;i++){
      if(unitCost[i][0]==form.getRange("C3").getValue() && unitCost[i][1]==form.getRange("C5").getValue()){
        mspl.getRange(rowID, 10).setValue(unitCost[i][2]);
        break;
      }
    }

This code could take a long time to run if you have 1000 rows below the bottom of your data. in range 'B3:D';

You only need to get one formula here:

//mspl.getRange(rowID, 11).setFormulasR1C1(mspl.getRange(rowID-1, 11).getFormulasR1C1()); //Cost Formula
    mspl.getRange(rowID, 11).setFormulaR1C1(mspl.getRange(rowID-1,11).getFormulaR1C1()); //Cost Formula

Here's you code after some minor tweaking. Not sure it's worth anything but I also included a menu function in there that might save you some time.

//you can change this to opOpen() or connected it up to an onOpen() trigger in the edit menu/current project's triggers.
function runFormSubmitMenu(){ 
  SpreadsheetApp.getUi().createMenu('My Tools')
      .addItem('Submit', 'msplFormSubmit')
      .addToUi();
}


function msplFormSubmit(){
  var ss=SpreadsheetApp.getActiveSpreadsheet();
  var form = ss.getSheetByName("MSPL Form");
  var mspl = ss.getSheetByName("MSPL");
  var formWIP = ss.getSheetByName("MSPL WIP Form");
  var msplWIP = ss.getSheetByName("MSPL WIP");
  var Pricing = ss.getSheetByName("Pricing")

  if (form.getRange("E2").getValue()=="SUBMIT"){
    var sectionName=form.getRange("C5").getValue() + '" ' + form.getRange("C3").getValue() + " - SUBTOTAL";
    var rowSearch=mspl.getRange("B:B").getValues();
    var rowID=0;
    //var unitCost=Pricing.getRange("B3:D").getValues();
    var unitCost=Pricing.getRange(3,2,Pricing.getLastRow(),4);
    form.getRange("E2").clearContent();
    form.getRange("C10").clearContent();
    form.getRange("B10").setValue("Processing ...");

    for(var i=0;i<mspl.getLastRow();i++){
      if(rowSearch[i]!=sectionName){
        rowID++;
      } else {
        break;
      }
    }
    mspl.insertRowAfter(rowID);
    rowID++; 
    if (mspl.getRange(rowID - 1, 2).getBackground()=="#ffffff"){
      mspl.getRange(rowID, 2, 1, 10).setBackground("#dcdcdc");
    }
    if (mspl.getRange(rowID - 1, 2).getBackground()==="#dcdcdc"){
      mspl.getRange(rowID, 2, 1, 10).setBackground("#ffffff");
    }
    mspl.getRange(rowID, 2).setValue(form.getRange("C2").getValue()); //Tag #
    mspl.getRange(rowID, 3).setValue(form.getRange("C3").getValue()); //Description
    mspl.getRange(rowID, 4).setValue(form.getRange("C4").getValue()); //Quantity
    mspl.getRange(rowID, 5).setValue(form.getRange("C5").getValue()); //Thickness
    mspl.getRange(rowID, 5).setNote(mspl.getRange(rowID-1, 5, 1, 1).getNote()); //Thickness Note
    mspl.getRange(rowID, 6).setValue(form.getRange("C6").getValue()); //Width
    mspl.getRange(rowID, 7).setValue(form.getRange("C7").getValue()); //Length
    mspl.getRange(rowID, 8, 1, 2).setFormulasR1C1(mspl.getRange(rowID-1, 8, 1, 2).getFormulasR1C1()); //Area and Weight Formulas
    mspl.getRange(rowID, 11).setFormulaR1C1(mspl.getRange(rowID-1,11).getFormulaR1C1()); //Cost Formula


    for (i=0;i<unitCost.length;i++){
      if(unitCost[i][0]==form.getRange("C3").getValue() && unitCost[i][1]==form.getRange("C5").getValue()){
        mspl.getRange(rowID, 10).setValue(unitCost[i][2]);
        break;
      }
    }
    mspl.getRange(rowID,10).setNumberFormat("$0.0000");
    form.getRange("C2:C7").clearContent();
    form.getRange("B10").clearContent();
    form.getRange("C10").setValue("READY");
    }
}

You'll probably have to figure this one out on your own. Trying using the Logger.log() function. It's pretty useful and take a look at the execution logs.

If this isn't particularly useful to you leave me a comment and I'll just delete it because I think people are more inclined to answer questions that don't have many answers.