Google sheet 单元格重新计算
Google sheet cell recalculation
我正在创建一个棋盘游戏,我决定为此目的选择 Google sheets。我已将我的问题简化为一个由一个 sheet 和一个脚本组成的最小示例。
情况
以下几点参考我的骰子sheet:
- 单元格 B2:C5 包含可用的 骰子 。第一列包含骰子精灵,第二列包含逗号分隔的骰子面数。
- 游戏设计视角:美术师可以改变骰子图像。设计者可以更改骰子面号。两种类型的更改都会自动传播到引用骰子的单元格。
- 单元格 E2:I2 和 E10:I10 包含特定的 throw。在每次投掷中,1 到 5 次引用 B 列中的骰子。
- 游戏设计视角:有许多不同的游戏项目,每个项目可能有不同的骰子来决定一个动作的结果。设计者可以添加或删除对骰子的引用,它会触发特定单元格的自动重新计算(在我们的例子中,这些单元格是 K2 和 K10) .
- 从 K2 和 K10 开始的单元格包含应用于范围 的
DICEFACES
函数的结果]E2:I2 和 E10:I10。
- 游戏设计视角: 骰子面矩阵将进一步用于计算骰子概率。为简单起见,我将矩阵本身视为最终结果。
DICEFACES
是我在脚本编辑器中创建的自定义函数
与样式 sheet 关联的文件 Code.gs
。它 returns 的矩阵
对应于提供范围内的骰子的骰子面。它是
正文如下:
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;
}
问题
问题是,当我更改 C 列中的骰子面时,没有重新计算 DICEFACE
公式。就在我创建 screenshot 之前,我向单元格 C2 添加了 ,4
后缀,正如您所见,单元格 [=52] 中没有 4
=]N2。但是,如果我 重新保存 Code.gs
脚本文件 或 更改 E2:I2[ 中的骰子=84=],立即重新计算。
我很确定我知道问题出在哪里:因为我正在遍历脚本中的单元格,所以 sheet 应用程序本身看不到 [=52 列中单元格之间的引用链接=]C和K2和K10中的公式。查看我的 sheet,单元格引用可能类似于:
K4 <-- E2:I2 <-- B2, B3 (C is not here)
K10 <-- E10:I10 <-- B4, B5 (C is not here)
我的符号A <-- B
的意思是If there's a change in range B, update cell A
。
问题
我应该更改什么才能在修改骰子面后立即自动重新计算?如果这不可能,完成我的任务的最佳方法是什么?
The problem is that when I change the dice faces in column C, the DICEFACE
formulas are not being recalculated.
DIFACE 是一个自定义函数,当打开电子表格并且自定义函数参数值发生变化时,会重新计算自定义函数。
考虑到上述情况,为了尽量减少对自定义函数的更改,请添加第二个参数作为触发器。
更改正则表达式
/=\w+\((.*)\)/i
到
/=\w+\((.*),.*\)/i
然后按以下方式调用您的自定义函数
=DICEFACES(E2:I2,C2)
或
=DICEFACES(E2:I2,C2:C5)
我假设使用的是 Google Sheets 参数分隔符,但某些电子表格可以使用分号。
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;
}
我正在创建一个棋盘游戏,我决定为此目的选择 Google sheets。我已将我的问题简化为一个由一个 sheet 和一个脚本组成的最小示例。
情况
以下几点参考我的骰子sheet:
- 单元格 B2:C5 包含可用的 骰子 。第一列包含骰子精灵,第二列包含逗号分隔的骰子面数。
- 游戏设计视角:美术师可以改变骰子图像。设计者可以更改骰子面号。两种类型的更改都会自动传播到引用骰子的单元格。
- 单元格 E2:I2 和 E10:I10 包含特定的 throw。在每次投掷中,1 到 5 次引用 B 列中的骰子。
- 游戏设计视角:有许多不同的游戏项目,每个项目可能有不同的骰子来决定一个动作的结果。设计者可以添加或删除对骰子的引用,它会触发特定单元格的自动重新计算(在我们的例子中,这些单元格是 K2 和 K10) .
- 从 K2 和 K10 开始的单元格包含应用于范围 的
DICEFACES
函数的结果]E2:I2 和 E10:I10。- 游戏设计视角: 骰子面矩阵将进一步用于计算骰子概率。为简单起见,我将矩阵本身视为最终结果。
DICEFACES
是我在脚本编辑器中创建的自定义函数 与样式 sheet 关联的文件Code.gs
。它 returns 的矩阵 对应于提供范围内的骰子的骰子面。它是 正文如下: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; }
问题
问题是,当我更改 C 列中的骰子面时,没有重新计算 DICEFACE
公式。就在我创建 screenshot 之前,我向单元格 C2 添加了 ,4
后缀,正如您所见,单元格 [=52] 中没有 4
=]N2。但是,如果我 重新保存 Code.gs
脚本文件 或 更改 E2:I2[ 中的骰子=84=],立即重新计算。
我很确定我知道问题出在哪里:因为我正在遍历脚本中的单元格,所以 sheet 应用程序本身看不到 [=52 列中单元格之间的引用链接=]C和K2和K10中的公式。查看我的 sheet,单元格引用可能类似于:
K4 <-- E2:I2 <-- B2, B3 (C is not here)
K10 <-- E10:I10 <-- B4, B5 (C is not here)
我的符号A <-- B
的意思是If there's a change in range B, update cell A
。
问题
我应该更改什么才能在修改骰子面后立即自动重新计算?如果这不可能,完成我的任务的最佳方法是什么?
The problem is that when I change the dice faces in column C, the
DICEFACE
formulas are not being recalculated.
DIFACE 是一个自定义函数,当打开电子表格并且自定义函数参数值发生变化时,会重新计算自定义函数。
考虑到上述情况,为了尽量减少对自定义函数的更改,请添加第二个参数作为触发器。
更改正则表达式
/=\w+\((.*)\)/i
到
/=\w+\((.*),.*\)/i
然后按以下方式调用您的自定义函数
=DICEFACES(E2:I2,C2)
或
=DICEFACES(E2:I2,C2:C5)
我假设使用的是 Google Sheets 参数分隔符,但某些电子表格可以使用分号。
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;
}