GAS:在处理程序函数中使用变量时,如何更改全局变量值并保留其更改后的值

GAS: How to change a global variable value and preserve its changed value when using the variable in a handler function?

本文关键字:保留 变量值 全局 何更改 程序 处理 函数 变量 GAS      更新时间:2023-09-26

我的脚本中有一个全局变量:

var targetDocId = 'No doc ID informed yet';

我试图在我的主要函数中更改这个全局变量的值

function generatePersonDatasheet() {
  var target = createDuplicateDocument(template, docName);
  var link = target.getUrl();
  targetDocId = target.getId(); // <-------- HERE
  if (theses == 1){
    Logger.log("going to showList() ");
    return showList();
  }   
  showURL(docName, link); 
}

之后,我将尝试访问处理程序函数中更改的全局变量值:

function submit(e){
  var numberOfItems = Number(e.parameter.checkbox_total);
  var thesesArrays = [];
  for(var i = 0; i < numberOfItems; i++){
    if(e.parameter['checkbox_isChecked_'+i] == 'true'){
      thesesArrays.push(fact_list[i]);
    }
  }
  for (var i = 0; i < thesesArrays.length; i++){
    var thesesId = thesesArrays[i][2];
    var thesesType = thesesArrays[i][1];        
    importTheses(targetDocId, thesesId, thesesType); // <-----HERE
  }
  return UiApp.getActiveApplication().close();
}
function importTheses(targetDocId, thesesId, thesesType) {
  var targetDoc = DocumentApp.openById(targetDocId);
  var targetDocParagraphs = targetDoc.getParagraphs();
  var targetDocElements = targetDocParagraphs.getNumChildren();
  var thesesDoc = DocumentApp.openById(thesesId);
  var thesesParagraphs = thesesDoc.getParagraphs();
  var thesesElements = thesesDoc.getNumChildren();
  var eltargetDoc=[];
  var elTheses=[];
  for( var j = 0; j < targetDocElements; ++j ) {
       var targetDocElement = targetDoc.getChild(j);
        eltargetDoc[j]=targetDocElement.getText();
       if(el[j]== thesesType){
           for( var k = 0; k < thesesParagraphs-1; ++k ) {
               var thesesElement = thesesDoc.getChild(k);
               elTheses[k] = thesesDoc.getText();
               targetDoc.insertParagraph(j, elTheses[k]);
         }
      }
   }
}

但是,只要我尝试更改targetDocId,当它用作importTheses(targetDocId, thesesId, thesesType);的参数时,它仍然具有值"尚未通知文档ID",即使我已经更改了它,就好像程序从一开始就运行一样。是否可以替代这种"重置为原始值"的行为?或者我必须使用scriptDB或ScriptProperties来存储全局变量的更改值?

没有这样的选项。您必须使用scriptProperties或scriptDb。一旦函数完成,全局变量就会超出范围。每个外部脚本调用都从零开始。

脚本的每个单独执行都在一个新的执行实例中完成。因此,在代码块之外定义的任何变量(也称为"全局"变量)对于该实例都是唯一的。当触发函数被事件调用时,它在自己的实例中运行,并且它设置的任何全局值仅对该实例可见;例如,由电子表格或文档UI调用的另一个函数将拥有该非作用域对象(全局)的自己版本。

targetDocId的定义和检索将是缓存服务的一个很好的应用票据

function get_targetDocId () {
  var cache = CacheService.getPublicCache();
  var cached = cache.get("targetDocId");
  if (cached != null) {
    return cached;
  }
  var target = createDuplicateDocument(template, docName);  /// Need to add handling for pre-existing document
  var link = target.getUrl();
  var contents = target.getId();
  cache.put("targetDocId", contents, 1500); // cache for 25 minutes
  return contents;
}

现在,不尝试使用全局变量,只需调用以下函数:

...
var targetDoc = DocumentApp.openById(get_targetDocId());
...

注意缓存服务是可用于Google Apps脚本的持久存储的一个示例。Properties Service是在编写这个答案之后引入的,它是在执行实例之间持久化"全局"变量的一种重量轻得多的方法。


观察:由于generatePersonDatasheet()没有参数,因此tempatedocName似乎使用了全局(静态)。您可以直接生成targetDocId。

Bug:正如它所写的,get_targetDocId()每次需要刷新缓存时(15分钟)都会创建一个docName的新副本。您应该添加对预先存在的文件的可能性的处理。(您现有的onOpen()也是如此。)