0

I have a Google App Script Code code that asks the user to input some values through an html custom dialog. The button in the dialog triggers a function in the .gs file, and I want to wait for that triggered function to return before I continue the rest of the code.

  function main () {
      selectSheets (); 
      //Below are the functions that I need openSheets to return before calling them (I'm not including their implementation here, as I don't think it's needed):
      categoriesAndScoresDictionary = getCategoriesDictionary(); 
      categoriesEntries = getCategoriesEntries(categoriesAndScoresDictionary); 
      //and other functions..

    }

function selectSheets () {

  var htmlDialog = HtmlService.createTemplateFromFile("sheets_menu")
  var spreadsheets = SpreadsheetApp.getActiveSpreadsheet().getSheets(); 
  var sheetsArray = []; 

  for (index in spreadsheets) {
    sheetsArray.push(spreadsheets [index].getSheetName());  
  }

  htmlDialog.sheetsArray = sheetsArray; 

  var html = htmlDialog.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setWidth(300); 

  SpreadsheetApp.getUi().showModalDialog(html, "Select sheets names");
  return html
}

The below function gets called through onclick in html and I want to wait for it to return before continuing the execution in the main function:

function openSheets (appsSelection, rubricsSelection) {

  var spreadsheetFile = SpreadsheetApp.getActiveSpreadsheet(); 
  Logger.log(appsSelection + " " + rubricsSelection); 

  //Open the sheet by name inside the opened Spreadsheet (inside the file)
  //Open applications sheet: 
  applicationsSheet = spreadsheetFile.getSheetByName(appsSelection);

  //Open rubrics sheet: 
  rubricsSheet = spreadsheetFile.getSheetByName(rubricsSelection);
  //This function gets called from the html side and it runs successfully, I need to wait for it to return before executing other functions called in main () 

}

This is the html:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <input type = "hidden" value="<?!= sheetsArray ?>" id= "sheetsArray"/>

    <br>
    <p>Select the name of the applications sheet:</p>
     <select id = "sheetsList">

     </select>
     <br>
     <p>Select the name of the rubrics sheet:</p>

     <select id = "sheetsList2">

     </select>

     <br><br><br>
    <center><input type= "button" value = "Confirm" onclick ="sendSelectionToJs()"/></center>

    <script> 
     // Create the list element:
     function fillSelection () {
     var firstMenu = document.getElementById("sheetsList"); 
     var secondMenu = document.getElementById("sheetsList2"); 

     var holderArray = document.getElementById ("sheetsArray").value; 
     var sheetsArray = holderArray.split(","); 

    for (var i = 0; i<sheetsArray.length; i++){
    var option = document.createElement("option");
    option.value = sheetsArray[i];
    option.innerHTML = sheetsArray[i];
    firstMenu.appendChild(option);    
    }

    for (var i = 0; i<sheetsArray.length; i++){
    var option = document.createElement("option");
    option.value = sheetsArray[i];
    option.innerHTML = sheetsArray[i];
    secondMenu.appendChild(option);    
    }
  }


    function sendSelectionToJs() {

    var appsSelection = document.getElementById ("sheetsList").value; 
    var rubricsSelection = document.getElementById ("sheetsList2").value; 
     google.script.run.openSheets(appsSelection, rubricsSelection); 
     google.script.host.close(); 

    }

    fillSelection (); 

    </script> 
  </body>
</html>

I tried the idea of having openSheets changes a flag value and I kept checking the flag value before executing the rest of the functions inside the main, but although the value changes inside openSheets, it never changes globally.

EDIT: What I'm trying to do is to ask the user to select the sheet names to process (they should select 2) through an html dialog, then open those sheets through openSheets. The remaining functions called in main () needs to know the sheets names, that's why I need to wait for openSheets to return.

Thanks.

Rubén
  • 34,714
  • 9
  • 70
  • 166
Dania
  • 1,648
  • 4
  • 31
  • 57
  • 1
    [ClientToServerCommunication](https://developers.google.com/apps-script/guides/html/communication) – Cooper Apr 25 '20 at 21:53
  • This is confusing. *want to wait for that triggered function to return before I continue the rest of the code.* *before continuing the execution in the main*. But you're calling `openSheets` function only. Right? Why would `main` function even run? – TheMaster Apr 25 '20 at 22:36
  • Please remove promises code or show original code along with promises modifications. Server side is synchronous. Promises won't work or do anything. I was expecting promises on the client side. Regardless, back off a bit and explain your original problem: why exactly do you want to wait? What problem led you to this as solution? – TheMaster Apr 25 '20 at 22:39
  • 1
    Does this answer your question? [Auto close modal dialog - After server code is done, close dialog in Google Spreadsheet](https://stackoverflow.com/questions/32527682/auto-close-modal-dialog-after-server-code-is-done-close-dialog-in-google-spre) – Rubén Apr 25 '20 at 22:40
  • @TheMaster I provided the original code, added some comments that will help clarify things, and added a text at the end to clarify why I need this. – Dania Apr 25 '20 at 22:51
  • @Rubén thanks but I don't need the dialog to wait till the code is run by the server, but I need the server to wait till openSheets returns then runs the remaining functions. So, if I'll use Success handlers as suggested by you and Cooper, do you mean that I can call a function that contains all reminding methods on the server from the success handler and by that I can maintain the required sequence? – Dania Apr 25 '20 at 22:57
  • You can put google.script.run calls in side of each other via the withSuccessHandler in order to achieve sequential execution. Personally I find it easier to accomplish by using anonymous functions rather than external functions. `google.script.run.withSuccessHandler(function(){google.script.run.withSuccessHandler(function(){etc....}).runTwo()}).runOne()` It can get complex but I've used in situation where I won't to be results from spreadsheets that are based upon data that is coming from a webapp. – Cooper Apr 26 '20 at 01:59
  • [This](https://stackoverflow.com/a/57200844/) might be helpful. – TheMaster Apr 26 '20 at 06:10
  • Can't you just write all `main()` content (excluding `selectSheets()`) at the end of `openSheets`, start the script by executing `selectSheets()` instead, and get rid of `main()`? – Iamblichus Apr 27 '20 at 09:54

1 Answers1

1

It's not possible to make that the server side code waits for client side code to finish. IMHO you should change the logic of your script:

  1. Use a server side function to open a dialog / sidebar. Usually this kind of functions will not include something else as the dialog / sidebar opening is asynchronous.
  2. The client side code should call a server-side function which may return a supported JavaScript object. This server function could be used to call other server functions that should run synchronously (in a specific order).

Related

Rubén
  • 34,714
  • 9
  • 70
  • 166