Google apps script 获取GAS项目中的功能列表

Google apps script 获取GAS项目中的功能列表,google-apps-script,google-apps-script-editor,Google Apps Script,Google Apps Script Editor,我想看看是否有办法获得我在谷歌应用程序脚本项目中拥有的所有功能的列表。我已经看到多个线程在获取所有谷歌应用程序脚本项目的列表,但到目前为止,还没有线程列出每个项目中的所有功能。有人知道这是否可能吗?我浏览了谷歌应用程序脚本参考概述,但没有找到任何突出的内容(当然,我可能错过了)。如果有人有任何建议,请告诉我 我能提供的最好例子是: 我有一个谷歌电子表格文件。谷歌电子表格附带一个GAS项目(通过谷歌工作表菜单“工具->脚本编辑器”访问),该项目有两个不同的功能,用于从工作表中获取值、进行一些计算并

我想看看是否有办法获得我在谷歌应用程序脚本项目中拥有的所有功能的列表。我已经看到多个线程在获取所有谷歌应用程序脚本项目的列表,但到目前为止,还没有线程列出每个项目中的所有功能。有人知道这是否可能吗?我浏览了谷歌应用程序脚本参考概述,但没有找到任何突出的内容(当然,我可能错过了)。如果有人有任何建议,请告诉我

我能提供的最好例子是:

我有一个谷歌电子表格文件。谷歌电子表格附带一个GAS项目(通过谷歌工作表菜单“工具->脚本编辑器”访问),该项目有两个不同的功能,用于从工作表中获取值、进行一些计算并将结果发布到不同的工作表

我试图完成的是:运行某种函数,可以为我提供GAS项目中所有函数的列表(最好是字符串值)。例如:

["runMyCalculations","myOnEdit","sortClosedFiles","formatSheets"]
所有这些都是只有打开脚本编辑器并在下拉菜单中选择它并单击“运行”按钮才能运行的函数


我想做的是创建一个动态列表,列出我拥有的所有函数,这样我就可以将它们传递到一个“打开”触发函数中,该函数在工作表中创建一个自定义菜单,列出我拥有的所有函数。我需要这样做,这样我就可以简单地更改工作表,转到下拉菜单并运行需要运行的功能,而不必打开脚本编辑器。

您可以使用应用程序脚本API从应用程序脚本文件中获取所有内容。 下面的代码可以选择传入要获取的文件名。您必须提供应用程序脚本文件ID。传入gs文件名是可选的。提供了3个功能。完成所有工作的函数、使用测试参数调用该函数的函数以及日志函数。不需要OAuth库,因为令牌是从ScriptApp服务获取的

注意:要使此代码正常工作,您需要启用应用程序脚本API,并批准对驱动器的权限。确保在第一次运行此代码时,检查从
UrlFetchApp.fetch()调用返回的错误消息。它可能有一个链接,您需要使用该链接来启用应用程序脚本API

