谷歌工作表-替换工作表而不中断对该工作表的引用



我们正在构建一个谷歌表单数据库,每个用户都有自己的电子表格,使用应用程序脚本访问中心表单以获取信息。

这意味着,我们有50名员工,需要维护50个电子表格。我正试图找到一种方法,将更新推送到所有50个电子表格,而不必手动更新每个电子表格。我在每个用户的工作表引用的库中都有所有的应用程序脚本代码,所以我已经计算好了代码维护。但事实证明,让每个用户的实际电子表格跟上最新功能是很困难的。

我想做到这一点的一种方法是有一个"模板"用户表,它会随着更改/新功能而更新。然后,当每个用户打开他们的电子表格时,它会将其所有工作表交叉引用到模板工作表,并根据在模板工作表中更新的时间检查是否需要将其工作表替换为最新的工作表。例如,当模板中的"项目报告"表比用户电子表格中的"工程报告"表更新时,用户SS会删除其当前的"工程报表",并通过copyTo()方法将模板"工程报告》表复制到自己的表中。

我用应用程序脚本处理了所有这些,但现在的问题是,当用户的本地工作表被删除并替换为新更新的seet时,其他工作表中对该工作表的所有公式引用都会中断,并用#REF替换引用。我曾计划通过只使用命名范围来克服这一点,但是,当工作表被替换到即使是应用程序脚本也无法再找到命名范围的地步时,即使是命名范围也会中断,因为在导入新版本的工作表时,它所查找的命名范围会自动重命名(即,模板SS中的"CustomNamedRange"在用户SS中被重命名为"SheetName'!CustomNamedRrange")。

在这一点上,我知道克服这个问题的唯一方法是创建一个集中的"范围索引"电子表格,其中包含所有命名的范围及其目标表和范围。我必须创建一个自定义函数,通过范围索引进行筛选,并根据给定的名称找到所需的地址。例如,我不会在工作表公式中调用"CustomNamedRange",而是调用自定义函数:getNamedRage("CustomNametRange"),应用程序脚本将返回在范围索引中找到的范围。当工作表被新版本替换时,没有引用会中断,因为所有引用都经过应用程序脚本筛选功能。

唯一的问题是,我可以预见这种方法(通过自定义函数调用脚本中需要的每个范围)会大大减慢我的电子表格速度,因为每次调用范围时,它都必须搜索范围索引才能找到并返回。

有人对如何实现我想要的目标有其他想法吗?至于让50多个单独的电子表格更新新功能,而不必手动进行,也不需要破坏所有参考?

很抱歉发了这么长的帖子,但我很感激你的想法!

我遇到了类似的问题,并通过使用SheetAPI替换文本来解决。我有一个名为Sheet1_template的模板,它是隐藏的。我删除Sheet1,复制Sheet1_Template,将其显示出来,然后将公式中所有出现的"Sheet1"替换为"Sheet1"。表单API必须在参考资料和Google API控制台中启用。

function copyTemplate() {
try {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("Sheet1");
if( sheet !== null ) spread.deleteSheet(sheet);
sheet = spread.getSheetByName("Sheet1_Template");
sheet = sheet.copyTo(spread);
sheet.setName("Sheet1");
sheet.showSheet();
sheet.activate();
spread.moveActiveSheet(0);
var requests = {"requests":[{"findReplace":{"allSheets":true,"find":"Sheet1","replacement":"Sheet1","includeFormulas":true}}]};
Sheets.Spreadsheets.batchUpdate(requests, spread.getId());
}
catch(err) {
Logger.log("error in copyTemplate: "+err);
}
}

我还没能测试它的实现,但我相信上面的答案就是我最初想要的。

我还没有花任何时间扰乱API,所以在此期间,我找到了另一个解决方案:

Google Sheets最近在其功能集中添加了宏。这样做的美妙之处在于,在工作表中记录操作后,您可以查看和编辑宏代码。目前,我计划在更新模板工作表时录制一个宏,然后将该宏的脚本复制到库中的自定义函数中,该函数将在用户每次打开电子表格时运行。当他们打开SS时,应用程序脚本将检查库的宏函数的日期是否晚于上次打开工作表的日期。如果它确实有一个新的日期,那么它将运行宏脚本,并且该用户的SS应该更新到与模板相同的状态。

如果您发现无法从@TheWizEd 运行查询

这可能是由于"表单API"没有在高级谷歌服务启用。请启用>

在脚本编辑器中,选择资源>高级Google服务在显示的对话框中,单击Google Sheets API v4的打开/关闭开关。请打开。单击"确定"按钮。

非常感谢TheWizEd让我开始(也请投票支持该帖子)。

这就是我需要的:

function replaceFormulasInSheet(sheet, searchFor, replaceWith) {
// https://stackoverflow.com/a/67151030/470749
// First you need to do this to enable the feature: https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services
// https://developers.google.com/sheets/api/quickstart/apps-script
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#findreplacerequest
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate
const spread = SpreadsheetApp.getActiveSpreadsheet();
const requests = {
"requests": [
{
"findReplace": {
// "allSheets": true, Omitting this property and instead setting the sheetId property is the only way to effectively set allSheets as false.
"sheetId": sheet.getSheetId(),
"find": searchFor,
"replacement": replaceWith,
"includeFormulas": true
}
}
]
}; 
return Sheets.Spreadsheets.batchUpdate(requests, spread.getId()); 
}

还要注意,它不适用于名称中带有连字符的图纸。如果他们的名字中需要连字符,请事先删除连字符,然后重新添加。

最新更新