问题
I had a prob with my script, which was greatly answered in this question. Basically custom functions cannot call services that require authorization. However, as far as I understood if I use simple triggers, such as onEdit it could work.
I checked the documentation suggested in the previous question, however I wasn't successful applying that to my code, which you can see below:
function FileName (id) {
var ss = DriveApp.getFileById(id);
return ss.getName();
}
How could I adapt my code to use simple triggers?
Here is a sample sheet that replicates the problem.
回答1:
I believe your goal as follows.
- You want to use your function of
FileName
as the custom function of Google Spreadsheet.- You want to automatically retrieve the filename when the file ID is put to the column "B".
- You want to put the filename to the column "C".
Issue and workaround:
Unfortunately, when the custom function is used, in the current specification, the most methods except several methods (for example, one of them is UrlFetchApp.) that the authorization is required cannot be used. By this, DriveApp.getFileById(id)
in your script cannot be used with the custom function. But there is a workaround. At the custom function, UrlFetchApp can be used. In this answer, I would like to propose to use the Web Apps with UrlFetchApp as the wrapper for authorizing. By this, the authorization can be done with the Web Apps. So your function can be run by the custom function.
Usage:
1. Prepare script.
Please copy and paste the following script to the script editor and save it.
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. Deploy Web Apps.
- On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
- Select "Me" for "Execute the app as:".
- By this, the script is run as the owner.
- Select "Anyone, even anonymous" for "Who has access to the app:".
- In this case, the access token is not required to request to Web Apps. But in this sample script, a key for requesting to Web Apps is used.
- Click "Deploy" button as new "Project version".
- Automatically open a dialog box of "Authorization required".
- Click "Review Permissions".
- Select own account.
- Click "Advanced" at "This app isn't verified".
- Click "Go to ### project name ###(unsafe)"
- Click "Allow" button.
- Click "OK".
- Copy the URL of Web Apps. It's like
https://script.google.com/macros/s/###/exec
.- When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
- Please set the URL of
https://script.google.com/macros/s/###/exec
to url of above script. And please redeploy Web Apps. By this, the latest script is reflected to the Web Apps. So please be careful this.
3. Test this workaround.
When the file ID is put to the cell "A1", please put =filename(A1)
to a cell as the custom function. By this, the script is run and the response value is returned.
Note:
Above sample script is a simple sample script for testing your script. So when you want to use the various methods, this post might be useful.
Please use this script with enabling V8.
As other method, I think that when the file ID is manually put to the column "B", the installable OnEdit trigger can be used. The sample script is as follows. Please set the sheet name. And please install the trigger to the function of
installedOnEdit
. Ref By this, when the file ID is put to the column "B" ofsheetName
, the file ID is put to the column "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); }
References:
- Web Apps
- Taking advantage of Web Apps with Google Apps Script
- Enhanced Custom Function for Google Spreadsheet using Web Apps as Wrapper
- Related questions
- Can you write a Google Sheets function that draws something?
- Error when running Youtube Data Service in App Scripts (js) – Daily Limit for Unauthenticated Use Exceeded
- How to enable not authorized users to protect the spreadsheet
- Changing Owner of the Sheet irrespective of the duplicator
- Installable Triggers
回答2:
As you can draw from the documentation, simple triggers cannot access services that require authorization neither
You have to use installable triggers instead.
However the workflow is very different from custom functions.
In your specific case, you can implement e.g. that when a cell in column A is being edited (that is a new URL is being inserted) - the respective file name is being found and returned into column D.
You can retrieve the value and the row in which the new URL is being inserted with help of event objects.
Sample:
function FileName (event) {
var id = event.value;
var ss = DriveApp.getFileById(id);
var row = event.range.getRow();
var sheet = event.range.getSheet();
// for column D:
var column = 4;
var returnCell = sheet.getRange(row,column);
returnCell.setValue(ss.getName());
}
For using an installable onEdit
trigger - bind it to this function through going on Edit > Current project's triggers
as explained here.
来源:https://stackoverflow.com/questions/64897709/using-triggers-with-custom-functions-on-google-apps-script