我们正在使用谷歌表格进行费用报销。每个月月底,每个员工都会填写他们的费用报销单,并通过表格将收据附在谷歌驱动器上,然后通过电子邮件提交数据。这已经实施并且运作良好。
但是,我们目前在与员工共享的每张工作表上都附有一个脚本副本,因此如果代码有更新,我们必须对每个文档进行更新,这既费时又容易出错。
我想使用一个独立的脚本,可以从与个人共享的所有谷歌表格中访问。
我无法让驱动器选择器在独立的谷歌脚本中工作。
这是我的picker.html文件
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons.css">
<script>
// IMPORTANT: Replace the value for DEVELOPER_KEY with the API key obtained
// from the Google Developers Console.
var DEVELOPER_KEY = 'purposely removed';
var DIALOG_DIMENSIONS = {width: 600, height: 425};
var pickerApiLoaded = false;
/**
* Loads the Google Picker API.
*/
function onApiLoad() {
gapi.load('picker', {'callback': function() {
pickerApiLoaded = true;
}});
}
/**
* Gets the user's OAuth 2.0 access token from the server-side script so that
* it can be passed to Picker. This technique keeps Picker from needing to
* show its own authorization dialog, but is only possible if the OAuth scope
* that Picker needs is available in Apps Script. Otherwise, your Picker code
* will need to declare its own OAuth scopes.
*/
function getOAuthToken() {
google.script.run.withSuccessHandler(createPicker)
.withFailureHandler(showError).getOAuthToken();
}
/**
* Creates a Picker that can access the user's spreadsheets. This function
* uses advanced options to hide the Picker's left navigation panel and
* default title bar.
*
* @param {string} token An OAuth 2.0 access token that lets Picker access the
* file type specified in the addView call.
*/
function createPicker(token) {
if (pickerApiLoaded && token) {
var picker = new google.picker.PickerBuilder()
// Instruct Picker to display only spreadsheets in Drive. For other
// views, see https://developers.google.com/picker/docs/#otherviews
.addView(google.picker.ViewId.SPREADSHEETS)
// Hide the navigation panel so that Picker fills more of the dialog.
.enableFeature(google.picker.Feature.NAV_HIDDEN)
// Hide the title bar since an Apps Script dialog already has a title.
.hideTitleBar()
.setOAuthToken(token)
.setDeveloperKey(DEVELOPER_KEY)
.setCallback(pickerCallback)
.setOrigin(google.script.host.origin)
// Instruct Picker to fill the dialog, minus 2 pixels for the border.
.setSize(DIALOG_DIMENSIONS.width - 2,
DIALOG_DIMENSIONS.height - 2)
.build();
picker.setVisible(true);
} else {
showError('Unable to load the file picker.');
}
}
/**
* A callback function that extracts the chosen document's metadata from the
* response object. For details on the response object, see
* https://developers.google.com/picker/docs/result
*
* @param {object} data The response object.
*/
function pickerCallback(data) {
var action = data[google.picker.Response.ACTION];
if (action == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
var id = doc[google.picker.Document.ID];
var url = doc[google.picker.Document.URL];
var title = doc[google.picker.Document.NAME];
document.getElementById('result').innerHTML =
'<b>You chose:</b><br>Name: <a href="' + url + '">' + title +
'</a><br>ID: ' + id;
} else if (action == google.picker.Action.CANCEL) {
document.getElementById('result').innerHTML = 'Picker canceled.';
}
}
/**
* Displays an error message within the #result element.
*
* @param {string} message The error message to display.
*/
function showError(message) {
document.getElementById('result').innerHTML = 'Error: ' + message;
}
</script>
</head>
<body>
<div>
<button onclick='getOAuthToken()'>Select a file</button>
<p id='result'></p>
</div>
<script src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
然后我得到这个: Google Drive Picker
但是当我单击选择文件按钮时,我得到了这个:
Uncaught TypeError: google.script.run.withSuccessHandler(...).withFailureHandler(...).getOAuthToken is not a function
at getOAuthToken (userCodeAppPanel:20)
at HTMLButtonElement.onclick (userCodeAppPanel:1)
我的Code.gs包含此功能以及处理所选文件的功能。
function getOAuthToken() {
DriveApp.getRootFolder();
return ScriptApp.getOAuthToken();
}
如果您需要更多信息,请告诉我。
我已经尝试过这个解决方案但它不起作用: 无法从 Web 应用程序调用 Google 脚本 API 函数(类型错误:无法读取未定义的属性“运行”)
任何帮助深表感谢。
谢谢
如何重现问题:
转到:https ://script.google.com/ 创建一个新脚本。在 Code.gs 文件中输入:
function saonopen() { var ui = SpreadsheetApp.getUi(); // add some functions to the UI ui.createMenu('Menu') .addItem('Add Attachments', 'tsc.showPicker') .addToUi(); } function showPicker() { var html = HtmlService.createHtmlOutputFromFile('picker.html') .setWidth(600) .setHeight(425) .setSandboxMode(HtmlService.SandboxMode.IFRAME); SpreadsheetApp.getUi().showModalDialog(html, 'Select a file'); } function processFilesChosen(ids, titles, urls) { var targetSheetCost = switchTargetMonth('sheet').cost; // record the files on the target cost sheet for (var i in titles) { i = parseInt(i) targetSheetCost.getRange("H"+(i+3)).setFormula('=HYPERLINK("'+urls[i]+'","'+titles[i]+'")'); targetSheetCost.getRange("I"+(i+3)).setValue(ids[i]); // Because of Google security update, we can not use this setSharing. // DriveApp.getFileById(ids[i]).setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.COMMENT); } } function getOAuthToken() { DriveApp.getRootFolder(); return ScriptApp.getOAuthToken(); }
添加一个新的 html 文件,将其命名为 picker.html 并将之前发布的代码放在 picker.html 下。
将脚本发布为 API 可执行文件并记下 API ID
创建一个新的 google sheet 并使用前面提到的 API ID 从脚本视图的资源菜单中将独立脚本作为库导入。它将作为标识符 - 放置:
tsc
- 在 Code.gs 文件中放置:
function onOpen() {
tsc.saonopen()
}
- 最后为这两个项目启用 Picker 和 Drive API Access。