【发布时间】:2014-04-20 01:11:25
【问题描述】:
为此目的编写了一些代码,但随着新的插件它们不再适用。
【问题讨论】:
-
不是真的,我的意思是自动刷新和重新计算
-
Rubén 来自stackoverflow.com/questions/38127603/… 的回答帮助了我
标签: google-sheets
为此目的编写了一些代码,但随着新的插件它们不再适用。
【问题讨论】:
标签: google-sheets
文件 -> 电子表格设置 ->(选项卡)计算 -> 重新计算(3 个选项)
但是..
.. 仅当函数的参数(它们的范围、单元格)受此影响时,它才会更新。
我的例子
我使用谷歌电子表格找出一个人的年龄。我有他的出生日期格式 (dd.mm.yyyy) -> 这是瑞士使用的格式。
=ARRAYFORMULA(IF(ISTEXT(K4:K), IF(TODAY() - DATE(YEAR(TODAY()), MONTH(REGEXREPLACE(K4:K, "[.]", "/")), DAY(REGEXREPLACE(K4:K, "[.]", "/"))) > 0, YEAR(TODAY()) - YEAR(REGEXREPLACE(K4:K, "[.]", "/")) + 1, YEAR(TODAY()) - YEAR(REGEXREPLACE(K4:K, "[.]", "/"))), IF(LEN(K4:K) > 0, IF(TODAY() - DATE(YEAR(TODAY()), MONTH(K4:K), DAY(K4:K)) > 0, YEAR(TODAY()) - YEAR(K4:K) + 1, YEAR(TODAY()) - YEAR(K4:K)), "")))
我正在使用TODAY(),并进行了上述重新计算设置。 -> 但不会自动刷新。 :-(
仅当我在函数正在查找的范围内更改某些值时,它才会更新。
因此我为此编写了一个 Google 脚本(工具 -> 脚本编辑器..)。
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetMaster = ss.getSheetByName("Master");
var sortRange = sheetMaster.getRange(firstRow, firstColumn, lastRow, lastColumn);
sortRange.getCell(1, 2).setValue(sortRange.getCell(1, 2).getValue());
}
您需要为firstRow、firstColumn、lastRow、lastColumn设置数字
当电子表格打开时,脚本会激活,将一个单元格的内容再次写入同一个单元格。这足以触发TODAY() 函数。
在该链接from Edward Moffett: Force google sheet formula to recalculate 上查找更多信息。
【讨论】:
IF(ISTEXT(… 替换为IF(NOW()*ISTEXT(…,而不是使用脚本。 (这不会改变值,因为 NOW()* 的行为类似于 AND(TRUE;,因为隐式转换为布尔值。)
getRange() 函数定义如下:getRange(row, column, numRows, numColumns) 所以不是 "lastRow, lastColumn" 它应该真正类似于 "numRows, numColumns"
setValues() - 它将使用原始输出值,并用这些值重写原始公式!!!请参阅我的答案以获得更好的方法。
对我有用的是在第一列之前插入一列并立即将其删除。 基本上,所做的更改将影响工作表中将触发重新计算的所有单元格。
【讨论】:
老问题......不过,只需在工作表的某处添加一个复选框即可。选中或取消选中它将刷新单元格公式。
【讨论】:
NOW()、TODAY()、RAND() 或 RANDBETWEEN() 公式在任何空白单元格上按 Backspace ← 或 Del 可立即触发重新计算公式,具体取决于 NOW()、TODAY()、 RAND() 或 RANDBETWEEN()(在整个电子表格的所有表格中,像往常一样)。
(如果手头没有空单元格,您可以删除填充的单元格,然后使用 Ctrl+z 撤消该操作。)
很遗憾,INDIRECT() 公式默认不会像这样更新。
INDIRECT() 公式您可以通过将范围粘贴到自身上来更新INDIRECT() 公式的(范围)单元格:
您可以在步骤 1 中使用 Ctrl+A 选择整个当前工作表。但对于大型工作表,其他 2 个操作可能需要几秒钟。 知道复制大范围的过程何时完成的技巧: 在复制您的范围之前复制一些单个单元格:丢失其虚线边框的单个单元格将是您的大副本完成的通知。
【讨论】:
问题
我看到很多单元格说#REF!。这些是我使用“复制到 > 现有工作表”从另一个 Google 工作表文档复制的工作表中的单元格。如果我在任何单元格中按 Enter,它会正确重新计算,但我不想对数百万个单元格这样做。
我的回答
我运行了这个recalcSheet() 脚本。每个单元格几乎需要 0.5 秒,这很慢,但比手动修复每个单元格要快。
function recalcSheet(){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
var sheet = spreadsheet.getSheetByName("put_your_sheet_name_here"); // https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getsheetbynamename
// var range = sheet.getSelection().getActiveRange();
// var range = sheet.getRange('A6:D6');
var range = sheet.getDataRange();
recalcRange(range, spreadsheet);
}
function recalcRange(range, spreadsheet){
// following structure of https://stackoverflow.com/a/52123839/470749
Logger.log('Range: ' + range.getA1Notation());
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var startRow = range.getRow();
var startCol = range.getColumn();
Logger.log('row: ' + startRow);
Logger.log('col: ' + startCol);
Logger.log('numRows: ' + numRows);
Logger.log('numCols: ' + numCols);
for (var r = 1; r <= numRows; r+=1) {
for (var c = 1; c <= numCols; c+=1) {
var originalFormula = range.getCell(r, c).getFormula(); // https://developers.google.com/apps-script/reference/spreadsheet/range#getFormula()
Logger.log(`r,c ${r}, ${c}; originalFormula: ${originalFormula}`);
if(originalFormula){
range.getCell(r, c).setFormula('');
//SpreadsheetApp.flush(); // https://webapps.stackexchange.com/a/35970/27487
range.getCell(r, c).setFormula(originalFormula);
}
}
}
spreadsheet.toast('Each cell in the range has been recalculated.', "Finished!"); // https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#toast(String)
}
【讨论】:
插入“复选框”。每次您选中或取消选中该框时,工作表都会重新计算。如果您将复选框的文本大小设置为 2,颜色几乎为黑色,单元格阴影为黑色,它将成为一个重新计算的按钮。
【讨论】:
我认为接受的答案存在一些重大问题(正如我在我的 cmets 中提到的),因此我提出了一个更好的方法。无论公式是否包含 NOW()、TODAY()、RAND() 或 RANDBETWEEN() 函数,这种方法都适用于我。事实上,它也适用于自定义函数。
需要注意的是,这种方法使用了setFormulas() 函数,需要用户确认。因此,下面的代码将创建一个标题为“刷新”的新菜单,并带有一个“刷新数据”按钮,而不是仅在电子表格打开时更新所有值。
无论何时按下此按钮,所需的数据范围都会刷新,方法是重新粘贴原始公式(不仅仅是值)。**
只需将此代码添加到电子表格中的工具 -> 脚本编辑器:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Refresh Data", functionName: "refreshData"});
ss.addMenu("Refresh", menuEntries);
}
function refreshData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var myRange = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
myRange.setFormulas(myRange.getFormulas());
}
请注意,如果您只想刷新电子表格的一部分,请更改 getRange() 函数中的值,如 relevant documentation 中所述。
【讨论】:
当问题出现在重新计算一个 IF 条件时,我添加AND(ISDATE(NOW());condition) 以便单元格根据
如前所述,在电子表格设置的计算选项卡中设置的内容。
这是可行的,因为NOW 是受计算设置影响的函数之一,而ISDATE(NOW()) 始终返回TRUE。
例如,在我的一张工作表中,我使用以下条件来检查是否已创建名称存储在 C1 中的工作表:
=IF(ISREF(INDIRECT(C$1&"!A1")); TRUE; FALSE)
在这种情况下C1="February",所以我希望在创建具有此名称的工作表时条件变为TRUE,但这并没有发生。为了强制它更新,我更改了计算设置并使用:
=IF(AND( ISDATE(NOW()) ; ISREF(INDIRECT(C$1&"!A1")) ); TRUE; FALSE)
【讨论】:
IF() 的 =INDIRECT(C$1&"!A1"):=INDIRECT(T(NOW())&C$1&"!A1")(解释:T() 过滤文本类型数据;NOW() 是日期时间类型(这是一个数字类型),所以不是文本类型,所以是 T(NOW())返回一个空字符串 ("")。& 连接该空字符串,保持结果不变(在处理字符串时)。)
我有一个非常适合我的解决方法,我有一个大工作表,其中包含许多“IMPORTRANGE”和许多指向其他工作表的链接,所以每次有人更新工作表时,它都没有显示在其他任何地方,所以我有逐个选项卡,选择整个内容,删除并返回以更新它,但我只是将公式“=IF(TODAY()=TODAY()”放在我所有的公式之前(这很痛苦脖子),终于成功了,一切都是实时更新的。
这花了我一些时间,但最终我得到了回报。
【讨论】:
我知道您正在寻找自动刷新;也许有些进来这里的人可能会对手动按钮的快速修复(如上面提出的复选框)感到满意。实际上,我只是偶然发现了与复选框类似的解决方案:选择要刷新的单元格,然后按 CTRL 和“+”键。似乎在 Office 365 v16 中工作;希望对有需要的人有用。
【讨论】: