我们正在构建一个Google表格数据库,其中每个用户都有自己的电子表格,该表格可使用应用程序脚本访问中央表格以获取信息。
这意味着有50名员工,我们需要维护50个电子表格。我试图找到一种方法来将更新推送到所有50个电子表格,而不必手动更新每个电子表格。我将所有应用程序脚本代码存储在每个用户的工作表都引用的库中,因此需要弄清楚编码维护。但是事实证明,要使每个用户的实际电子表格具有最新功能都是很困难的。
我想做到这一点的一种方法是拥有一个“模板”用户表,该用户表使用更改/新功能进行更新。然后,当每个用户打开其电子表格时,它会将所有工作表交叉引用到模板工作表,并根据模板工作表中的更新时间检查是否需要将其工作表替换为最新工作表。例如,当模板中的“项目报告”工作表比用户电子表格中的“项目报告”工作表新时,用户SS会删除其当前的“项目报告”,并通过以下方式将模板“项目报告”工作表复制到自己的模板中copyTo()方法。
我已经使用Apps脚本了,但是现在的问题是,当用户的本地工作表被删除并替换为新的更新Seet时,其他工作表中对该工作表的所有公式引用都被破坏,并将引用替换为#REF 。我曾计划仅使用命名范围来解决此问题,但是当替换工作表时,即使命名范围也会中断,即使应用程序脚本也无法再找到命名范围,因为查找的命名范围在导入了新版本的工作表(又将模板SS中的“ CustomNamedRange”重命名为用户SS中的“'SheetName'!CustomNamedRange”)。
到目前为止,我知道克服此问题的唯一方法是创建一个集中的“范围索引”电子表格,该表格具有所有命名范围及其目标工作表和范围。我将必须创建一个自定义函数,该函数可以过滤范围索引并根据给定的名称查找所需的地址。例如,不是调用工作表公式中的“ CustomNamedRange”,而是调用自定义函数:getNamedRange(“ CustomNamedRange”),而apps脚本将返回在范围索引中找到的范围。而且,当工作表替换为较新的版本时,没有引用会中断,因为所有引用都通过了应用脚本过滤功能。
唯一的问题是,我可以预见这种方法(通过自定义函数调用脚本中需要的每个范围)会减慢我的电子表格的运行速度,因为每次调用范围时,都必须遍历整个范围找到并返回范围索引。
有人对实现我所寻找的东西还有其他想法吗?就像在保持50多个单独的电子表格具有新功能的情况下,而无需手动进行操作并且不破坏所有引用一样?
很抱歉,很长的帖子,但我感谢任何想法!
答案 0 :(得分:1)
我有一个类似的问题,并且能够通过使用SheetAPI替换文本来解决。我有一个名为Sheet1_Template的模板,它已隐藏。我删除Sheet1,复制Sheet1_Template,显示它,然后将公式中所有出现的“ Sheet1”替换为“ Sheet1”。必须在参考资料和Google API控制台中启用Sheet 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);
}
}
答案 1 :(得分:1)
我还不能测试它的实现,但是我相信上面的答案就是我最初想要的。
我还没有花时间来弄乱API,因此与此同时,我找到了另一个解决方案:
Google表格最近在其功能集中添加了宏。这样做的好处是,您可以在表格中记录操作后就可以查看和编辑宏代码。现在,我计划在对模板工作表进行更新时记录宏,然后将该宏的脚本复制到库中的自定义函数中,该函数将在用户每次打开电子表格时运行。当他们打开SS时,apps脚本将检查该库的宏功能是否具有比上次打开工作表的日期晚的日期。如果确实有新日期,则它将运行宏脚本,并且该用户的SS应该更新为与模板相同的状态。
答案 2 :(得分:0)
此外,如果您发现无法从@TheWizEd运行查询
这可能是由于高级Google服务未启用“ Sheets API”。请启用>
在脚本编辑器中,选择资源>高级Google服务在出现的对话框中,单击Google Sheets API v4的打开/关闭开关。请打开。点击确定按钮。
答案 3 :(得分:0)
非常感谢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());
}
另请注意,它不适用于名称中带有连字符的工作表。如果您的名称中需要连字符,请事先删除连字符并在后面重新添加。