function getFuncNames(po) {
  var allFiles,dataContentAsString,downloadUrl,fileContents,fileData,i,options,
      theAccessTkn,thisFileName;
  var ndxOfFunction=0,counter=0, ndxOfEnd=0, functionName="", allFncNames=[],
      hasSpaces = 0;
  var innerObj, thisFile, fileType = "", thisGS_Content,howManyFiles, allGsContent="";

  /*
    Get all script function names.  If no gs file name is provided, the code
    gets all the function names.
  */

  /*
    po.fileID - required - The Apps Script file ID
    po.gsFileName - optional - the gs code file name to get - gets just one 
       file instead of all files
  */

  //ll('po',po);

  if (!po.fileID) {
    return false;
  }

  theAccessTkn = ScriptApp.getOAuthToken();//Get an access token for OAuth

  downloadUrl = "https://script.google.com/feeds/download/export?id=" +
      po.fileID + "&format=json";//create url

  options = {
    "kind": "drive#file",
    "id": po.fileID,
    "downloadUrl": downloadUrl,
    "headers": {
       'Authorization': 'Bearer ' +  theAccessTkn,
     },
    "contentType": "application/vnd.google-apps.script+json",
    "method" : "GET"
  };

  fileData = UrlFetchApp.fetch(downloadUrl, options);//Get all the content from the Apps Script file
  //ll('fileData',fileData)

  dataContentAsString = fileData.getContentText();

  fileContents = JSON.parse(dataContentAsString);//Parse string into object

  allFiles = fileContents.files;//All the files in the Apps Script project

  howManyFiles = allFiles.length;

  for (i=0;i<howManyFiles;i++) {
    thisFile = allFiles[i];//Get one inner element that represents one file
    if (!thisFile) {continue;}

    fileType = thisFile.type;
    if (fileType !== "server_js") {continue;}//This is not a gs file - its HTML or json

    thisFileName = thisFile.name;
    //ll('typeof thisFileName',typeof thisFileName)
    //ll('thisFileName',thisFileName)
    //ll('equal',po.gsFileName !== thisFile.name)

    if (po.gsFileName) {//Is there a setting for the file name to restrict the search to
      if (po.gsFileName !== thisFile.name) {//The name to search for is not this file name
        continue;
      }
    }

    thisGS_Content = thisFile.source;//source is the key name for the file content
    allGsContent = allGsContent + thisGS_Content;
  }

  //ll('allGsContent',allGsContent)

  while (ndxOfFunction !== -1 || counter < 1000) {
    ndxOfFunction = allGsContent.indexOf("function ");

    //ll('ndxOfFunction',ndxOfFunction)
    if (ndxOfFunction === -1) {break};

    allGsContent = allGsContent.slice(ndxOfFunction+9);//Remove everything in front of 'function' first

    ndxOfEnd = allGsContent.indexOf("(");
    functionName = allGsContent.slice(0,ndxOfEnd);
    allGsContent = allGsContent.slice(ndxOfEnd+2);//Remove the     
    hasSpaces = functionName.indexOf(" ");

    if (hasSpaces !== -1) {continue;}

    if (functionName.length < 150) {
      allFncNames.push(functionName);
    }//Any string over 150 long is probably not a function name

    counter ++;
  };

  //ll('allFncNames',allFncNames)
  return allFncNames;
};

function runOtherFnk() {
  getFuncNames({fileID:"Your File ID here",gsFileName:"Code"});
}

function ll(a,b) {
  //Logger.log(typeof a)

  if (typeof b === 'object') {
    b = JSON.stringify(b);
  }

  Logger.log(a + ":" + b)
}

您可以使用应用程序脚本API从应用程序脚本文件中获取所有内容。 下面的代码可以选择传入要获取的文件名。您必须提供应用程序脚本文件ID。传入gs文件名是可选的。提供了3个功能。完成所有工作的函数、使用测试参数调用该函数的函数以及日志函数。不需要OAuth库,因为令牌是从ScriptApp服务获取的

注意:要使此代码正常工作,您需要启用应用程序脚本API,并批准对驱动器的权限。确保在第一次运行此代码时,检查从
UrlFetchApp.fetch()调用返回的错误消息。它可能有一个链接,您需要使用该链接来启用应用程序脚本API

