Jan*_*nik 5 google-sheets google-apps-script custom-function google-sheets-formula
我正在创建一个棋盘游戏,为此我决定选择 Google 表格。我已将我的问题简化为一个由一张纸和一个脚本组成的最小示例。
以下几点参考我的骰子表:
DICEFACES应用于范围E2:I2和E10:I10的函数的结果。
DICEFACES是我在Code.gs与样式表关联的文件中的脚本编辑器中创建的自定义函数。它返回与提供范围内的骰子对应的骰子面矩阵。它的身体如下:
function DICEFACES(unused_ref_to_range_containing_dices)
{
var app = SpreadsheetApp;
var spr = app.getActiveSheet();
// In the end this array will hold the dice faces. For example two
// 1d6 dices would result in [[1,2,3,4,5,6],[1,2,3,4,5,6]].
//
var Dices = [];
// The the formula inside the active cell (i.e. the cell on which
// we are calling this function). This is a string like:
//
// "=DICEFACES(E2:I2)"
//
var active_formula = spr.getActiveRange().getFormula();
// Set item_range to the one pointed to by the formula. This could
// be a range like E2:I2.
//
var item_range = spr.getRange(active_formula.match(/=\w+\((.*)\)/i)[1]);
// Loop over dice cells in the item_range.
//
for (var i = 1; i <= item_range.getNumColumns(); i++)
{
// "=B2", "=B3", ...
//
var dice_formula = item_range.getCell(1, i).getFormula();
// As soon as we encounter an empty formula, we skip (i.e. there are
// no more dices).
//
if (dice_formula == "")
{
break;
}
// A reference to the cell containing the dice image. We don't really
// need the image, the dice faces are of greater importance to us.
//
var dice_cell = spr.getRange(dice_formula.substr(1));
// Move one column to the right prior to the dice_cell and retreive
// the value of the cell. This is a string like "1,2,3,4,5,6".
//
var dice_csv = dice_cell.offset(0, 1).getValue();
// Convert the CSV string to a javascript array like [1,2,3,4,5,6]
// and push it to Dices.
//
Dices.push(dice_csv.split(",").map(Number));
}
return Dices;
}
Run Code Online (Sandbox Code Playgroud)问题是,当我更改C列中的骰子面时,DICEFACE不会重新计算公式。就在我创建屏幕截图之前,我,4在单元格C2 中添加了后缀,正如您所看到的4,单元格N2 中没有。不过,如果我要么重新保存Code.gs脚本文件或更改骰子E2:I2,重新计算立即发生。
我很确定我知道问题出在哪里:因为我在脚本中遍历单元格,所以工作表应用程序本身看不到C列中的单元格与K2和K10 中的公式之间的引用链接。查看我的工作表,单元格引用可能类似于:
K4 <-- E2:I2 <-- B2, B3 (C is not here)
K10 <-- E10:I10 <-- B4, B5 (C is not here)
Run Code Online (Sandbox Code Playgroud)
我的符号的意思A <-- B是If there's a change in range B, update cell A。
在我修改骰子面后,我应该更改什么才能使自动重新计算立即发生?如果这是不可能的,那么完成我的任务的最佳方法是什么?
问题是,当我更改C列中的骰子面时,
DICEFACE不会重新计算公式。
DIFACE 是一个自定义函数,当打开电子表格并且自定义函数参数值发生更改时,会重新计算自定义函数。
考虑到上述情况,为了最大限度地减少对自定义函数的更改,请添加第二个参数作为触发器。
改变正则表达式
/=\w+\((.*)\)/i
Run Code Online (Sandbox Code Playgroud)
到
/=\w+\((.*),.*\)/i
Run Code Online (Sandbox Code Playgroud)
然后通过以下方式调用您的自定义函数
=DICEFACES(E2:I2,C2)
Run Code Online (Sandbox Code Playgroud)
或者
=DICEFACES(E2:I2,C2:C5)
Run Code Online (Sandbox Code Playgroud)
OP自定义功能修改版
/**
* Returns a matrix of dice faces corresponding to the dices in the provided range.
*
* @param {Array} unused_ref_to_range_containing_dices Reference to range. i.e. E2:I2
* @param {String|Number|Date|Array} ref_as_trigger Reference to a range used as trigger. i.e. C2 or C2:C5
* @return array
* @customfunction
*/
function DICEFACES(unused_ref_to_range_containing_dices,ref_as_trigger)
{
var app = SpreadsheetApp;
var spr = app.getActiveSheet();
// In the end this array will hold the dice faces. For example two
// 1d6 dices would result in [[1,2,3,4,5,6],[1,2,3,4,5,6]].
//
var Dices = [];
// The the formula inside the active cell (i.e. the cell on which
// we are calling this function). This is a string like:
//
// "=DICEFACES(E2:I2)"
//
var active_formula = spr.getActiveRange().getFormula();
// Set item_range to the one pointed to by the formula. This could
// be a range like E2:I2.
//
var item_range = spr.getRange(active_formula.match(/=\w+\((.*),.*\)/i)[1]); // CHANGED
// Loop over dice cells in the item_range.
//
for (var i = 1; i <= item_range.getNumColumns(); i++)
{
// "=B2", "=B3", ...
//
var dice_formula = item_range.getCell(1, i).getFormula();
// As soon as we encounter an empty formula, we skip (i.e. there are
// no more dices).
//
if (dice_formula == "")
{
break;
}
// A reference to the cell containing the dice image. We don't really
// need the image, the dice faces are of greater importance to us.
//
var dice_cell = spr.getRange(dice_formula.substr(1));
// Move one column to the right prior to the dice_cell and retreive
// the value of the cell. This is a string like "1,2,3,4,5,6".
//
var dice_csv = dice_cell.offset(0, 1).getValue();
// Convert the CSV string to a javascript array like [1,2,3,4,5,6]
// and push it to Dices.
//
Dices.push(dice_csv.split(",").map(Number));
}
return Dices;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
185 次 |
| 最近记录: |