GASは「Googleアカウント」と「インターネット接続環境」があれば利用できます
*「JavaScript」の基本的な知識が必要です
まずは、サーバーとして利用させていただきます😊
基本的なこと
- GASは開発環境(サーバーやエディタ)の準備が不要です
- GASから(Googleのサーバー側から)「Web上のリソース(データ)をURLフェッチ(取得)」したり、「JSONなどの形式でテキストを提供」したり、「HTMLファイルを返却」したりできます
- 様々なサービス(Gmail・スプレッドシート・Googleマップ・Googleドライブ・Googleカレンダー・Googleドキュメント・Googleフォーム・Google翻訳など)と連携できます
- 様々なトリガー(自動で実行するための機能)を設定できます
- 「GASで参照・編集したいファイル」はGoogleドライブ上に保存する必要があります(直接ローカルドライブ上に置いたファイルを参照できません)
- スクリプトの実行時間は1回当たり最大6分(カスタム関数の1処理あたり最大30秒)と上限があります
- トリガーには「Simple Triggers」と「Installable Triggers」があります
- 「Simple Triggers」はスクリプトエディタに設定(自分で実行内容を設定)
- 「Installable Triggers」はGASのスクリプトの左上時計マークから設定(サービス毎に既にあるトリガーを選択)
一部のGASの機能には1日の割り当てと制限があります
制限を超えると、例外を投げて実行が停止します
GASの利用方法
スタンドアロン(単独のGAS)とコンテナバインド(サービスに紐付くGAS)
スタンドアロンは、GoogleドライブからGASを新規ファイルとして開きます
この場合、例えばスプレッドシートを開く際は、IDや名前を指定する必要がありスプレッドシート側からGASの実行はできません
*IDについて:Googleドライブ上のファイルにはユニークなIDが付与されます
URLのd/のあとの部分「https://…………../d/{ID}/」
コンテナバインドは、紐付けるサービスの「メニューから」GASのスクリプトエディタを開きます(主にスプレッドシートから開くことが多いです)
スタンドアロンで使用できないコマンドが使えます
*Googleドライブ上では紐ずくサービスが表示されます(GASファイルとして表示されません)
アクセス権限の承認
権限を確認→アカウントを選択して→詳細→プロジェクトに移動→許可をクリック
UrlFetchAppクラスとHTTPResponseクラス
リクエストを送り、レスポンスを受け取ります
備考:制限
URLフェッチの呼び出し 20,000 /1日
レスポンスサイズ 50MB /1回
大前提:リクエストとレスポンスは文字列です(JSONも文字列です)
JSON.stringify(Obj)
「JavaScriptのオブジェクト」を「JSON文字列」に変換しますJSON.parse(ObjStr)
「JSON文字列」を「JavaScriptオブジェクト」に変換します
UrlFetchApp.fetch(url, paramsObj)
URLを取得する
UrlFetchAppクラスの「fetchメソッド」でリクエストを送り
レスポンスに対してHTTPResponseクラスの「getContentText()
」で文字列としてエンコードされたHTTPのコンテンツを取得します
*レスポンスからバイナリコンテンツ(画像など)を取得する時は「getContent()
」を使用します
function myFunction() {
const url = "http://www.google.com/"
const res = UrlFetchApp.fetch(url);
//レスポンスの文字列
console.log(res.getContentText());
}
POSTリクエストを行います(第二引数にオプション(オブジェクト)を設定)
「Content-type」には通常「application/json(jsonフォーマット)」もしくは「application/x-www-form-urlencoded(HTMLのフォームの送信形式と同じ)」をHTTPヘッダーに指定します
function myFunction() {
//POSTリクエストの内容
const data = {
'body': 'hoge',
};
const options = {
'method' : 'post',
'contentType': 'application/json',
//POSTは JSON文字列に変換
'payload' : JSON.stringify(data)
};
const res = UrlFetchApp.fetch('https://httpbin.org/post', options);
//ヘッダーの属性のマップを取得
console.log(res.getContentText());
}
余談
「https://httpbin.org/」はHTTPリクエストしたヘッダー情報の確認が簡単にできるサービスです(自分が送ったパラメータやヘッダー情報を返却してくれます)
GASで設定した何らかのトリガーが実行された時に「LINE Notify」へリクエストを送り、LINEで通知を受け取ります
*「LINE Notify」はWebサービスからの通知をLINEで受信することが出来るサービスです
- 自分だけのLINEグループを作り
- LINE Notifyのサイトでトークンを取得(右上マイページから任意のトークン名を入力、一覧に表示されているトークルームから通知を送ってほしいグループを選択します)
- LINE NotifyをLINEグループに招待
- GAS側で下記の「sendLineMessage(メッセージ内容)」関数を実行(トリガーなどを設定)してLINE Notifyにリクエストを送ります
//送りたいメッセージを引数に渡す
function sendLineMessage(mag){
const LINE_NOTIFY_TOKEN = "LINE Notifyのトークン "
const LINE_NOTIFY_API = "https://notify-api.line.me/api/notify";
const options = {
'method' : 'post',
'headers': { "Authorization": `Bearer ${LINE_NOTIFY_TOKEN}` },
'payload' : {'message': mag }
};
UrlFetchApp.fetch(LINE_NOTIFY_API, options);
}
Webアプリとして公開
「doGet(e)
またはdoPost(e)
」関数が「コンテンツサービスのTextOutputオブジェクト」または 「HTMLサービスのHtmlOutputオブジェクト」を返す場合はWebアプリとして公開できます
コンテンツサービス
「テキスト・XML・ JSON」 などのさまざまな形式でコンテンツを返します
function doGet() {
return ContentService.createTextOutput('Hello, world!');
}
APIもどき(GETリクエストに対してJSONをレスポンスします)
//提供するオブジェクト
const data = {
status : 'success',
};
function doGet(){
// listデータをjsonに変換
var output = JSON.stringify(data);
//コンテンツのMIMEタイプ(JSON)も設定します
return ContentService.createTextOutput(output).setMimeType(ContentService.MimeType.JSON);
}
GETリクエストにパラメーターを含めます
「Webアプリ」としてデブロイして(アプリケーションにアクセス出来るユーザーは「全員」にします)
コピーしたURLに?param=hogeを追加してアクセスします
https://script.google.com/macros/s/{ID}/exec?param=hoge
この場合hogeと表示されます
function doGet(e) {
var param = e.parameter.param;
console.log(param);
return ContentService.createTextOutput(param);
}
Google翻訳サービスを使って、英単語を日本語で返す例
https://script.google.com/macros/s/{ID}}/exec?text={英単語}&source=en&target=ja
function doGet(e) {
// リクエストパラメータを取得する
const p = e.parameter;
// Google翻訳のパラメーターの部分
//exec?text={}&source={}&target={}
const translatedText = LanguageApp.translate(p.text, p.source, p.target);
// レスポンスボディの作成
const body = {}
if (translatedText) {
body.status = 200
body.text = translatedText
} else {
body.status = 400
body.text = "Bad Request"
}
var res = ContentService.createTextOutput();
res.setMimeType(ContentService.MimeType.JSON);
res.setContent(JSON.stringify(body));
return res;
}
//Google翻訳
var text = LanguageApp.translate('This is a pen', 'en', 'ja');
console.log(text); //これはペンです
余談
CORS非対応のサードパーティAPI(ブラウザからのリクエストNG)に対して自分でサーバー環境を作ることなく利用する方法(ブラウザからはGASへリクエストを送ります)
GASからサードパーティAPIへ「UrlFetchAppクラス」を使ってリクエストを送り
GASで受け取った「サードパーティAPIからのレスポンス」を「コンテンツサービス」を使ってJSONをレスポンスします😅
*GASをサーバーサイドプロキシのように機能させていたアプリがエラーに😭
HTMLサービス
「HtmlServiceクラス」は HTMLやテキストコンテンツを返すためのサービスです
GASの関数とやり取りできるWebページを作成できます(HTML5の一部の高度な機能は利用できません)
*コンテナバインドの場合はカスタムメニュー・ダイアログ・サイドバーなどのUI部品としても使用可能です(この場合はdoGet()特に関数は必要なく、デプロイしたりする必要もありません onOpen() 関数やopenDialog()を使用します)
HtmlOutputクラス
HtmlService.createHtmlOutput()
の戻り値は「HtmlOutputクラス」です
HtmlOutputクラスから提供できるオブジェクトはサニタイズされたHTMLを返します
自動的に「IFRAMEサウンドボックスモード」で実行されます
*IFRAMEサウンドボックスモードでの制限事項
function doGet() {
return HtmlService.createHtmlOutput('<b>Hello, world!</b>');
}
スクリプトを「デプロイをテスト(常に最後に保存されたコードを実行)」にするとリロードするだけで変更が反映されます( コードと同期されます)
「新しいデプロイ」では、変更するたびにテプロイする必要があります(バージョン付きデプロイ)
*開発中は最初に「新しいデプロイ」で公開し、「デプロイをテスト」で取得したURLで変更を確認します
*バージョン付きデプロイはアーカイブできますが、削除することはできません
「index.htmlファイル」を返しますcreateHtmlOutputFromFile('index')
左側にある [ファイルを追加] をクリックし HTMLファイル(ファイル名index)を追加します
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
動的にHTMLを書き換える
- テンプレート:テンプレート内のコードは、ページが読み込まれるときに1回実行され、処理が完了するまでコンテンツはクライアントに送信されません
- google.script.run:非同期方式で「GAS関数」を呼び出します(ブラウザ側JavaScriptで書き換えるイメージ)
HtmlTemplateクラス
備考
動的にHTMLを書き換える場合:HtmlService.createTemplateFromFile('index').evaluate()
単純なHTMLの場合: HtmlService.createHtmlOutputFromFile('index')
HtmlTemplateクラス(HTMLを動的に構築するためのテンプレートオブジェクト)では「evaluate()
メソッド」はテンプレートを評価して「HtmlOutputオブジェクト」を返します
*getCode()メソッドは評価可能なJavaScriptコードの文字列を生成します
function doGet() {
//index.htmlをテンプレートに使う
t = HtmlService.createTemplateFromFile('index');
t.title = 'タイトル';
//テンプレートの実際の出力コードを確認できます
console.log( t.getCode() );
return t.evaluate()
}
テンプレートを使用した変数の受け渡し
HtmlOutputオブジェクトを返します
function doGet() {
return HtmlService.createTemplateFromFile('index').evaluate()
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title><?= title ?></title>
</head>
<body>
<h1><?= title ?></h1>
</body>
</html>
CSSやJavaScriptを別ファイルにする場合
function doGet(request) {
return HtmlService.createTemplateFromFile('index')
.evaluate();
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
<!DOCTYPE html>
<html>
<head>
<?!= include('index.css'); ?>
</head>
<body>
<?!= include('index.js'); ?>
</body>
</html>
<style>
</style>
<script>
</script>
google.script.run
「google.script.run
」
「HTMLサービスページ」が「GAS関数」を呼び出せるようにする非同期のクライアント側 「JavaScript API 」です
「withSuccessHandler(function)
」
クライアント側のコードは「GAS関数」の完了を待たずに次に進むため、引数に「GAS関数が応答したときに実行するクライアント側のコールバック関数」を指定できます
「GAS関数」が値を返す場合、その値を引数として新しい関数に渡します
<script>
//doSomething()はGASの関数
google.script.run.withSuccessHandler(onSuccess).doSomething()
//onSuccessはGASの関数が成功した後に実行する関数
function onSuccess() {}
</script>
(ドキュメントの例)
クライアント側から、ファイルを Googleドライブにアップロードして、ファイルのURLを出力します
*「form」では「フィールド名をキー・フィールド値を値」とするオブジェクトになります
{myFile: ‘値’}
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function processForm(formObject) {
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
return driveFile.getUrl();
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// フォーム送信を止めます
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
//GAS側processForm関数にフォームオブジェクトを渡して実行
//完了後にprocessForm関数の戻り値をupdateUrl関数の引数に渡して実行
google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
}
function updateUrl(url) {
var div = document.getElementById('output');
div.innerHTML = '<a href="' + url + '">Got it!</a>';
}
</script>
</head>
<body>
<form id="myForm" onsubmit="handleFormSubmit(this)">
<input name="myFile" type="file" />
<input type="submit" value="Submit" />
</form>
<div id="output"></div>
</body>
</html>
トリガー
「Installable Triggers」
- 左側「トリガー]」をクリックします
- 右下 「トリガーを追加」をクリックします
- 作成するトリガーのタイプを選択してトリガーを作成します
- 「保存」をクリックします
「Simple Triggers」
- onOpen(e) :「スプレッドシート・ドキュメント・プレゼンテーション・フォーム」を開くと実行
- onEdit(e):スプレッドシートの値を変更すると実行
- onSelectionChange(e) :スプレッドシートで選択内容を変更すると実行
- doGet(e) :ウェブアプリに HTTP GET リクエストを送信すると実行
- doPost(e) : ウェブアプリに HTTP POST リクエストを送信すると実行
トリガーが発生すると、GAS関数にイベントオブジェクト(e)を引数として渡します
イベントオブジェクトには、トリガーが発生する原因となったコンテキストに関する情報が含まれます