Search code examples
google-apps-scriptparameter-passinggoogle-apps-script-editor

Passing parameters in apps script


Based on https://www.plivo.com/blog/Send-templatized-SMS-from-a-Google-spreadsheet-using-Plivo-SMS-API/ I have the following code:

data = {
    "SOURCE" : "+1234567890",
    "DESTINATION" : "+2345678901",
    "FIRST_NAME" : "Jane",
    "LAST_NAME" : "Doe",
    "COUPON" : "DUMMY20",
    "STORE" : "PLIVO",
    "DISCOUNT" : "20",
}

template_data = "Hi   FIRST_NAME , your coupon code for discount of % purchase at  is "

function createMessage(data,template_data){
  Logger.log(data);

  for (var key in data) {
    Logger.log(key);

    if (data.hasOwnProperty(key)) {
      template_data = template_data.replace(new RegExp('+key+', 'gi'), data[key]);
    }
  }
  Logger.log(template_data);
  return template_data;
}

When I run createMessage and check the logs I see:

[18-10-02 13:19:03:139 EDT] undefined
[18-10-02 13:19:03:139 EDT] undefined

This suggests to me that the parameters are not being passed into the function. What am I doing wrong?


Solution

  • Running a function in the Script Editor does not pass arguments to the function. Currently, you have 3 user objects in your project's global namespace (among others from Google):

    • createMessage (a function object)
    • template_data (a string)
    • data (an object).

    The line function createMessage(data, template_data) declares the object createMessage to be a function object, and indicates that the first two arguments passed to the function are known within the function's scope as data and template_data, respectively. These function-scope argument declarations shadow any more-distant declarations (i.e. from global scope or an enclosing function scope).

    The solution is then to either write a "driver function" that you actually execute, in which you define the input parameters to your called functions, or to remove the parameters from the function call:

    var data = {...}; // global var
    var template_data = {...}; // global var
    function driver() {
      createMessage(data, template_data); // uses the globally scoped `data` & `template_data` objects
      var otherdata = 1,
          otherTemplate = 2;
      createMessage(otherdata, otherTemplate); // uses the function-scoped `otherdata` and `template_data` objects
    }
    function createMessage(someData, someTemplate) {
      Logger.log(someData);
      Logger.log(arguments[0]); // equivalent to the above line.
      // ...
    }
    

    Avoiding reference shadowing:

    function createMessage() { // removed `arguments` reference binding
      Logger.log(data);  // accesses global-scope `data` object because there is no `data` reference in the nearest scope
    

    To help with this scenario - preventing manual execution via the Script editor of functions needing parameters - I will generally make the functions private by adding a trailing _ to the name: function cantBeRunManually_(arg1, arg2, arg3) { ... }

    References: