
中学生の子どもが図書委員をやっているのだけど、
貸出や返却が手間かかって仕方ないらしいんだよね。

どうしてッスか?

なんだかね、都度エクセルにポチポチ入力しているみたいなんだよ。
貸出や返却を。

うわ。めんどくさいッスね。

そういうシステムって、結構お金がかかるんだよね。
小さい町の小さい学校だと、その予算も大変なんだろうね。
無料のものだと、少人数しか使えなかったりするし。
そこで思ったんだけどさ。
今はAIに聞けば、プログラミングもしてくれるでしょ。
だから、貸出システムを自作できれば便利になるのかな、と思ったんだよね。
Geminiに聞いてみた。

一番使い慣れているAIのGeminiに聞いてみることにするよ。
本を貸したり返したりするシステムをプログラミングしたいのですが、どうすればいいでしょう?

書籍の貸し借りを管理するシステムをプログラミングするのですね。
これは、ユーザー、書籍、貸出記録という3つの主要な要素を中心に考えると、比較的シンプルに構築できます。
Pythonを使って、基本的なシステムの骨組みを説明しますね。
(以下、説明がダラダラ……)

Python?ピョッホン?
それ、なんスか?

「パイソン」と読むんだよ。
プログラミング言語の1つだよ。プログラミング言語の中では、簡単な方と言われているよ。
でも、本やユーザーをリストで管理したいなぁ。
Googleだったらスプレッドシートがあるよね。
Googleのプログラミング言語の「GAS(ガス)」で作った方が便利そう。
GASでお願いします。

Google Apps Script (GAS) で書籍の貸し借りシステムをプログラミングするのですね。
GASはGoogleスプレッドシートやGoogleフォームと連携して、Webアプリケーションを簡単に作れるため、このシステムに非常に適しています。

じゃあ最初っからGASで作ればよかったッス。
何でPythonにしたッスか?
Python使えるマウントッスか?

まぁまぁ。
Pythonのほうが打ち込む行数少ないから、気を遣ってくれたのかもしれないし。
GASで作ってみた。


プログラミングのコードは、ほぼ全部Geminiが書いてくれるね。
スプレッドシートの入力も、Geminiが全部教えてくれたよ。
わからなかったりエラーが出たら、その都度Geminiに聞けばいいね。

画面のデザイン的には、なんというか、どシンプルッスね。

そのへんは、いずれ良くしていこうね。
ユーザーIDやISBN(本についているバーコード)は、バーコードスキャナーがあれば楽に入力できるね。
古くてISBNが無い本も、適当に番号を付けて、ネットのフリーサイトでバーコード作ればいいし。
使ってみた。

貸出や返却のところにIDとISBNを入力すると、スプレッドシートに反映されるよ。

すごいッス。
プログラミング素人でもできるんッスね。

ただ、動作が遅いのが少し気になるかな。
本のリストは2冊、ユーザーは4人分しか登録していないけど、1冊の処理に1~2秒かかったね。
そこはプログラミング素人の限界だね。Geminiに聞けば早くできるのかな。

「返す日がいつ」とか、予約とかはどうなってるんスか?

返す日は2週間後の日付が自動で画面に表示されるようにしたよ。
予約は、今後の課題だね。
今後の課題。

予約以外にも、何かあるッスか?

検索ができるといいね。
データはスプレッドシートに入っているから、「Ctrl+F」の検索でいけるよね。
ただ、今はまだタイトルと著者名とISBNくらいしか無いから、項目を増やしたいね。
図書館で言う「請求記号」(分類や本の場所を示す)を付けるといいかも。
あと、著者とタイトルの読みも別の項目で足すと、検索しやすくなるね。
GASのコードです。

