7
votes

I have a form that my users enter data and I use onFormSubmit to trigger a script that creates a CSV based on the data inserted and after I create the CSV file I delete the data. Problem is that I am deleting the data before creating CSV file. Usually I would just make a promise call but I think it is not possible with Google Apps Script. Is there any alternative to it?

So my complete code is here:

More insight about what it does: When I receive a new form entry, the "Avaliacao" sheet gets updated and will trigger testTrigger().

Then, it will write the email and the usercity in the LastUser city so it can lookup for some data that I will use to build my CSV file. But the saveAsCsv function is called before the sheet completed its VLOOKUP calls. So my CSV file is empty.

Another issue that I have with synchronization is that if I enable the sLastUser.clear(); line it will also delete before creating the CSV.

function testTrigger () {
  //open the sheets
  var SS = SpreadsheetApp.getActiveSpreadsheet();
  var sAvaliacao = SS.getSheetByName("Avaliação");  
  var sPreCSV = SS.getSheetByName("PreCSV");  
  var sInput = SS.getSheetByName("Input");    
  var sLastUser = SS.getSheetByName("LastUser"); 
  var dAvaliacao = sAvaliacao.getDataRange().getValues();
  var dInput = sInput.getDataRange().getValues();

  var avaliacaoLastRow = sAvaliacao.getLastRow()-1;

  var userEmail = dAvaliacao[avaliacaoLastRow][2];
  var userCity = dAvaliacao[avaliacaoLastRow][5];
  var userId = dInput[3][52];

  sLastUser.appendRow([userEmail, userCity]);

  saveAsCSV(userId);
//  sLastUser.clear();   <== this is the line where I can`t enable
}

function saveAsCSV(csvName) {
  // Name
  var fileName = String(csvName) + ".csv"
  // Calls convertcsv
  var csvFile = convertOutputToCsv_(fileName);
  // create the file on my drive
  DriveApp.createFile(fileName, csvFile);
}

function convertOutputToCsv_(csvFileName) {
  // open sheets
  var sPreCSV = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PreCSV");
  var cont = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Input").getDataRange().getValues()[3][50] + 1;

  var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PreCSV").getRange(1, 1, cont, 3);
  try {
    var data = ws.getValues();
    var csvFile = undefined;

    // Loop through the data in the range and build a string with the CSV data
    if (data.length > 1) {
      var csv = "";
      for (var row = 0; row < data.length; row++) {
        for (var col = 0; col < data[row].length; col++) {
          if (data[row][col].toString().indexOf(",") != -1) {
            data[row][col] = "\"" + data[row][col] + "\"";
          }
        }

        // Join each row's columns
        // Add a carriage return to end of each row, except for the last one
        if (row < data.length-1) {
          csv += data[row].join(",") + "\r\n";
        }
        else {
          csv += data[row];
        }
      }
      csvFile = csv;
    }
    return csvFile;
  }
  catch(err) {
    Logger.log(err);
    Browser.msgBox(err);
  }
}
3
what did you do before promises?omarjmh
You will need to show us your code for us to be able to help. You can likely use a callback to know when some operation is done. We'd have to see the exact code/API you are using to know if promises are supported. FYI, questions about your code should nearly always include your actual code. You will get 10x better answers if we can see your actual code rather than trying to answer a vague and hypothetical question.jfriend00
@jfriend00, thank you for the advice. I edited my post with the codeHugo Nakamura
I'd try inserting SpreadsheetApp.flush(); before the line with clearuser3717023

3 Answers

6
votes

Indeed, the JS engine used by Google Apps Script does not support promises (Logger.log(Promise); shows it's undefined).

To make sure that spreadsheet changes take effect before proceeding further, you can use SpreadsheetApp.flush().

Another relevant feature is event object passed by the trigger on Form Submit: it delivers the submitted data to the script without it having to fish it out of the spreadsheet.

6
votes

Now with engine v8 Promise is defined object

2
votes

There are no native Promises in GAS. With that said you can write your code in ES6/ESnext and make use of promises that way. To see how you can configure modules to expose the to the global scope see my comment here.

By doing this you can take advantage of promises. With that said depending on the size of your project this may be overkill. In such a case I'd advise using simple callbacks if possible.