简体   繁体   中英

Javascript Wait for Dynamic Input

I am using a variation of a script to generate random numbers in multiple columns of a spreadsheet , as shared by Tim Cooper on stackoverflow, which works by selecting any range of contiguous cells and running the script from an onOpen menu.

The variation is implemented as a custom function in Google Sheets and uses values from an INPUT column (A) as maximum values for random numbers generated in the adjacent OUTPUT column (B), which in turn are used by the spreadsheet to derive the subsequent INPUT values. A simplified example:

The custom function reads A1 and writes a random number between 0 and A1 (80) in B1. A2 is then calculated by adding 10 to B1, etc.

     |  A  |  B  |
  1  | 80  | 75  |
  2  | 85  | 63  |
  3  | 73  | 52  |
  4  | 62  | 40  |
  5  | 50  | 25  |

The problem is that the spreadsheet needs some time to fill in the next input value (in this case, A2), which will produce errors when it is too slow to supply the input for the custom function to calculate the random value in the next row.

As is, the custom function is a single block of code which identifies the active sheet and range of cells. It then loops through the number of rows, retrieving input values, determining the random values and writing them to the adjacent cells.

function generate_random_numbers()
{
  var sheet = SpreadsheetApp.getActiveSheet()
  var range = sheet.getActiveRange()
  var counter = 0

  for (var y = 1; y <= range.getHeight(); y++)
  {
   counter = counter + 1
   if (counter != 3)
   {
    var maximum = range.getCell(y, 1).getValue()
    var random = (maximum != 0) ? Math.floor(Math.random() * maximum) + 1: 0
   }
    else
   {
    random = ""
    counter = 0
   }
   range.getCell(y, 2).setValue(random)
  }
}

I looked into splitting the function into a seperate part which retrieves the values, with an isNaN check to determine success and in case of failure setTimeout the function for 100. Unfortunately, Google Apps Script doesn't seem to support setTimeout.

I'd appreciate suggestions on how to get a spreadsheet and a script which uses dynamic values to work smoothly together.

The problem is in Google Apps Script's look-ahead caching, which limits custom functions to those values which were present in a spreadsheet at the time the custom function was invoked.

It is possible to use SpreadsheetApp.flush() to update the cache -- writing out the new values calculated by the custom function to the spreadsheet and reading in the resulting values from the spreadsheet into the cache -- but the approach is slow as it needs to be done repeatedly to keep the cache fresh and even then some cells in the spreadsheet may get stuck "Loading..."

In the end, I chose to move all the calculations from the spreadsheet into custom functions. It took some learning, but it is much faster and never freezes. By storing the values in global arrays (per character and into rounds and values referenced by easily named global constants instead of numbers) and isolating the calculations in their own functions, it is easy to manage and tinker with.

As the fundamental issue was never resolved, but rather side-stepped, I posted the issue on Google's Apps Script Issues and Requests , per a suggestion by Sandy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM