大学の副手でプログラミングの採点をしているが,GASでその手間を減らすアプリケーションを作ることができた
その際にGASのイディオムを結構覚えたのでメモ.
アプリケーションの主な仕様
- Googleフォームから採点するファイルをアップロードする
- zipファイルの解凍,採点者ごとの担当を決めフォルダの再配置が自動で行われる
- 採点用シートを自動作成
- 採点完了後に踏むことでcsv書き出し,ダウンロードができるリンクを作成
- 採点シート,各採点者ごとのフォルダ,ダウンロードリンクをSlack通知
Googleフォームから採点するファイルをアップロードする
Googleフォームではファイルのアップロード機能がついており,GASのhookと組み合わせることでフォームの送信ごとに自動でファイル処理を行うことができる.
hookでフォームから投稿されたファイルを扱うには下のようにすれば良い.
function submitForm(e) {
const itemResponses = e.response.getItemResponses();
const fileId = itemResponses.filter(
function(itemResponse){
return itemResponse.getItem().getTitle() == "質問名";
})[0].getResponse();
const file = DriveApp.getFileById(fileId).getName();
}
フォームに投稿されたファイルはフォームが置いてあるディレクトリ以下の,
#{フォーム名}(File responses)/#{質問名}(File responses)
に保存されている.
ここで注意しないといけないのは,アップロードされたファイルは元のファイル名に加えアップロードした人の名前が追加されていることである.
fugaというユーザがhoge.zipというファイルをアップした際,
ファイル名はhoge - fuga.zip
となるため注意が必要である.
zipファイルの解凍,採点者ごとの担当を決めフォルダの再配置が自動で行われる / 採点用シートを自動作成
GASにはunzip
やcreateFile
など,Drive上でファイルを扱うメソッドが用意されていて簡単だった.
振り分け後,担当者と学籍番号のペアを返しスプレッドシートに書き込む.
採点完了後に踏むことでcsv書き出し,ダウンロードができるリンクを作成
ここはhookではなくGASから「Webアプリケーションとして公開」を利用した.
固定のURLにファイル名のパラメータを付けてアクセスすることで,対応するシートの情報からcsvをエクスポートするリンクを表示する実装になっている.
ファイルダウンロードはこれを参考にした.
googleappsscript.hatenablog.com
これにurlパラメータと埋め込みを利用することで動的にシートやファイルを変更できるようになった.
function doGet(e) {
var html = HtmlService.createTemplateFromFile("dialog");
html.sheetName = e.parameter.fileName;
html.fileName = e.parameter.fileName + ".csv";
return html.evaluate();
}
<html>
<head>
<base target="_top">
<script type='text/javascript'>
function handleDownload() {
var sheetName = <?= sheetName ?>;
var content = <?= export(sheetName); ?>;
var blob = new Blob([, content ], { "type" : "text/csv"});
document.getElementById("download").href = window.URL.createObjectURL(blob);
}
</script>
</head>
<body>
<a id="download" href="#" download="<?= fileName ?>" onclick="handleDownload()">ダウンロード</a>
</body>
</html>
採点シート,各採点者ごとのフォルダ,ダウンロードリンクをSlack通知
GASにはGETやPOSTを行うメソッドもあるためSlackのwebhookを用意するだけで通知ができる.
qiita.com
スプレッドシートリンクを共有する際,getUrl()
では前回アクティブだったシートが開かれてしまうため,指定したいときは下のようにgidも付けてURLにする必要がある.
function getSheetUrl(sheetName){
const spreadSheet = SpreadsheetApp.openById(globalVariables().spreadSheetId);
const sheet = spreadSheet.getSheetByName(sheetName);
return spreadSheet.getUrl() + '#gid=' + String(sheet.getSheetId());
}
また,GASには環境変数がないため,分離したいものを以下のようにまとめて参照している.
function globalVariables(){
return {
spreadSheetId: '',
rootFolderId: '',
webappUrl: '',
slackUrl: ''
}
}
動作
フォームからzipファイルをアップロードすることでこのようなSlack通知が流れるようになる.
雑感
サーバレスというとLambdaが話題になりがちだけど,スプレッドシートやフォーム,ドライブを簡単に扱えるGASでも色々できそう.
それに加えて引き継ぎが必要な小規模グループだとAWSはアカウントや課金周りで相性悪い気がする.
github.com