Geminiに書いてもらったコードを載せておきます。
でも、ここをコピペするより、AIに聞いたほうがいいと思います。
// スプレッドシートのIDを設定
const SPREADSHEET_ID = ‘ここにあなたのスプレッドシートIDを貼り付けてください’;
// シート名を定数として定義
const SHEET_NAMES = {
BOOKS: ‘書籍リスト’,
USERS: ‘ユーザーリスト’,
BORROWS: ‘貸出記録’
};
/**
- WebアプリケーションのGETリクエストを処理し、HTMLファイルを表示します。
*/
function doGet() {
return HtmlService.createHtmlOutputFromFile(‘index’);
}
/**
- WebアプリケーションのPOSTリクエストを処理し、HTMLファイルを表示します。
*/
function doPost() {
return HtmlService.createHtmlOutputFromFile(‘index’);
}
/**
- 書籍を貸し出す関数
- @param {string} userId – ユーザーID
- @param {string} isbn – 書籍のISBN
- @return {string} – 処理結果メッセージ
*/
function borrowBook(userId, isbn) {
try {
// 入力値の前後のスペースを削除
userId = userId.trim();
isbn = isbn.trim(); const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
const bookSheet = ss.getSheetByName(SHEET_NAMES.BOOKS);
const userSheet = ss.getSheetByName(SHEET_NAMES.USERS);
const borrowSheet = ss.getSheetByName(SHEET_NAMES.BORROWS); if (!bookSheet || !userSheet || !borrowSheet) {
throw new Error(‘スプレッドシートのシート名が正しくありません。’);
} // ユーザーIDの存在チェック
const userExists = userSheet.getRange(2, 1, userSheet.getLastRow() – 1, 1)
.getValues().flat().some(id => String(id).trim() === userId);
if (!userExists) {
return ‘エラー: ユーザーIDが存在しません。’;
} // 書籍の存在と貸出状況の確認
const bookData = bookSheet.getDataRange().getValues();
let bookRowIndex = -1;
let bookStatus = ”; for (let i = 1; i < bookData.length; i++) {
const sheetIsbn = String(bookData[i][0]).trim();
if (sheetIsbn === isbn) {
bookRowIndex = i + 1; // 1ベースの行番号
bookStatus = String(bookData[i][3]).trim();
break;
}
} if (bookRowIndex === -1) {
return ‘エラー: 書籍が見つかりません。’;
}
if (bookStatus === ‘貸出中’) {
return ‘エラー: この書籍は現在貸出中です。’;
} // 返却予定日を計算(貸出日から14日後)
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + 14); // 貸出処理
bookSheet.getRange(bookRowIndex, 4).setValue(‘貸出中’);
// 貸出記録に、返却予定日を新しいE列(インデックス4)に追加
borrowSheet.appendRow([userId, isbn, new Date(), null, dueDate]); // 処理結果メッセージに返却予定日を追加
const dueDateFormat = Utilities.formatDate(dueDate, Session.getScriptTimeZone(), ‘yyyy年MM月dd日’);
return貸出が完了しました。返却予定日は ${dueDateFormat} です。
; } catch (e) {
return予期せぬエラーが発生しました: ${e.message}
;
}
}
/**
- 書籍を返却する関数
- @param {string} userId – ユーザーID
- @param {string} isbn – 書籍のISBN
- @return {string} – 処理結果メッセージ
*/
function returnBook(userId, isbn) {
try {
// 入力値の前後のスペースを削除
userId = userId.trim();
isbn = isbn.trim(); const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
const bookSheet = ss.getSheetByName(SHEET_NAMES.BOOKS);
const borrowSheet = ss.getSheetByName(SHEET_NAMES.BORROWS); if (!bookSheet || !borrowSheet) {
throw new Error(‘スプレッドシートのシート名が正しくありません。’);
} // 貸出記録を検索して返却処理
const borrowData = borrowSheet.getDataRange().getValues();
let borrowRowIndex = -1; for (let i = 1; i < borrowData.length; i++) {
const sheetUserId = String(borrowData[i][0]).trim();
const sheetIsbn = String(borrowData[i][1]).trim(); // 返却日が空欄(インデックス3)の貸出記録を探す
if (sheetUserId === userId && sheetIsbn === isbn && !borrowData[i][3]) {
borrowRowIndex = i + 1;
break;
}
} if (borrowRowIndex === -1) {
return ‘エラー: この書籍の貸出記録が見つかりません。’;
} // 返却処理
// 貸出記録のD列(インデックス3)に返却日を記入
borrowSheet.getRange(borrowRowIndex, 4).setValue(new Date()); // 書籍の貸出状況を「貸出可」に戻す
const bookData = bookSheet.getDataRange().getValues();
let bookRowIndex = -1;
for (let i = 1; i < bookData.length; i++) {
const sheetIsbn = String(bookData[i][0]).trim();
if (sheetIsbn === isbn) {
bookRowIndex = i + 1;
break;
}
}
if (bookRowIndex !== -1) {
bookSheet.getRange(bookRowIndex, 4).setValue(‘貸出可’);
} return ‘返却が完了しました。’; } catch (e) {
return予期せぬエラーが発生しました: ${e.message}
;
}
}
以下、広告です。