公立高校の教員(理科・物理)です。初のQiita投稿です!
作ったもの
スプレッドシートで、アプリケーションを作成しました。Excelのように、ボタンをクリックするとコードが実行されます。
こちらのリンクからコピーを保存できます。この記事を読んで興味を持ってくださった方は、ご自身のドライブから実行してみてください。
なにができるのか
- Google Classroomのストリームには、生徒を指定した限定公開の機能があります。このソフトでは、限定公開の機能を使って、スプレッドシートに事前に記録した内容を、生徒一人ひとりに限定公開で配信をします。
- 今までExcel等で作成し、印刷していた生徒個票を、Classroom上で配信することで代替できます。
- 使用例:出欠日数のおしらせ、提出物提出回数の確認、各種アカウントの配布
- 操作ミスを防ぐために、スプレッドシートのメッセージボックスやインプットボックスを使って、多くの学校現場で使われているであろう、ExcelVBAで作られたソフトウェアと見た目を似せてみました。
- 機能面や運用面のことはさておき、Qiitaでは、GASの技術面についてコメントを残します。
作成した関数の紹介
- その前に...公式リファレンス等では、classroomを識別する値をcourseIdとしていますが、私が作成したプログラムでは、変数名をclassIdとしてしまっています。その2つは、同様のものをさしていると思って読み進めてください。
getClassListSS 関数
- 自分が担当している授業名とコースIDをスプレッドシートに出力します。
- コースIDとは、classroomに生徒を招待するときに使う「クラスコード」とは別物で、GASなどで各クラスを扱うときに使う識別番号です。
function getClassListSS() {
var response = Classroom.Courses.list();
var courses = response.courses;
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('担当クラスリスト');
sheet.clear();
sheet.appendRow(["授業名", "クラスコード"]);
for (i = 0; i < courses.length; i++) {
Logger.log('%s (%s)', courses[i].name, courses[i].id);
sheet.appendRow([courses[i].name, courses[i].id]);
}
sheet.activate();
Browser.msgBox("【担当クラスリスト】のシートに、授業のリストを作りました。クラスコードをコピーしてください。");
}
- sheet.appendRow(配列)が、便利でした。
createStudentListMaxSS 関数
- getClassListSS関数で取得した担当授業一覧のコースIDを使います。
- コースIDで指定したクラスの、参加生徒一覧を取得してスプレッドシートに書き出します。
- コースIDは、文字列型で渡す必要があるので、String(コースId)として、型変換をしています。(これに気づかずに、少し時間を食いました。)
function createStudentListMaxSS() {
var classId = Browser.inputBox("生徒リストを作成します。classroomのIDを入力してください。\n わからない場合は、キャンセルを押してください。", Browser.Buttons.OK_CANCEL); //ClassroomのIDを入力
if (classId != "cancel") {
classId = String(classId);
className = getClassName(classId);
Logger.log(className);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('生徒リスト');
sheet.clear();
sheet.appendRow(["クラスコード", "アドレス", "生徒名", "連絡事項(はじめは空欄)", "送信状況(送信済みは、空欄)"]);
// 取得したクラスIDから、そのクラスに所属している生徒リストを取得
var students = getStudentListMax(classId);
// 生徒一覧をログとして出力
for (i = 0; i < students.length; i++) {
Logger.log(students[i][0]);//生徒のアドレス出力
Logger.log(students[i][1]);//生徒の名前を出力
sheet.appendRow([classId, students[i][0], students[i][1], "ここに記入", "これから送信する"]);
}
sheet.getRange('A1').activate();
//作成したスプレッドシートのURLをログに表示
Browser.msgBox("生徒リストを作成しました。生徒リストのD列に、配信する文章を記録してください。");
} else {
Browser.msgBox("キャンセルが押されました。");
}
}
- getStudentListMaxは、コースIDを引数に取る、自作関数です。
function getStudentListMax(classId) {
let pageToken = "";
var cnt = 0;
let allStudentList = [];// 空の配列を用意
do {
let studentList = Classroom.Courses.Students.list(classId, { "pageToken": pageToken });
for (i = 0; i < studentList['students'].length; i++) {
let student = studentList['students'][i];
allStudentList.push([student['profile']['emailAddress'], student['profile']['name']['fullName']]);//生徒のアドレスを配列に追加
}
pageToken = studentList.nextPageToken;//しおりを挟む。最後のページでなければまた「do」する
cnt = cnt + 1;
} while (pageToken);//最後のページまで行ったら処理を辞める
return allStudentList;
}
- 引数にコースIDを取り、メールアドレスとフルネームを戻り値とします。allStudentListに格納する値を変えれば、ほかの値もできます。
- JSONを戻り値にすればよかったのかもしれませんが、自分の知識不足でうまく扱えませんでした...。
listToClassroom 関数
- 最後に、投稿する関数です。
- 誤投稿を防ぐために、msgBoxで処理を分けています。
function listToClassroom() {
var ck = Browser.msgBox("Okを押すと、生徒に個別配信されます。", "続けますか", Browser.Buttons.OK_CANCEL);
if (ck == 'ok') {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName('生徒リスト');
const lastRow = sheet.getLastRow();
for (let i = 2; i <= lastRow; i++) {
if (sheet.getRange(i, 5).getValue()) { //空欄の場合は、送信しない。
const values = sheet.getRange(i, 1, 1, 4).getValues();
console.log(values);
postAnounceIndividual(values[0][0], values[0][1], values[0][2], values[0][3]);
sheet.getRange(i, 5).clearContent();
}
}
Browser.msgBox("ストリームに、個別の連絡を送信しました。");
}
if (ck == 'cancel') {
Browser.msgBox("キャンセルを押しました");
}
}
- postAnounceIndividual関数は、[コースID、生徒のアドレス、生徒のフルネーム、投稿する文章]の4つの引数をとって、Classroom APIを使って実際に投稿をする関数です。
function postAnounceIndividual(target, mailAdressStr, nameStr, textStr) {
studentList = [mailAdressStr];
var data = {
"courseId": String(target),
"text": nameStr + "さんへ(個別連絡です。) \n \n " + textStr,
"assigneeMode": "INDIVIDUAL_STUDENTS",
"individualStudentsOptions": {
"studentIds": studentList//スプレッドシートから取得した生徒のIDリストを渡す
},
"state": "PUBLISHED"
};
Classroom.Courses.Announcements.create(data, String(target));
Logger.log(studentList + "_" + textStr + "______anounce!!");
}
- Classroom.Courses.Announcements.create()の引数にJSON形式で投稿するテキストや送信相手のメールアドレスを指定することで、Classroomに投稿ができます。公式リファレンスはこちら。
- "assigneeMode"と、"studentIds"が、個別投稿のキモです。(でも正直よくわかっていませんw)
getClassName 関数
- 最後におまけで、コースIDを引数に、授業名を戻す関数です。この手の処理は、探して見ると意外と見つからないものです。
function getClassName(targetClassId) {
//ClassIdから、授業名を返します。
var myCourses = Classroom.Courses.list().courses;
////取得したいクラスの名前を、IDから取得
for (i = 0; i < myCourses.length; i++) {
if (myCourses[i]['id'] === targetClassId) {//targetClassNameに一致するときのみ以下の処理を実施
var inviteClassName = myCourses[i]['name'];
} else {
continue;
}
}
return inviteClassName;
}
最後に
- トリガーと連携させれば、「formが提出されたらclassroomでお知らせする」などもできると思います。
- 「メールでやればいいじゃん!」と思った方へ、確かに、臨時休業中は、私もメールで連絡や提出チェック等を行っていました。
- しかし、高校生の生徒にとって、メールは身近ではありません。学校で使うから...という理由で、メールアプリをインストールさせて、学校アドレスを登録して...なんていうのは、生徒・教員ともども負担が大きいです。
- 一方、クラスルームは朝の連絡や健康観察等で毎朝アクセスさせているので、比較的高い割合で確認してくれます。
- GIGAスクールなんちゃらで、多くの自治体がGoogle Classroom等を利用していると思います。GASを使うことで、様々な校務の効率化ができると思います。今後も、GASに関する投稿ができればいいなと思います。
2021/06/16追記
- Gmail禁止でも大丈夫!生徒個別メッセージスクリプトでGoogle Classroom上で個別相談!で、上記のコードを紹介していただきました。ちょびっと嬉しいです。