Google Apps Script API มีเมธอด scripts.run
ที่จะเรียกใช้ฟังก์ชัน Apps Script ที่ระบุจากระยะไกล คุณสามารถใช้วิธีการนี้ในแอปพลิเคชันการเรียกใช้เพื่อเรียกใช้ฟังก์ชันในโปรเจ็กต์สคริปต์โปรเจ็กต์ใดโปรเจ็กต์หนึ่งจากระยะไกลและรับคําตอบ
ข้อกำหนด
คุณต้องมีคุณสมบัติตรงตามข้อกำหนดต่อไปนี้ก่อน แอปพลิเคชันการโทรจะใช้เมธอด scripts.run
ได้ คุณต้องดำเนินการดังนี้
ทำให้โปรเจ็กต์สคริปต์ใช้งานได้เป็นไฟล์ดำเนินการของ API คุณสามารถทำให้โปรเจ็กต์ใช้งานได้ ยกเลิกการทำให้ใช้งานได้ และทำให้โปรเจ็กต์ใช้งานได้อีกครั้งตามที่จำเป็น
ระบุโทเค็น OAuth ที่กำหนดขอบเขตอย่างเหมาะสมสำหรับการดำเนินการ โทเค็น OAuth นี้ต้องครอบคลุมขอบเขตทั้งหมดที่สคริปต์ใช้ ไม่ใช่เฉพาะขอบเขตที่ฟังก์ชันที่เรียกใช้ใช้เท่านั้น ดูรายการขอบเขตการให้สิทธิ์ทั้งหมดได้ในข้อมูลอ้างอิงเมธอด
ตรวจสอบว่าสคริปต์และไคลเอ็นต์ OAuth2 ของแอปพลิเคชันการเรียกใช้แชร์โปรเจ็กต์ Google Cloud ร่วมกัน โปรเจ็กต์ที่อยู่ในระบบคลาวด์ต้องเป็นโปรเจ็กต์ระบบคลาวด์มาตรฐาน เนื่องจากโปรเจ็กต์เริ่มต้นที่สร้างสำหรับโปรเจ็กต์ Apps Script จะไม่เพียงพอ คุณจะใช้โปรเจ็กต์ Cloud มาตรฐานใหม่หรือที่มีอยู่ก็ได้
เปิดใช้ Google Apps Script API ในโปรเจ็กต์ที่อยู่ในระบบคลาวด์
เมธอด scripts.run
เมธอด scripts.run
ต้องใช้ข้อมูลระบุคีย์จึงจะเรียกใช้ได้
- รหัสของโปรเจ็กต์สคริปต์
- ชื่อฟังก์ชันที่จะเรียกใช้
- รายการพารามิเตอร์ ที่ฟังก์ชันต้องการ (หากมี)
หรือคุณจะกำหนดค่าสคริปต์ให้ทำงานในโหมดการพัฒนาก็ได้
โหมดนี้จะดำเนินการกับโปรเจ็กต์สคริปต์เวอร์ชันที่บันทึกล่าสุดแทนที่จะเป็นเวอร์ชันที่ใช้งานล่าสุด ซึ่งทําได้โดยตั้งค่าบูลีน devMode
ในเนื้อหาของคําขอเป็น true
เฉพาะเจ้าของสคริปต์เท่านั้นที่เรียกใช้สคริปต์ในโหมดการพัฒนาได้
การจัดการประเภทข้อมูลพารามิเตอร์
การใช้เมธอด Apps Script API scripts.run
มักจะรวมถึงการส่งข้อมูลไปยัง Apps Script เป็นพารามิเตอร์ฟังก์ชัน และการรับข้อมูลกลับมาเป็นค่าฟังก์ชันที่ส่งกลับมา API สามารถรับและแสดงผลค่าที่มีประเภทพื้นฐานเท่านั้น ซึ่งได้แก่ สตริง อาร์เรย์ ออบเจ็กต์ ตัวเลข และบูลีน ซึ่งคล้ายกับประเภทพื้นฐานใน JavaScript ออบเจ็กต์ของ Apps Script ที่ซับซ้อนขึ้น เช่น เอกสารหรือชีตไม่สามารถส่งผ่านหรือจากโปรเจ็กต์สคริปต์ด้วย API
เมื่อเขียนแอปพลิเคชันการโทรด้วยภาษาที่มีประเภทขั้นสูง เช่น Java ระบบจะส่งผ่านพารามิเตอร์เป็นรายการหรืออาร์เรย์ของออบเจ็กต์ทั่วไปที่ตรงกับประเภทพื้นฐานเหล่านี้ ในหลายกรณี คุณสามารถใช้
Conversion ประเภทพื้นฐานโดยอัตโนมัติ เช่น ฟังก์ชันที่ใช้พารามิเตอร์ตัวเลขอาจได้รับออบเจ็กต์ Java Double
หรือ Integer
หรือ Long
เป็นพารามิเตอร์โดยไม่ต้องมีการจัดการเพิ่มเติม
เมื่อ API แสดงผลการตอบกลับฟังก์ชัน คุณมักจะต้องแคสต์ค่าที่แสดงผลไปยังประเภทที่ถูกต้องก่อนจึงจะใช้งานได้ ตัวอย่างการใช้ Java มีดังนี้
- ตัวเลขที่ API แสดงผลไปยังแอปพลิเคชัน Java จะปรากฏเป็นออบเจ็กต์
java.math.BigDecimal
และอาจต้องแปลงเป็นประเภทDoubles
หรือint
ตามความจำเป็น หากฟังก์ชัน Apps Script แสดงผลอาร์เรย์ของสตริง แอปพลิเคชัน Java จะแคสต์การตอบกลับไปยังออบเจ็กต์
List<String>
List<String> mylist = (List<String>)(op.getResponse().get("result"));
หากต้องการแสดงผลอาร์เรย์ของ
Bytes
อาจสะดวกที่จะเข้ารหัสอาร์เรย์เป็นสตริง base64 ภายในฟังก์ชัน Apps Script และแสดงผลสตริงนั้นแทนreturn Utilities.base64Encode(myByteArray); // returns a String.
ตัวอย่างโค้ดตัวอย่างด้านล่างจะแสดงวิธีตีความการตอบกลับของ API
ขั้นตอนทั่วไป
ข้อมูลต่อไปนี้จะอธิบายกระบวนการทั่วไปในการใช้ Apps Script API เพื่อเรียกใช้ฟังก์ชันของ Apps Script
ขั้นตอนที่ 1: ตั้งค่าโปรเจ็กต์ Cloud ทั่วไป
ทั้งสคริปต์และแอปพลิเคชันการเรียกใช้ต้องแชร์โปรเจ็กต์ที่อยู่ในระบบคลาวด์เดียวกัน โปรเจ็กต์ที่อยู่ในระบบคลาวด์นี้อาจเป็นโปรเจ็กต์ที่มีอยู่หรือโปรเจ็กต์ใหม่ที่สร้างขึ้นเพื่อวัตถุประสงค์นี้ก็ได้ เมื่อมีโปรเจ็กต์ที่อยู่ในระบบคลาวด์แล้ว คุณต้องเปลี่ยนโปรเจ็กต์สคริปต์เพื่อใช้งาน
ขั้นตอนที่ 2: ปรับใช้สคริปต์เป็นไฟล์ปฏิบัติการของ API
- เปิดโครงการ Apps Script ที่มีฟังก์ชันที่ต้องการใช้
- ที่ด้านขวาบน ให้คลิกทำให้ใช้งานได้ > การทำให้ใช้งานได้ใหม่
- ในกล่องโต้ตอบที่เปิดขึ้น ให้คลิกเปิดใช้ประเภทการทำให้ใช้งานได้
> ดำเนินการของ API
- ในเมนูแบบเลื่อนลง "ผู้ที่มีสิทธิ์เข้าถึง" ให้เลือกผู้ใช้ที่ได้รับอนุญาตให้เรียกใช้ฟังก์ชันของสคริปต์โดยใช้ Apps Script API
- คลิกทำให้ใช้งานได้
ขั้นตอนที่ 3: กำหนดค่าแอปพลิเคชันการโทร
แอปพลิเคชันการเรียกใช้ต้องเปิดใช้ Apps Script API และสร้างข้อมูลรับรอง OAuth ก่อนจึงจะใช้งานได้ คุณต้องมีสิทธิ์เข้าถึงโปรเจ็กต์ที่อยู่ในระบบคลาวด์ จึงจะดำเนินการนี้ได้
- กำหนดค่าโปรเจ็กต์ที่อยู่ในระบบคลาวด์ที่แอปพลิเคชันและสคริปต์การโทรใช้อยู่ โดยทำตามขั้นตอนต่อไปนี้
- เปิดโครงการสคริปต์และคลิกภาพรวม
ทางด้านซ้าย
- ในส่วนขอบเขตของโปรเจ็กต์ OAuth ให้บันทึกขอบเขตทั้งหมดที่สคริปต์ต้องการ
ในโค้ดแอปพลิเคชันการเรียกใช้ ให้สร้างโทเค็นการเข้าถึง OAuth ของสคริปต์สำหรับการเรียก API ซึ่งไม่ใช่โทเค็นที่ API ใช้ แต่เป็นโทเค็นที่สคริปต์ต้องใช้เมื่อดำเนินการ ซึ่งควรสร้างโดยใช้รหัสไคลเอ็นต์ของโปรเจ็กต์ที่อยู่ในระบบคลาวด์และขอบเขตสคริปต์ที่คุณบันทึกไว้
ไลบรารีของไคลเอ็นต์ Google จะช่วยสร้างโทเค็นนี้และจัดการ OAuth สำหรับแอปพลิเคชันได้อย่างมาก ซึ่งโดยปกติจะช่วยให้คุณสร้างออบเจ็กต์ "ข้อมูลเข้าสู่ระบบ" ระดับที่สูงกว่าได้โดยใช้ขอบเขตสคริปต์ โปรดดูการเริ่มต้นใช้งาน Apps Script API อย่างรวดเร็วเพื่อดูตัวอย่างการสร้างออบเจ็กต์ข้อมูลเข้าสู่ระบบจากรายการขอบเขต
ขั้นตอนที่ 4: ส่งคำขอscript.run
เมื่อกำหนดค่าแอปพลิเคชันการโทรแล้ว คุณจะโทรออกได้
scripts.run
การเรียก API แต่ละรายการมีขั้นตอนดังนี้
- สร้างคำขอ API โดยใช้รหัสสคริปต์ ชื่อฟังก์ชัน และพารามิเตอร์ที่จำเป็น
- เรียกใช้
scripts.run
และรวมโทเค็น OAuth ของสคริปต์ที่คุณสร้างไว้ในส่วนหัว (หากใช้คำขอPOST
พื้นฐาน) หรือใช้ออบเจ็กต์ข้อมูลเข้าสู่ระบบที่สร้างด้วยขอบเขตสคริปต์ - ปล่อยให้สคริปต์ทำงานจนเสร็จสิ้น สคริปต์อาจใช้เวลาดำเนินการสูงสุด 6 นาที ดังนั้นแอปพลิเคชันของคุณจึงควรจะอนุญาต
- เมื่อดำเนินการเสร็จสิ้น ฟังก์ชันของสคริปต์อาจแสดงผลค่า ซึ่ง API จะส่งกลับไปที่แอปพลิเคชันหากค่านั้นเป็นประเภทที่รองรับ
ดูตัวอย่างการเรียก API script.run
รายการได้ที่ด้านล่าง
ตัวอย่างคำขอ API
ตัวอย่างต่อไปนี้แสดงวิธีส่งคำขอเรียกใช้ Apps Script API ในภาษาต่างๆ โดยเรียกใช้ฟังก์ชัน Apps Script เพื่อพิมพ์รายการโฟลเดอร์ในไดเรกทอรีรากของผู้ใช้ ต้องระบุรหัสสคริปต์ของโปรเจ็กต์ Apps Script ที่มีฟังก์ชันที่เรียกใช้แล้วในตำแหน่งที่ระบุด้วย ENTER_YOUR_SCRIPT_ID_HERE
ตัวอย่างดังกล่าวใช้ไลบรารีของไคลเอ็นต์ Google API สำหรับภาษาที่เกี่ยวข้อง
สคริปต์เป้าหมาย
ฟังก์ชันในสคริปต์นี้จะใช้ Drive API
คุณต้องเปิดใช้ Drive API ในโปรเจ็กต์ที่โฮสต์สคริปต์
นอกจากนี้ แอปพลิเคชันการเรียกใช้ยังต้องส่งข้อมูลเข้าสู่ระบบ OAuth ซึ่งรวมถึงขอบเขตไดรฟ์ต่อไปนี้
https://www.googleapis.com/auth/drive
ตัวอย่างแอปพลิเคชันที่นี่ใช้ไลบรารีของไคลเอ็นต์ Google เพื่อสร้างออบเจ็กต์ข้อมูลเข้าสู่ระบบสำหรับ OAuth โดยใช้ขอบเขตนี้
/**
* Return the set of folder names contained in the user's root folder as an
* object (with folder IDs as keys).
* @return {Object} A set of folder names keyed by folder ID.
*/
function getFoldersUnderRoot() {
const root = DriveApp.getRootFolder();
const folders = root.getFolders();
const folderSet = {};
while (folders.hasNext()) {
const folder = folders.next();
folderSet[folder.getId()] = folder.getName();
}
return folderSet;
}
Java
/**
* Create a HttpRequestInitializer from the given one, except set
* the HTTP read timeout to be longer than the default (to allow
* called scripts time to execute).
*
* @param {HttpRequestInitializer} requestInitializer the initializer
* to copy and adjust; typically a Credential object.
* @return an initializer with an extended read timeout.
*/
private static HttpRequestInitializer setHttpTimeout(
final HttpRequestInitializer requestInitializer) {
return new HttpRequestInitializer() {
@Override
public void initialize(HttpRequest httpRequest) throws IOException {
requestInitializer.initialize(httpRequest);
// This allows the API to call (and avoid timing out on)
// functions that take up to 6 minutes to complete (the maximum
// allowed script run time), plus a little overhead.
httpRequest.setReadTimeout(380000);
}
};
}
/**
* Build and return an authorized Script client service.
*
* @param {Credential} credential an authorized Credential object
* @return an authorized Script client service
*/
public static Script getScriptService() throws IOException {
Credential credential = authorize();
return new Script.Builder(
HTTP_TRANSPORT, JSON_FACTORY, setHttpTimeout(credential))
.setApplicationName(APPLICATION_NAME)
.build();
}
/**
* Interpret an error response returned by the API and return a String
* summary.
*
* @param {Operation} op the Operation returning an error response
* @return summary of error response, or null if Operation returned no
* error
*/
public static String getScriptError(Operation op) {
if (op.getError() == null) {
return null;
}
// Extract the first (and only) set of error details and cast as a Map.
// The values of this map are the script's 'errorMessage' and
// 'errorType', and an array of stack trace elements (which also need to
// be cast as Maps).
Map<String, Object> detail = op.getError().getDetails().get(0);
List<Map<String, Object>> stacktrace =
(List<Map<String, Object>>) detail.get("scriptStackTraceElements");
java.lang.StringBuilder sb =
new StringBuilder("\nScript error message: ");
sb.append(detail.get("errorMessage"));
sb.append("\nScript error type: ");
sb.append(detail.get("errorType"));
if (stacktrace != null) {
// There may not be a stacktrace if the script didn't start
// executing.
sb.append("\nScript error stacktrace:");
for (Map<String, Object> elem : stacktrace) {
sb.append("\n ");
sb.append(elem.get("function"));
sb.append(":");
sb.append(elem.get("lineNumber"));
}
}
sb.append("\n");
return sb.toString();
}
public static void main(String[] args) throws IOException {
// ID of the script to call. Acquire this from the Apps Script editor,
// under Publish > Deploy as API executable.
String scriptId = "ENTER_YOUR_SCRIPT_ID_HERE";
Script service = getScriptService();
// Create an execution request object.
ExecutionRequest request = new ExecutionRequest()
.setFunction("getFoldersUnderRoot");
try {
// Make the API request.
Operation op =
service.scripts().run(scriptId, request).execute();
// Print results of request.
if (op.getError() != null) {
// The API executed, but the script returned an error.
System.out.println(getScriptError(op));
} else {
// The result provided by the API needs to be cast into
// the correct type, based upon what types the Apps
// Script function returns. Here, the function returns
// an Apps Script Object with String keys and values,
// so must be cast into a Java Map (folderSet).
Map<String, String> folderSet =
(Map<String, String>) (op.getResponse().get("result"));
if (folderSet.size() == 0) {
System.out.println("No folders returned!");
} else {
System.out.println("Folders under your root folder:");
for (String id : folderSet.keySet()) {
System.out.printf(
"\t%s (%s)\n", folderSet.get(id), id);
}
}
}
} catch (GoogleJsonResponseException e) {
// The API encountered a problem before the script was called.
e.printStackTrace(System.out);
}
}
JavaScript
/**
* Load the API and make an API call. Display the results on the screen.
*/
function callScriptFunction() {
const scriptId = '<ENTER_YOUR_SCRIPT_ID_HERE>';
// Call the Apps Script API run method
// 'scriptId' is the URL parameter that states what script to run
// 'resource' describes the run request body (with the function name
// to execute)
try {
gapi.client.script.scripts.run({
'scriptId': scriptId,
'resource': {
'function': 'getFoldersUnderRoot',
},
}).then(function(resp) {
const result = resp.result;
if (result.error && result.error.status) {
// The API encountered a problem before the script
// started executing.
appendPre('Error calling API:');
appendPre(JSON.stringify(result, null, 2));
} else if (result.error) {
// The API executed, but the script returned an error.
// Extract the first (and only) set of error details.
// The values of this object are the script's 'errorMessage' and
// 'errorType', and an array of stack trace elements.
const error = result.error.details[0];
appendPre('Script error message: ' + error.errorMessage);
if (error.scriptStackTraceElements) {
// There may not be a stacktrace if the script didn't start
// executing.
appendPre('Script error stacktrace:');
for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
const trace = error.scriptStackTraceElements[i];
appendPre('\t' + trace.function + ':' + trace.lineNumber);
}
}
} else {
// The structure of the result will depend upon what the Apps
// Script function returns. Here, the function returns an Apps
// Script Object with String keys and values, and so the result
// is treated as a JavaScript object (folderSet).
const folderSet = result.response.result;
if (Object.keys(folderSet).length == 0) {
appendPre('No folders returned!');
} else {
appendPre('Folders under your root folder:');
Object.keys(folderSet).forEach(function(id) {
appendPre('\t' + folderSet[id] + ' (' + id + ')');
});
}
}
});
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
}
Node.js
/**
* Call an Apps Script function to list the folders in the user's root Drive
* folder.
*
*/
async function callAppsScript() {
const scriptId = '1xGOh6wCm7hlIVSVPKm0y_dL-YqetspS5DEVmMzaxd_6AAvI-_u8DSgBT';
const {GoogleAuth} = require('google-auth-library');
const {google} = require('googleapis');
// Get credentials and build service
// TODO (developer) - Use appropriate auth mechanism for your app
const auth = new GoogleAuth({
scopes: 'https://www.googleapis.com/auth/drive',
});
const script = google.script({version: 'v1', auth});
try {
// Make the API request. The request object is included here as 'resource'.
const resp = await script.scripts.run({
auth: auth,
resource: {
function: 'getFoldersUnderRoot',
},
scriptId: scriptId,
});
if (resp.error) {
// The API executed, but the script returned an error.
// Extract the first (and only) set of error details. The values of this
// object are the script's 'errorMessage' and 'errorType', and an array
// of stack trace elements.
const error = resp.error.details[0];
console.log('Script error message: ' + error.errorMessage);
console.log('Script error stacktrace:');
if (error.scriptStackTraceElements) {
// There may not be a stacktrace if the script didn't start executing.
for (let i = 0; i < error.scriptStackTraceElements.length; i++) {
const trace = error.scriptStackTraceElements[i];
console.log('\t%s: %s', trace.function, trace.lineNumber);
}
}
} else {
// The structure of the result will depend upon what the Apps Script
// function returns. Here, the function returns an Apps Script Object
// with String keys and values, and so the result is treated as a
// Node.js object (folderSet).
const folderSet = resp.response.result;
if (Object.keys(folderSet).length == 0) {
console.log('No folders returned!');
} else {
console.log('Folders under your root folder:');
Object.keys(folderSet).forEach(function(id) {
console.log('\t%s (%s)', folderSet[id], id);
});
}
}
} catch (err) {
// TODO(developer) - Handle error
throw err;
}
}
Python
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def main():
"""Runs the sample."""
# pylint: disable=maybe-no-member
script_id = "1VFBDoJFy6yb9z7-luOwRv3fCmeNOzILPnR4QVmR0bGJ7gQ3QMPpCW-yt"
creds, _ = google.auth.default()
service = build("script", "v1", credentials=creds)
# Create an execution request object.
request = {"function": "getFoldersUnderRoot"}
try:
# Make the API request.
response = service.scripts().run(scriptId=script_id, body=request).execute()
if "error" in response:
# The API executed, but the script returned an error.
# Extract the first (and only) set of error details. The values of
# this object are the script's 'errorMessage' and 'errorType', and
# a list of stack trace elements.
error = response["error"]["details"][0]
print(f"Script error message: {0}.{format(error['errorMessage'])}")
if "scriptStackTraceElements" in error:
# There may not be a stacktrace if the script didn't start
# executing.
print("Script error stacktrace:")
for trace in error["scriptStackTraceElements"]:
print(f"\t{0}: {1}.{format(trace['function'], trace['lineNumber'])}")
else:
# The structure of the result depends upon what the Apps Script
# function returns. Here, the function returns an Apps Script
# Object with String keys and values, and so the result is
# treated as a Python dictionary (folder_set).
folder_set = response["response"].get("result", {})
if not folder_set:
print("No folders returned!")
else:
print("Folders under your root folder:")
for folder_id, folder in folder_set.items():
print(f"\t{0} ({1}).{format(folder, folder_id)}")
except HttpError as error:
# The API encountered a problem before the script started executing.
print(f"An error occurred: {error}")
print(error.content)
if __name__ == "__main__":
main()
ข้อจำกัด
Apps Script API มีข้อจำกัดหลายประการดังนี้
โปรเจ็กต์ Cloud ทั่วไป สคริปต์ที่เรียกใช้และแอปพลิเคชันการเรียกใช้ต้องแชร์โปรเจ็กต์ที่อยู่ในระบบคลาวด์ โปรเจ็กต์ที่อยู่ในระบบคลาวด์ต้องเป็นโปรเจ็กต์ระบบคลาวด์มาตรฐาน แต่โปรเจ็กต์เริ่มต้นที่สร้างสำหรับโปรเจ็กต์ Apps Script นั้นไม่เพียงพอ โปรเจ็กต์ Cloud มาตรฐานอาจเป็นโปรเจ็กต์ใหม่หรือโปรเจ็กต์ที่มีอยู่ก็ได้
พารามิเตอร์พื้นฐานและประเภทการคืนสินค้า API ไม่สามารถส่งหรือแสดงผลออบเจ็กต์เฉพาะของ Apps Script (เช่น Documents, Blob, ปฏิทิน, ไฟล์ในไดรฟ์ ฯลฯ) ไปยังแอปพลิเคชัน เฉพาะประเภทพื้นฐานเท่านั้น เช่น สตริง อาร์เรย์ ออบเจ็กต์ ตัวเลข และบูลีน ที่จะส่งผ่านและแสดงผลได้
ขอบเขตของ OAuth API จะเรียกใช้สคริปต์ที่มีขอบเขตที่จำเป็นอย่างน้อย 1 ขอบเขตได้เท่านั้น ซึ่งหมายความว่าคุณจะใช้ API เพื่อเรียกใช้สคริปต์ที่ไม่ต้องมีการให้สิทธิ์ในบริการอย่างน้อย 1 รายการไม่ได้
ไม่มีทริกเกอร์ API สร้างทริกเกอร์ Apps Script ไม่ได้