大学の副手でプログラミングの採点をしているが,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(); }
<!DOCTYPE html> <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を用意するだけで通知ができる.
スプレッドシートリンクを共有する際,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