Google apps script 在Google Apps脚本上使用带有自定义函数的触发器

Google apps script 在Google Apps脚本上使用带有自定义函数的触发器,google-apps-script,google-sheets,Google Apps Script,Google Sheets,我的剧本有一个问题,这个问题在我的书中得到了很好的回答。 基本上,自定义函数不能调用需要授权的服务。然而,据我所知,如果我使用简单的触发器,比如onEdit,它就可以工作 我检查了上一个问题中建议的文档,但是我没有成功地将其应用到我的代码中,您可以在下面看到: function FileName (id) { var ss = DriveApp.getFileById(id); return ss.getName(); } 如何调整代码以使用简单触发器 这就复制了问题。从中可以看出,简

我的剧本有一个问题,这个问题在我的书中得到了很好的回答。 基本上,自定义函数不能调用需要授权的服务。然而,据我所知,如果我使用简单的触发器,比如onEdit,它就可以工作

我检查了上一个问题中建议的文档,但是我没有成功地将其应用到我的代码中,您可以在下面看到:

function FileName (id) {
  var ss = DriveApp.getFileById(id);
  return ss.getName();
}
如何调整代码以使用简单触发器

这就复制了问题。

从中可以看出,简单触发器也无法访问需要授权的服务 你必须改用

但是,工作流与自定义功能非常不同

在您的特定情况下,您可以实现,例如,当编辑列a中的单元格(即插入新URL)时,将找到相应的文件名并将其返回到列D中

您可以在的帮助下检索插入新URL的值和行

样本:

函数文件名(事件){
var id=event.value;
var ss=DriveApp.getFileById(id);
var row=event.range.getRow();
var sheet=event.range.getSheet();
//对于D列:
var列=4;
var returnCell=sheet.getRange(行、列);
returnCell.setValue(ss.getName());
}
对于使用可安装的
onEdit
触发器,请按照说明,通过执行
Edit>当前项目的触发器将其绑定到此函数。

正如您可以从中得出的,简单触发器也无法访问需要授权的服务 你必须改用

但是,工作流与自定义功能非常不同

在您的特定情况下,您可以实现,例如,当编辑列a中的单元格(即插入新URL)时,将找到相应的文件名并将其返回到列D中

您可以在的帮助下检索插入新URL的值和行

样本:

函数文件名(事件){
var id=event.value;
var ss=DriveApp.getFileById(id);
var row=event.range.getRow();
var sheet=event.range.getSheet();
//对于D列:
var列=4;
var returnCell=sheet.getRange(行、列);
returnCell.setValue(ss.getName());
}

对于使用可安装的
onEdit
触发器,请按照说明,通过执行
Edit>当前项目的触发器将其绑定到此函数。

我相信您的目标如下

  • 您想使用
    FileName
    函数作为Google电子表格的自定义函数。
    • 当文件ID放入“B”列时,您希望自动检索文件名
    • 您想将文件名放在“C”列
问题和解决方法: 不幸的是,在使用自定义函数时,在当前规范中,除了几个方法(例如,其中一个是UrlFetchApp)之外,大多数需要授权的方法都不能使用。因此,脚本中的
DriveApp.getFileById(id)
不能与自定义函数一起使用。但有一个解决办法。在自定义函数中,可以使用UrlFetchApp。在这个回答中,我想建议使用带有UrlFetchApp的Web应用作为授权的包装。通过这种方式,可以通过Web应用程序进行授权。因此,您的函数可以由自定义函数运行

用法: 1.准备脚本。 请将以下脚本复制粘贴到脚本编辑器并保存

const key = "samplekey"; // This is a key for using Web Apps. You can freely modify this.

// This is your function.
function FileName_(id) {
  var ss = DriveApp.getFileById(id);
  return ss.getName();
}

// Web Apps using as the wrapper for authorizing.
function doGet(e) {
  let res = "";
  if (e.parameter.key === key) {
    try {
      res = FileName_(e.parameter.id);
    } catch (err) {
      res = `Error: ${err.message}`;
    }
  } else {
    res = "Key error.";
  }
  return ContentService.createTextOutput(JSON.stringify({value: res}));
}

function Filename(id) {
  const webAppsUrl = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps after you set the Web Apps.

  const res = UrlFetchApp.fetch(`${webAppsUrl}?id=${id}&key=${key}`);
  if (res.getResponseCode() != 200) throw new Error(res.getContentText());
  return JSON.parse(res.getContentText()).value;
}
2.部署Web应用程序。
  • 在脚本编辑器上,通过“发布”->“部署为web应用”打开对话框
  • 选择“我”以执行应用程序:“”。
    • 这样,脚本将作为所有者运行
  • 为有权访问应用程序的用户选择“任何人,甚至匿名”“。
    • 在这种情况下,请求Web应用不需要访问令牌。但在这个示例脚本中,使用了一个用于请求Web应用程序的密钥
  • 单击“部署”按钮作为新的“项目版本”
  • 自动打开“需要授权”对话框。
  • 单击“查看权限”
  • 选择自己的帐户
  • 单击“此应用未验证”处的“高级”
  • 单击“转到####项目名称###(不安全)”
  • 单击“允许”按钮
  • 单击“确定”
  • 复制Web应用程序的URL。就像
    https://script.google.com/macros/s/###/exec
    • 当您修改Google Apps脚本时,请重新部署为新版本。这样,修改后的脚本将反映到Web应用程序中。请注意这一点。
  • 请设置
    https://script.google.com/macros/s/###/exec
    到上述脚本的url。请重新部署Web应用程序。这样,最新的脚本就会反映到Web应用程序中。所以请小心这个
  • 3.测试此解决方法。 将文件ID放入单元格“A1”时,请将
    =filename(A1)
    作为自定义函数放入单元格。这样,脚本将运行并返回响应值

    注:
    • 上面的示例脚本是用于测试脚本的简单示例脚本。因此,当您想使用各种方法时,本文可能会很有用

    • 请在启用V8时使用此脚本

    • 作为另一种方法,我认为当手动将文件ID放入列“B”时,可以使用可安装的OnEdit触发器。示例脚本如下所示。请设置工作表名称。请将触发器安装到
      installedEndit
      的功能中。这样,当文件ID放入
      sheetName
      的“B”列时,文件ID放入“C”列

    参考资料:
    • 相关问题

      • 我相信你的目标如下
          function installedOnEdit(e) {
            const sheetName = "Sheet1";
            const range = e.range;
            const sheet = range.getSheet();
            if (!(sheet.getSheetName() == sheetName && range.getColumn() == 2 && range.getRow() > 1)) return;
            const value = range.getValue();
            let res = "";
            try {
              res = DriveApp.getFileById(value).getName();
            } catch(e) {
              res = e.message;
            }
            range.offset(0, 1).setValue(res);
          }