我编写了一个自定义的Google Apps脚本,它将收到id
并从网络服务中获取信息(价格)。
我在电子表格中使用此脚本,它工作得很好。我的问题是这些价格会发生变化,我的电子表格也不会更新。
如何强制它重新运行脚本并更新单元格(无需手动遍历每个单元格)?
答案 0 :(得分:75)
好吧,好像我的问题是谷歌表现得很奇怪 - 只要脚本参数相似,它就不会重新运行脚本,它会使用之前运行的缓存结果。因此,它不会重新连接到API并且不会重新获取价格,它只返回缓存的先前脚本结果。
在此处查看更多信息:https://code.google.com/p/google-apps-script-issues/issues/detail?id=888
在这里:Script to summarise data not updating
我的解决方案是在我的脚本中添加另一个参数,我甚至不使用它。现在,当您使用与先前调用不同的参数调用该函数时,它将不得不重新运行该脚本,因为这些参数的结果将不在缓存中。
所以每当我调用该函数时,对于额外的参数,我都会传递“$ A $ 1”。 我还创建了一个名为refresh的菜单项,当我运行它时,它将当前日期和时间放在A1中,因此所有对$ A $ 1作为第二个参数的脚本调用都必须重新计算。这是我脚本中的一些代码:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Refresh",
functionName : "refreshLastUpdate"
}];
sheet.addMenu("Refresh", entries);
};
function refreshLastUpdate() {
SpreadsheetApp.getActiveSpreadsheet().getRange('A1').setValue(new Date().toTimeString());
}
function getPrice(itemId, datetime) {
var headers =
{
"method" : "get",
"contentType" : "application/json",
headers : {'Cache-Control' : 'max-age=0'}
};
var jsonResponse = UrlFetchApp.fetch("http://someURL?item_id=" + itemId, headers);
var jsonObj = eval( '(' + jsonResponse + ')' );
return jsonObj.Price;
SpreadsheetApp.flush();
}
当我想将ID为5的商品的价格放在单元格中时,我使用以下公式:
=getPrice(5, $A$1)
当我想刷新价格时,我只需点击“刷新” - > “刷新”菜单项。
请记住,在更改onOpen()
脚本后,您需要重新加载电子表格。
答案 1 :(得分:30)
我知道这是一个老问题。但是这种方法除了进行更改外不需要任何用户操作。
我所做的与tbkn23类似。
我想要重新评估的函数有一个额外的未使用参数,$ A $ 1。所以函数调用是
=myFunction(firstParam, $A$1)
但在代码中,函数签名是
function myFunction(firstParam)
我没有使用刷新功能,而是使用了像这样的onEdit(e)函数
function onEdit(e)
{
SpreadsheetApp.getActiveSheet().getRange('A1').setValue(Math.random());
}
只要编辑电子表格中的任何单元格,就会触发此功能。所以现在你编辑一个单元格,一个随机数放在A1中,这会刷新参数列表为tbkn23建议,导致自定义函数被重新评估。
答案 2 :(得分:9)
答案 3 :(得分:3)
如果您的自定义功能位于特定列中,只需按该列订购电子表格。
排序强制刷新数据,同时为该列的所有行调用自定义函数。
答案 4 :(得分:1)
/*@customfunction*/
function sheetNames(e) {
return SpreadsheetApp.getActive()
.getSheets()
.map(function(sheet) {
return sheet.getName();
});
}
/*Create a installable trigger to listen to grid changes on the sheet*/
function onChange(e) {
if (!/GRID/.test(e.changeType)) return; //Listen only to grid change
SpreadsheetApp.getActive()
.createTextFinder('=SHEETNAMES\\([^)]*\\)')
.matchFormulaText(true)
.matchCase(false)
.useRegularExpression(true)
.replaceAllWith(
'=SHEETNAMES(' + (Math.floor(Math.random() * 500) + 1) + ')'
);
}
答案 5 :(得分:1)
如前所述:
除非参数更改,否则自定义函数不会更新。
可能的解决方案是在单个单元格中创建一个复选框,并将该单元格用作自定义函数的参数:
=myFunction(A1)
答案 6 :(得分:0)
这可能是一个超级老线程,但对于那些尝试这样做的人来说可能很有用,就像我刚才那样。
按原样使用Lexi的脚本,它似乎不再适用于当前的Sheets,但如果我将虚拟变量添加到我的函数中作为参数(无需实际使用)它在函数内部,它确实会强制google工作表再次刷新页面。
所以,声明如:function myFunction(firstParam,dummy)然后调用它就像建议的那样。这对我有用。
此外,如果在您编辑的所有工作表上显示随机变量是一件麻烦事,那么限制为一张工作表的简单补救措施如下:
function onEdit(e)
{
e.source.getSheetByName('THESHEETNAME').getRange('J1').setValue(Math.random());
}
答案 7 :(得分:0)
答案 8 :(得分:0)
您应该使用特定的更新函数,初始化“当前时间”变量并将这个永久更新的变量传递给您的自定义函数。然后转到触发器并为更新功能设置一个“每分钟”时间驱动的触发器(或选择另一个时间间隔进行更新)。
代码:
function update() {
var dt = new Date();
var ts = dt.toLocaleTimeString();
var cellVal = '=CustomFunction("'+ ts + '")';
SpreadsheetApp.getActiveSheet().getRange('A1').setValue(cellVal);
}
答案 9 :(得分:0)
今天我解决了这个问题
function MY_FUNC(a, b, additional_param) { /* ... */ }
=MY_FUNC("a", "b", A1)
现在,只需单击(在复选框上)即可强制重新计算我的函数。
答案 10 :(得分:-3)
如果您已编写自定义函数并在电子表格中将其用作公式,则每次打开电子表格或修改任何引用单元格时,都会重新计算公式。
如果您只想继续盯着电子表格并希望更改其值,请考虑添加一个更新单元格的定时触发器。阅读有关触发器here
的更多信息