谷歌电子表格公式/函数来获得随机值,无需重新计算(RANDBETWEEN)

问题描述 投票:0回答:2

我想才达到以下。在谷歌sparesheet我有一个表与价值观“所有值”,在另一片“随机值”我想从表“AllValues”获得随机值。

我已经尝试了两种选择,一开始我尝试RANDBETWEEN公式:

=INDEX(AllValues!A4:A103,RANDBETWEEN(1,COUNTA(AllValues!A4:A103)),1)

这是工作,但它刷新/重新计算所有的时间列被改变的新值。 Googeled了很多,似乎没有太多的做冻结已经计算结果。

接下来,我试图函数:

    function random() {
      var sss = SpreadsheetApp.getActiveSpreadsheet();
      var ss = sss.getSheetByName('Values'); //the sheet that has the data
      var range = ss.getRange(1,1,ss.getLastRow(), 4); //the range you need: 4 columns on all row which are available
      var data = range.getValues();

      for(var i = 0; i < data.length; i++) 
      { 
        var j = Math.floor(Math.random()*(data[i].length)); //method of randomization
        var element = data[i][j]; // The element which is randomizely choose
        ss.getRange(i+1, 6).setValue(element); 
      }
    }

但是,这个功能不是为我工作,谷歌sparesheet给出了11行错误,即setVaue是不允许的。

11号线:ss.getRange(i+1, 6).setValue(element);

太Google搜索这一块,有很多建议,但我不是很熟悉的功能,我没有设法得到它的工作。

希望有人能帮助我。

google-apps-script google-sheets custom-function google-sheets-formula
2个回答
1
投票

使用公式通常假定重复计算。你无法阻止他们,只能试图返回旧值来代替。这个任务是不平凡的,因为任何公式不能指其中的结果将被返回(圆形引用发生)相同的小区。不要使用单一的时间计算公式。

在另一方面,使用脚本功能,可以直接且仅一次或按需生成所需的数据。我想,下面的功能将帮助您了解所有样品源和目标范围内的neccesary步骤。

function random() {
  var source = "AllValues!A4:A103",
      target = "RandomValues!F2:F22";
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sourceValues = ss.getRange(source).getValues(),
      targetRange = ss.getRange(target),
      targetValues = [];
  while (targetValues.length < targetRange.getHeight()) {
    var randomIndex = Math.floor(Math.random() * sourceValues.length);
    targetValues.push(sourceValues[randomIndex]);
  }
  targetRange.setValues(targetValues);
}

您可以手动运行,或选择合适的触发。


1
投票

有实现这个目标的多种方式。

自定义菜单

正如@Tanaike提到的,你能避免重新计算,并通过使用自定义菜单式依赖性:

// @OnlyCurrentDoc
// Create a function that binds the "simple trigger" for the open event:
function onOpen(e) {
  // Add a menu to the UI with the function we want to be able to invoke.
  const ui = SpreadsheetApp.getUi();
  ui.createMenu("Randomizer")
    .addItem("Sample from 'AllValues' sheet", "sampleAllValues")
    .addToUi();
}

那么你需要一个函数定义匹配这个名字sampleAllValues,并且当用户选择关联菜单选项,它会随着点击用户的权限调用(用户将首先提示每脚本的OAuth范围接入提供同意书) 。

function sampleAllValues() {
  const wb = SpreadsheetApp.getActive();
  const destination = wb.getSheetByName("RandomValues");
  const source = wb.getSheetByName("AllValues");
  if (!source || !destination)
    throw new Error("Missing required sheets 'RandomValues' and 'AllValues'");

  // Create a flat array of all non-empty values in all rows and columns of the source sheet.
  const data = source.getDataRange().getValues().reduce(function (compiled, row) {
    var vals = row.filter(function (val) { return val !== ""; });
    if (vals.length)
      Array.prototype.push.apply(compiled, vals);
    return compiled;
  }, []);

  // Sample the smaller of 50 elements or 10% of the data, without replacement.
  const sample = [];
  var sampleSize = Math.min(50, Math.floor(data.length * .1));
  while (sampleSize-- > 0)
  {
    var choice = Math.floor(Math.random() * data.length);
    Array.prototype.push.apply(sample, data.splice(choice, 1));
  }

  // If we have any samples collected, write them to the destination sheet.
  if (sample.length)
  {
    destination.getDataRange().clearContent();
    // Write a 2D column array.
    destination.getRange(1, 1, sample.length, 1)
      .setValues(sample.map(function (element) { return [ element ]; }));
    // Write a 2D row array
    // destination.getRange(1, 1, 1, sample.length)
    //   .setValues( [sample] );
  }
}

自定义功能

如果你仍然想使用自定义函数从RandomValues片,例如

RandomValues!A1: =sampleAllValues(50, AllValues!A1:A)

那么你就需要return sample,而不是写一个特定的表。需要注意的是自定义的功能确定性处理 - 他们在入境时计算,然后只有当它们的参数值的变化重新计算。自定义功能非常有限的范围内运行,所以一定要检查他们的限制。上述使用提示,你可能会发现它很有用,允许传入所需的样本数量,并从采样值:

function sampleAllValues(sampleSize, value2Darray) {
  const data = value2Darray.reduce(function (compiled, row) {
    /* as above */
  }, []);
  /* sample as above */
  return sample; // Must be 2D row or 2D column array, or a single primitive e.g. `1`
}

无论你采取哪条路线,一定要通过查看你的脚本为Stackdriver日志查看脚本的错误日志记录。 (查看 - >为Stackdriver记录)

参考文献:

© www.soinside.com 2019 - 2024. All rights reserved.