我想要实现的目标
我有一张包含2张prefetch_select('toppings')
的电子表格。 A
。
B
有2列 - 名称,金额(主列表)
A
有4列 - 姓名,金额,X,Y(交易清单)
B
Sheet B
个引用名称列的 名称列。每当选择一个名称时,我想在Sheet A
中填充Amount列,并将B
列中的Amount列为用户可以覆盖的占位符。为此,我计划在数组中加载sheet A
数据(全局可用),以便在Sheet A
中我可以引用该数组而不是访问onEdit(e)
。
但我能找到的选项 - Sheet B
和CacheService
- 只保存字符串值。但我希望:
PropertyService
问题 哪里&如何定义myGlobalArray?
我尝试使用var myGlobalArray = [];
function on init(){
//iterate and fill the array such that it has following output
//myGlobalArray[Name1] = 1
//myGlobalArray[Name2] = 2
//myGlobalArray[Name3] = 3
}
function onEdit(e){
//if selected value is name1, populate myGolbalArray[Name1] value in Amount
}
和JSON.Stringify
的缓存服务,但JSON.parse
中的数组为空。
答案 0 :(得分:5)
对脚本的每次调用都会创建一个具有自己唯一全局变量的脚本的新实例。每次你打电话给一个剧本,你实际上都会找到一个全球性的"这个"对于那个特定的例子。将PropertyService视为保存数据的持久方法是正确的。
马上关闭我看到你的globalArray设置不正确:
var myGlobalArray = [];
需要
var myGlobalArray = {};
myGlobalArray['name1'] = 1
myGlobalArray['name2'] = 2
myGlobalArray['name3'] = 3
//myGlobalArray = {name3=3.0, name1=1.0, name2=2.0}
var stringArray = JSON.stringify(myGlobalArray)
//{"name1":1,"name2":2,"name3":3};
现在可以保存到属性商店并从中读取。
PropertiesService.getScriptProperties().setProperty("NameArray", stringArray);
stringArray = PropertiesService.getScriptProperties().getProperty("NameArray");
myGlobalArray = JSON.parse(stringArray);
Logger.log(myGlobalArray['name1']) // returns 1
答案 1 :(得分:4)
CacheService和PropertyService仅保存字符串值,但您可以使用JSON
utilities JSON.stringify()
和JSON.parse()
存储任何标量数据。
// Save an array in cache service
CacheService.getPublicCache()
.put("myGlobalArray", JSON.stringify(myGlobalArray));
// Retrieve an array from property service
var myGlobalArray = JSON.parse( CacheService.getPublicCache()
.get("myGlobalArray") );
// Save an array in property service
PropertiesService.getDocumentProperties()
.setProperty("myGlobalArray", JSON.stringify(myGlobalArray));
// Retrieve an array from property service
var myGlobalArray = JSON.parse( PropertiesService.getDocumentProperties()
.getProperty("myGlobalArray") );
当调用变量" Global"时,我们指的是范围,表示它可用于同一模块中的所有代码。 (您可以在What is the scope of variables in JavaScript?)
中详细了解范围但是,既然您正在查看CacheService和PropertyService,那么您已经知道范围只是问题的一部分。每次调用onEdit()
时,它都将在Google的某个服务器上的新执行实例中运行。以前实例中的全局变量中的值将不可用于此新实例。因此,我们需要填充我们的全局变量"在我们脚本的每次新调用中。
引用全局变量的一种优雅方式是特殊this
对象的名称属性。例如,我们脚本中的每个函数都可以引用this.myGlobalArray
。 1
您可以将getRssFeed()
文档中的get_myGlobalArray()
示例调整为onEdit()
。然后,您的this.myGlobalArray
触发器只需要先调用它,以确保function onEdit(e){
get_myGlobalArray();
//if selected value is name1, populate myGlobalArray[Name1] value in Amount
...
sheet.getRange(e.range.getRow(),2).setValue(myGlobalArray[e.value]);
}
/**
* Ensure the global variable "myGlobalArray" is defined and contains the
* values of column A in SheetA as an array.
*/
function get_myGlobalArray() {
if (typeof this.myGlobalArray == 'undefined') {
// Global variable doesn't exist, so need to populate it
// First, check for cached value
var cache = CacheService.getPublicCache();
var cached = cache.get("myGlobalArray");
if (cached) {
// We have a cached value, so parse it and store in global
this.myGlobalArray = JSON.parse(cached);
}
else {
// No value in the cache, so load it from spreadsheet
var data = SpreadsheetApp.getActive().getSheetByName("Sheet A").getDataRange().getValues();
this.myGlobalArray = {};
for (var row=0; row<data.length; row++) {
this.myGlobalArray[data[row][0]] = data[row][6];
}
// Stringify and store the global into the cache
cache.put("myGlobalArray", JSON.stringify(this.myGlobalArray));
}
}
}
包含相关的数组数据。
onEdit()
在//if selected value is name1, populate myGolbalArray[Name1] value in Amount
中的评论中,它表示:
myGlobalArray
这意味着this.myGlobalArray
是关联数组,其中索引是非整数值。此要求现在反映在从电子表格中读取时for (var row=0; row<data.length; row++) {
this.myGlobalArray[data[row][0]] = data[row][6];
// ^^^^^^^^^^^^ ^^^^^^^^^^^^
// Name ---------------/ /
// Amount ------------------------/
}
填充的方式。
this
关于Javascript数组的不同风格已经写了很多,例如Class Cache。
1 实际上,只有具有全局范围的函数才能理解this
表示&#34;全局到脚本&#34;。包含在对象内的函数会将layout.cshtml
解释为仅表示其主机对象。但那是另一天的故事。