function getFuncNames(po) {
  var allFiles,dataContentAsString,downloadUrl,fileContents,fileData,i,options,
      theAccessTkn,thisFileName;
  var ndxOfFunction=0,counter=0, ndxOfEnd=0, functionName="", allFncNames=[],
      hasSpaces = 0;
  var innerObj, thisFile, fileType = "", thisGS_Content,howManyFiles, allGsContent="";

  /*
    Get all script function names.  If no gs file name is provided, the code
    gets all the function names.
  */

  /*
    po.fileID - required - The Apps Script file ID
    po.gsFileName - optional - the gs code file name to get - gets just one 
       file instead of all files
  */

  //ll('po',po);

  if (!po.fileID) {
    return false;
  }

  theAccessTkn = ScriptApp.getOAuthToken();//Get an access token for OAuth

  downloadUrl = "https://script.google.com/feeds/download/export?id=" +
      po.fileID + "&format=json";//create url

  options = {
    "kind": "drive#file",
    "id": po.fileID,
    "downloadUrl": downloadUrl,
    "headers": {
       'Authorization': 'Bearer ' +  theAccessTkn,
     },
    "contentType": "application/vnd.google-apps.script+json",
    "method" : "GET"
  };

  fileData = UrlFetchApp.fetch(downloadUrl, options);//Get all the content from the Apps Script file
  //ll('fileData',fileData)

  dataContentAsString = fileData.getContentText();

  fileContents = JSON.parse(dataContentAsString);//Parse string into object

  allFiles = fileContents.files;//All the files in the Apps Script project

  howManyFiles = allFiles.length;

  for (i=0;i<howManyFiles;i++) {
    thisFile = allFiles[i];//Get one inner element that represents one file
    if (!thisFile) {continue;}

    fileType = thisFile.type;
    if (fileType !== "server_js") {continue;}//This is not a gs file - its HTML or json

    thisFileName = thisFile.name;
    //ll('typeof thisFileName',typeof thisFileName)
    //ll('thisFileName',thisFileName)
    //ll('equal',po.gsFileName !== thisFile.name)

    if (po.gsFileName) {//Is there a setting for the file name to restrict the search to
      if (po.gsFileName !== thisFile.name) {//The name to search for is not this file name
        continue;
      }
    }

    thisGS_Content = thisFile.source;//source is the key name for the file content
    allGsContent = allGsContent + thisGS_Content;
  }

  //ll('allGsContent',allGsContent)

  while (ndxOfFunction !== -1 || counter < 1000) {
    ndxOfFunction = allGsContent.indexOf("function ");

    //ll('ndxOfFunction',ndxOfFunction)
    if (ndxOfFunction === -1) {break};

    allGsContent = allGsContent.slice(ndxOfFunction+9);//Remove everything in front of 'function' first

    ndxOfEnd = allGsContent.indexOf("(");
    functionName = allGsContent.slice(0,ndxOfEnd);
    allGsContent = allGsContent.slice(ndxOfEnd+2);//Remove the     
    hasSpaces = functionName.indexOf(" ");

    if (hasSpaces !== -1) {continue;}

    if (functionName.length < 150) {
      allFncNames.push(functionName);
    }//Any string over 150 long is probably not a function name

    counter ++;
  };

  //ll('allFncNames',allFncNames)
  return allFncNames;
};

function runOtherFnk() {
  getFuncNames({fileID:"Your File ID here",gsFileName:"Code"});
}

function ll(a,b) {
  //Logger.log(typeof a)

  if (typeof b === 'object') {
    b = JSON.stringify(b);
  }

  Logger.log(a + ":" + b)
}

记录此
的属性。这就是我需要的信息!非常感谢。附加问题:在我测试这个的GAS项目中,我有我的Code.gs文件和macros.gs文件。“this”似乎是一个包含函数的对象,该函数包含我的所有函数(来自Code.gs和macros.gs)。是否有方法仅返回Code.gs中的函数?据我所见,“this”对象的唯一属性是实际函数本身。对于它们的来源(代码或宏)没有任何倾向。应用程序脚本在所有文件中都有一个名称空间。我已更新了答案以显示应用程序脚本API的使用情况。请记录
的属性。这就是我需要的信息!非常感谢。附加问题:在我测试这个的GAS项目中,我有我的Code.gs文件和macros.gs文件。“this”似乎是一个包含函数的对象,该函数包含我的所有函数(来自Code.gs和macros.gs)。是否有方法仅返回Code.gs中的函数?据我所见,“this”对象的唯一属性是实际函数本身。对于它们的来源(代码或宏)没有任何倾向。应用程序脚本在所有文件中都有一个名称空间。我已经更新了答案以显示应用程序脚本API的使用情况。这很有效!我很感激你的代码。我猜它背后的解释是“this”指的是文件本身。我从来不知道这件事。很高兴知道!非常感谢。附加问题:在我测试这个的GAS项目中,我有我的Code.gs文件和macros.gs文件。“this”似乎是一个包含函数的对象,该函数包含我的所有函数(来自Code.gs和macros.gs)。是否有方法仅返回Code.gs中的函数?据我所见,“this”对象的唯一属性是实际函数本身。对于它们的来源(代码或宏)没有任何倾向。是的,有一种方法可以只从Code.gs获取函数名,您需要使用应用程序脚本API。我已经更新了答案。这很有效!我很感激你的代码。我猜它背后的解释是“this”指的是文件本身。我从来不知道这件事。很高兴知道!非常感谢。附加问题:在我测试这个的GAS项目中,我有我的Code.gs文件和macros.gs文件。“this”似乎是一个包含函数的对象,该函数包含我的所有函数(来自Code.gs和macros.gs)。是否有方法仅返回Code.gs中的函数?据我所见,“this”对象的唯一属性是实际函数本身。对于它们的来源(代码或宏)没有任何倾向