google-apps-scriptgoogle-sheetscustom-function

Refresh data retrieved by a custom function in Google Sheet


I've written a custom Google Apps Script that will receive an id and fetch information from a web service (a price).

I use this script in a spreadsheet, and it works just fine. My problem is that these prices change, and my spreadsheet doesn't get updated.

How can I force it to re-run the script and update the cells (without manually going over each cell)?


Solution

  • Ok, it seems like my problem was that google behaves in a weird way - it doesn't re-run the script as long as the script parameters are similar, it uses cached results from the previous runs. Hence it doesn't re-connect to the API and doesn't re-fetch the price, it simply returns the previous script result that was cached.

    See more info here(Add a star to these issues, if you're affected):

    and Henrique G. Abreu's answer

    My solution was to add another parameter to my script, which I don't even use. Now, when you call the function with a parameter that is different than previous calls, it will have to rerun the script because the result for these parameters will not be in the cache.

    So whenever I call the function, for the extra parameter I pass "$A$1". I also created a menu item called refresh, and when I run it, it puts the current date and time in A1, hence all the calls to the script with $A$1 as second parameter will have to recalculate. Here's some code from my script:

    function onOpen() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet();
      var entries = [{
        name : "Refresh",
        functionName : "refreshLastUpdate"
      }];
      sheet.addMenu("Refresh", entries);
    };
    
    function refreshLastUpdate() {
      SpreadsheetApp.getActiveSpreadsheet().getRange('A1').setValue(new Date().toTimeString());
    }
    
    function getPrice(itemId, datetime) {
      var headers =
          {
            "method" : "get",
            "contentType" : "application/json",
            headers : {'Cache-Control' : 'max-age=0'}
          };
    
      var jsonResponse = UrlFetchApp.fetch("http://someURL?item_id=" + itemId, headers);
      var jsonObj = eval( '(' + jsonResponse + ')' );
      return jsonObj.Price;
      SpreadsheetApp.flush();
    }   
    

    And when I want to put the price of item with ID 5 in a cell, I use the following formula:

    =getPrice(5, $A$1)
    

    When I want to refresh the prices, I simply click the "Refresh" -> "Refresh" menu item. Remember that you need to reload the spreadsheet after you change the onOpen() script.