我想才达到以下。在谷歌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搜索这一块,有很多建议,但我不是很熟悉的功能,我没有设法得到它的工作。
希望有人能帮助我。
使用公式通常假定重复计算。你无法阻止他们,只能试图返回旧值来代替。这个任务是不平凡的,因为任何公式不能指其中的结果将被返回(圆形引用发生)相同的小区。不要使用单一的时间计算公式。
在另一方面,使用脚本功能,可以直接且仅一次或按需生成所需的数据。我想,下面的功能将帮助您了解所有样品源和目标范围内的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);
}
您可以手动运行,或选择合适的触发。
有实现这个目标的多种方式。
正如@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记录)
参考文献: