学校によって異なりますが、多くの学生のニーズがあれば夜間自律学習を行う可能性が高いです。
それで、私たちの学校ではまだ夜間自律学習が残っています。
夜自の名前は「読書三道」です。
これまで夜間自律学習の出席チェックは手書きで行ってきました。

自習室に入る前に席の図が描かれた出席簿に自分の学籍番号、名前を書き込むと、自律学習担当教員がその出席簿を持って自習室を回り、学生の名前を確認しなければなりませんでした。
それで夜自前には出席簿の前で子供たちが並んで自分の名前を記入することが多かったです。
学期末には夜間自律学習に参加した学生の統計も必要でした。
これらすべてが手書きなのです。
そこで一度電算化してみることにし、1学期間うまく運営しました。
あらかじめ作成されたアンケートとスプレッドシートをリンクしておきます。
1. アイデア

夜自の出席チェックにおいて最も重要なコアを挙げてみました。
- 簡単で手軽に出席チェックが可能であるべきです。
- 提出後に修正可能であるべきです。
- 担当教員の確認が必要です。
上記の三つを満たす方法として、GoogleフォームのクエリストリングをQRコードにして配布することだと考えました。
各席ごとにクエリストリングを含むアンケートのQRコードを作成して貼っておけば、学生たちはそのQRを撮ってアンケートを提出する方式です。
このように収集されたデータをスプレッドシートのApps Scriptを利用して特定の時間に日付と共に1行ずつ追加します。
こうすると、夜自担当教員もモバイルで出席簿に内容を追加したり修正したりできます。
また、学期末には学生の参加度を集計できます。
さあ、このプロセスで設定を進めてみましょう。
2. 夜自用のアンケートとスプレッドシートを作成する
Googleフォームで内容は席番号、学籍番号、名前のみです。
入力する内容はできるだけ簡潔にする必要があります。

そして右上に「事前に記入されたリンクを取得」というのがあります。
そのリンクに入ります。

私たちの学校では夜自は席が指定されていないため、学籍番号と名前は空白にしておき、席番号だけを事前に記入する予定です。
リンクをコピーして下記のようなアドレスを得ることができます。

ここでviewform?の後ろがクエリです。
クエリストリングは?の後にキーと値のペアを渡します。
私は席番号を23番、学籍番号を20366、名前をカンガルーでアドレスを生成しました。
https://docs.google.com/forms/d/e/1FAIpQLScXgTn9UK5HETv3fCipGiRMl-et9IezB1OSZp2r9-Nj8b54Fg/viewform?usp=pp_url
&entry.1738725719=23 // 席番号
&entry.7330080=20366 // 学籍番号
&entry.1354978010=%EC%BA%A5%EA%B1%B0%EB%A3%A8 // 名前
したがって、生成すべきアドレスは次のようになります。
このアドレスにアクセスすると

さて、このアンケートのスプレッドシートを生成してシートを作成しましょう。

3. スプレッドシートを設定する

まず、シートに入るとアンケート応答シートがあります。
ここにはアンケートの応答が時間順に積み重なります。

中間出席簿ではアンケートの応答を整理する役割を果たします。
ここが最も重要です。
まずquery関数を使用してタイムスタンプが当日であるデータを取得します。
=QUERY('アンケート応答シート1'!$A:$D,"SELECT B,C,D WHERE A<DATE'"&YEAR('自律学習室'!C1)&"-"&MONTH('自律学習室'!C1)&"-"&DAY('自律学習室'!C1)+1&"' AND A>=DATE'"&YEAR('自律学習室'!C1)&"-"&MONTH('自律学習室'!C1)&"-"&DAY('自律学習室'!C1)&"' ORDER BY A",1)
こうして取得した際にいくつかの問題点を考えることができます。
- 学生が座席を変えながら異なる席に名前が重複する場合
- 1つの席に2人の学生が重複する場合
そこでunique関数とxlookup関数でこれを解決しました。

まず「学籍番号」、「名前」の列では=UNIQUE(F:G)でユニークな値を取得します。
そして「座った席」タブでは=XLOOKUP(J2,F:F,E:E,,,-1)でその学籍番号の最後に提出された値だけを取得します。

そして最終的に席番号に対して座った学生を決定します。
=XLOOKUP($A2,$I:$I,J:J,"",,-1)で提出された席の中で最も最後の値を取得します。
これでデータの整理は終了です。
さて、席番号に対する学籍番号と名前で複数のシートを作成すれば良いです。

自律学習室シートは教員に見せるためのシートです。
スプレッドシート関数のtoday()を使用して今日の日付を表示します。
その場に対応する座席テーブルを1つ作成し、その値を中心に席に合わせた学生の学籍番号、名前を中間出席簿から呼び出します。
条件付きスタイルを利用して座った席は緑色に変更します。

最後に出欠統計とチェックのためのシートです。
夜間自律学習に参加する学生の統計のためのものです。
夜自に2/3以上参加する場合、生活記録簿に記入することができます。
ここでApps Script設定が必要です。
4. Apps Script設定

上のメニューから拡張プログラムに入り、Apps Scriptというタブがあります。
ここに入るとシートに対する命令をJavaScriptで与えることができます。

Excelでプログラムを作成するためにはVisual Basicを学ぶ必要があるのに対して、スプレッドシートではJavaScriptだけで望む機能を実装することができるのでとても便利です。
コードを入力するところに次のコードを入力します。
関数名はaddRowDailyにしましたが、なんでも構いません。
詳しい説明はコメントで代わりにします。
function addRowDaily() {
// シートを呼び出すオブジェクトを生成
let checkSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("出席統計");
let data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("中間出席簿");
// 列のインデックスとして使用する日付情報
let date = new Date()
let month = date.getMonth() + 1;
let day = date.getDate();
let time = date.getHours();
// 中間に挿入する列と最後の行を取得
let lastColumn = 3
let rowRange = checkSheet.getLastRow()
// 中間に列を挿入。列の名前は月、日、時間であり、すべてチェックボックス形式
checkSheet.insertColumnAfter(lastColumn-1);
checkSheet.getRange(1, lastColumn).setValue(`${month}月 ${day}日 ${time}時`);
checkSheet.getRange(2, lastColumn, rowRange-1, 1).insertCheckboxes();
// 学生の名前がある行情報をmapで保存。学籍番号がkey、行番号がvalue。
let studentMap = new Map();
checkSheet.getRange("A1:B6").getValues().forEach((row, idx) => {
studentMap.set(row[0], idx+1)
});
// 出席がある行を回って値がある行の学籍番号を取得。mapで学籍番号をキーとして該当する行に[true]を入力する。
let checkedStudents = data.getRange("A2:C64").getValues();
checkedStudents.forEach((rows) => {
let seatNumbers = rows[0];
let studentIdNumber = rows[1];
let studentName = rows[2];
if (studentIdNumber ===""){
return
};
checkSheet.getRange(studentMap.get(studentIdNumber), lastColumn).setValue([true]);
})
}
// セルの編集を監視する。出席統計セルのA11セルが変更された場合、関数を実行する
function onEdit(e){
let rg = e.range;
if (rg.getA1Notation() === "A11" && rg.isChecked() && rg.getSheet().getName() === "出席統計"){
addRowDaily();
rg.uncheck();
};
}

最後には関数実行用のトリガーを指定しました。
なぜチェックボックスをボタンとして使うのか知りたい場合は、stackoverflowを参考にしてください。
さて、テストを押すと以下のような奇妙なウィンドウが表示されます。
権限の確認をクリックしてください。

未確認のアプリという警告が出ますが、私が書いたコードなので特殊な検査は必要ありません。
詳細設定に入り、最下部のリンクをクリックします。

それから元のシートに戻ると、1つの行が追加されたことが確認できます。

A11セルにトリガーを指定したため、このセルに関数実行用のチェックボックスを一つ作成します。
そしてチェックボックスを一度クリックしてみてください。

チェックボックスをクリックすると、関数が実行された後に再びチェックが解除されることがわかります。
大まかな枠はできたので、QRコードを作成しましょう。
5. QRコードを作成する
QRコードはPythonのqrcodeを利用します。
ライブラリがない場合はpipを使ってqrcodeをインストールします。
pip install qrcode
qrcodeの使用方法は非常に直感的で単純です。
makeとsaveでQRコードが簡単にできます。
import qrcode
checkqr = qrcode.make('https://naver.com')
checkqr.save('./qr.png')
このライブラリを知ってからはPythonでのみQRコードを作成しています。
さて、私たちは席番号に対するQRコードを作成するので、forループを回しながらQRコードを作成すれば良いです。
上記で入力したアドレスを活用しましょう。
import qrcode
for i in range(1,44):
url = f"https://docs.google.com/forms/d/e/1FAIpQLScXgTn9UK5HETv3fCipGiRMl-et9IezB1OSZp2r9-Nj8b54Fg/viewform?usp=pp_url&entry.1738725719={i}"
qr = qrcode.make(url)
qr.save(f"./qr/{i}番.png")
これで私が望む席番号までのQRコードが作成されます。
しかし、これを利用するためにはフォーマットを整える必要があります。
QRコードをどう活用するのか、出席チェックをどう行うのかなどの説明が一緒に必要です。
これもpywin32を使って解決しました。

以前と同じように、席番号と画像が挿入される位置にあらかじめ入力フィールドを作成しておきます。
そして次のコードを実行します。
import win32com.client as win32
import os
import time
hwpdir = os.getcwd()
hwpfiles = hwpdir + "/2.hwpx"
maxnum = 43 # 必要な席番号まで
hwp = win32.gencache.EnsureDispatch('HWPFrame.HwpObject')
hwp.RegisterModule("FilePathCheckDLL", "FilePathCheckerModule")
hwp.Open(hwpfiles)
field_list = [i for i in hwp.GetFieldList().split('\x02')]
time.sleep(0.5)
hwp.MovePos(3)
hwp.Run('SelectAll')
hwp.Run('Copy')
hwp.MovePos(3)
for i in range(0,maxnum):
hwp.MovePos(3)
hwp.Run('Paste')
hwp.MovePos(3)
for page in range(0,maxnum):
hwp.PutFieldText(f'席番号{{{{{page}}}}}', page+1)
hwp.MoveToField(f'QRコード{{{{{page}}}}}')
hwp.InsertPicture(f'{hwpdir}/2qr/{page+1}番.png', True, 1, False, False, 0, 60, 60)
al
hwp.SaveAs(hwpfiles+".hwpx")
hwp.Quit()
これで私が希望する番号までの座席に貼るハングル文書が一度に完成します。
単にA4用紙に印刷するとサイズが大きすぎるので、ページ分割を利用して印刷します。

6. 使用後記

この方法を4月に考案し、7月まで使いました。
アンケート結果が739人もあり、クラブの学生たちと一緒に夜自参加学生の推移と好みの座席統計を出してみたりしました。
2学期に使用しなかった理由は、1〜3年生の夜間自律学習が統合され、名簿に変更があったためです。
また、私が業務担当者ではないため、他の学年が統合運営する業務に介入するのも簡単ではありませんでした。

来年にはフォーマットをもう少し美しく作成し、業務担当者に推薦しようと考えています。
今年もよく使ったので、来年も使用する可能性が高いと思います。
学校の多くの部分が自動化されることを期待しています。
댓글을 불러오는 중...