我写了从用电子表格中的备份恢复日历数据的脚本。 由于数据量是非常难以预测的,我设计一个回路分钟的指定次数后,即停止,让用户continue
或cancel
,同时显示实际计数器状态(此为防止与谷歌最大执行时间限制的问题)。
它工作得很好,但在这个简单的测试脚本我用来测试它的作品只有一次的想法:当第一个“超时”的发生,它显示了continue/cancel
的预期选项,然后从那里开始,但继续在相同的条件下发生第二次的continue
按钮不会显示出来。
我的问题很简单:为什么呢? 或者更好的是什么这两种情况之间的区别?
与嵌入脚本的电子表格是这里公开检验的 (见menu : test
)
而整个脚本如下所示(这是一个有点长,当然,但interresting部分已经接近尾声)
我用ScriptProperties
跟踪的执行时间,并继续从我离开那里,循环。
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [
{name: "test", functionName: "test"},
];
ss.addMenu("test", menuEntries);
}
function test(){
ScriptProperties.setProperty('restorePointers',[0,0].join('@'))
var app = UiApp.createApplication().setTitle("test");
app.setHeight(150).setWidth(250);
var doc = SpreadsheetApp.getActiveSpreadsheet();
var panel = app.createVerticalPanel();
var handlerCancel = app.createServerHandler('canceltest');
var handlerContinue = app.createServerHandler('continuetest');
var contCHandler = app.createClientHandler();
var cancel = app.createButton("cancel.", handlerCancel).setId('cancel').setVisible(false);
var cont = app.createButton('continue',handlerContinue).setId('continue').setVisible(false).addClickHandler(contCHandler);
var button = app.createButton('start').setId('button');
var handler = app.createServerClickHandler('runtest');
handler.addCallbackElement(panel);
contCHandler.forTargets(button).setEnabled(false).forEventSource().setVisible(false);
var cHandler = app.createClientHandler().forTargets(cancel).setVisible(true).forEventSource().setVisible(false);
button.addClickHandler(handler).addClickHandler(cHandler);
app.add(panel.add(button).add(cont).add(cancel))//.add(trig));
doc.show(app);
}
function canceltest(e){
var app = UiApp.getActiveApplication();
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers','canceled');
SpreadsheetApp.getActiveSpreadsheet().toast(' ','restore aborted');
app.close()
return app;
}
function continuetest(e){
runtest(e)
}
function runtest(e){
var dStart; var dEnd;
ScriptProperties.setProperty('startrestore',new Date().getTime().toString())
if(ScriptProperties.getProperty('restoreData')==null||Utilities.jsonStringify(ScriptProperties.getProperties()).indexOf('restoreData')==-1)
{ScriptProperties.setProperty('restoreData',Utilities.jsonStringify(e))
}
var app = UiApp.getActiveApplication();
var pointers = ScriptProperties.getProperty('restorePointers');
if(pointers=='0@0'){
dStart = 0;
dEnd = 500;
}else{
dStart = Number(pointers.split('@')[0]);
dEnd = Number(pointers.split('@')[1]);
}
// main loop --------------------------
for(var ee=dStart;ee<dEnd;++ee){ // main loop
var ccc = ScriptProperties.getProperty('restorePointers');
if(ccc=='canceled'){ app.close();return app};
Utilities.sleep(85); // simulate some activity
if((ee/10)==parseInt(ee/10)&&ee>0){
SpreadsheetApp.getActiveSpreadsheet().toast(ee+' steps completed')
if(new Date().getTime()-Number(ScriptProperties.getProperty('startrestore'))>12000){ ;// +- 12 sec timeout
ScriptProperties.setProperty('restorePointers',[ee,dEnd].join('@'));
app.getElementById('continue').setHTML('continue from '+ee).setVisible(true)
return app
}
}
}
// end of main loop-----------------
ScriptProperties.setProperty('restoreData','')
ScriptProperties.setProperty('restorePointers',0+'@'+0);
SpreadsheetApp.getActiveSpreadsheet().toast('normal process end');
app.close();
return app;
}