Kahoot!用スプレッドシート生成スクリプト解説 - Pythonで作る問題集作成自動化ツール

## はじめに

この記事は [Kahoot!完全解説2024](https://tech.jugoya.ai/blog/understanding-kahoot-2024) の記事で紹介されているPythonスクリプトについて、実装方法と使い方を詳しく解説したものです。

教育現場やビジネス研修で人気の高まっているKahoot!。クイズ形式で学習を進められる便利なツールですが、大量の問題を一度に登録しようとすると意外と手間がかかります。

この記事では、JSONファイルから一括でKahoot!用のスプレッドシートを生成するPythonスクリプトを紹介します。

## 環境準備

### 必要なライブラリ
```bash
pip install openpyxl
```

### Kahoot!の準備
1. 公式の[スプレッドシートテンプレート](https://kahoot.com/library/quiz-spreadsheet-template/)をダウンロード
2. テンプレートの構造を確認（MS Excel, LibreOffice等で開けます）
3. 本スクリプトが生成するファイルと比較して、フォーマットが一致していることを確認

### 注意点
- Kahoot!は問題データのインポート時に厳密なバリデーションを行います
- エラーがある場合は詳細なメッセージが表示されます
- 問題のある設問はスキップして続行することも可能です

## スクリプトの全体像

まず、完成形のスクリプトを見てみましょう。

```python
import openpyxl
import json
from openpyxl.styles import PatternFill, Font

def create_kahoot_spreadsheet(input_json_file, output_excel_file):
    # JSONファイルから問題データを読み込む
    with open(input_json_file, 'r', encoding='utf-8') as f:
        questions = json.load(f)

    # 新しいワークブックを作成
    wb = openpyxl.Workbook()
    sheet = wb.active
    sheet.title = "Quiz"

    # ヘッダー行の設定
    headers = [
        ("B8", "Question", "max 95 characters"),
        ("C8", "Answer 1", "max 60 characters"),
        ("D8", "Answer 2", "max 60 characters"),
        ("E8", "Answer 3", "max 60 characters"),
        ("F8", "Answer 4", "max 60 characters"),
        ("G8", "Time limit (sec)", "5, 10, 20, 30, 60, 90, 120, or 240 secs"),
        ("H8", "Correct answer(s)", "choose at least one (1-4)")
    ]

    # ヘッダーのスタイル設定
    header_fill = PatternFill(start_color="E7E6E6", end_color="E7E6E6", fill_type="solid")
    header_font = Font(bold=True)

    for cell, title, note in headers:
        sheet[cell] = f"{title} - {note}"
        sheet[cell].fill = header_fill
        sheet[cell].font = header_font

    # 問題データの書き込み
    start_row = 9
    for i, question in enumerate(questions):
        row = start_row + i
        
        # 質問文（最大95文字）
        text = question["text"][:95]
        sheet[f"B{row}"] = text
        
        # 選択肢（各最大60文字）
        for j, option in enumerate(question["options"]):
            if j < 4:
                col = chr(ord('C') + j)
                option_text = option[:60]
                sheet[f"{col}{row}"] = option_text
        
        # 制限時間
        time = question.get("time", 20)  # デフォルト20秒
        if time not in [5, 10, 20, 30, 60, 90, 120, 240]:
            time = 20
        sheet[f"G{row}"] = time
        
        # 正解の選択肢
        correct = question["correct_option"]
        if 1 <= correct <= 4:
            sheet[f"H{row}"] = correct

    # ファイルを保存
    wb.save(output_excel_file)
```

## 使い方

1. 問題データをJSONファイルで用意します：

```json
[
    {
        "text": "Pythonの開発者は誰？",
        "options": ["グイド・ヴァン・ロッサム", "ラリー・ウォール", "ビャーネ・ストラウストラップ", "ジェームズ・ゴスリン"],
        "correct_option": 1,
        "time": 20
    },
    {
        "text": "Pythonのパッケージマネージャーといえば？",
        "options": ["pip", "npm", "gem", "composer"],
        "correct_option": 1,
        "time": 30
    }
]
```

2. スクリプトを実行します：

```python
if __name__ == "__main__":
    input_json = "questions.json"
    output_excel = "kahoot_questions.xlsx"
    create_kahoot_spreadsheet(input_json, output_excel)
```

## スクリプトの解説

### 1. ファイルの読み込みと初期設定

```python
# JSONファイルから問題データを読み込む
with open(input_json_file, 'r', encoding='utf-8') as f:
    questions = json.load(f)

# 新しいワークブックを作成
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = "Quiz"
```

この部分では、問題データの読み込みとExcelワークブックの初期設定を行っています。UTF-8でJSONファイルを読み込み、新しいワークブックを作成します。

### 2. ヘッダー行の設定

```python
headers = [
    ("B8", "Question", "max 95 characters"),
    # ... 省略 ...
]

for cell, title, note in headers:
    sheet[cell] = f"{title} - {note}"
    sheet[cell].fill = header_fill
    sheet[cell].font = header_font
```

Kahoot!のテンプレートに合わせて、8行目にヘッダーを配置します。各列の制限事項も明記しています。

### 3. 問題データの書き込み

```python
start_row = 9
for i, question in enumerate(questions):
    row = start_row + i
    
    # 質問文（最大95文字）
    text = question["text"][:95]
    sheet[f"B{row}"] = text
```

9行目から順に問題データを書き込んでいきます。Kahoot!の仕様に合わせて、質問文は95文字までに制限しています。

## よくある質問

Q: なぜヘッダーが8行目から始まるの？
A: Kahoot!の公式テンプレートに合わせています。1-7行目は使用されません。

Q: 制限時間の選択肢が限られているのはなぜ？
A: Kahoot!のシステム仕様です。5, 10, 20, 30, 60, 90, 120, 240秒の中から選択する必要があります。

## トラブルシューティング

### ファイル関連の問題

1. 文字化けが発生する場合
   - JSONファイルがUTF-8で保存されているか確認してください
   - エディタの文字コード設定を確認してください

2. 選択肢が表示されない
   - JSONの形式が正しいか確認してください
   - "options"配列に4つの要素があるか確認してください

### Kahoot!へのインポート時の問題

1. インポートが失敗する
   - 公式テンプレートと比較して、セルの位置が正しいか確認してください
   - 特に、ヘッダー行（8行目）の位置が重要です

2. 一部の問題がスキップされる
   - 制限時間が指定の値（5, 10, 20, 30, 60, 90, 120, 240秒）になっているか確認
   - 質問文が95文字以内、選択肢が60文字以内になっているか確認
   - 正解の選択肢が1-4の範囲内か確認

3. インポート後に文字化けする
   - スプレッドシートを編集する際は、互換性のあるアプリケーション（MS Excel, LibreOffice等）を使用
   - CSVエディタなど、一部のツールでは文字コードが正しく処理されない場合があります

## まとめ

このスクリプトを使うことで、大量の問題データをKahoot!用のスプレッドシートに一括変換できます。特に以下のような場面で効果を発揮します：

- 既存の問題データをKahoot!に移行したい
- 定期的にクイズを更新する必要がある
- 複数のクイズセットを管理している

## 参考文献・リソース

- [Kahoot!完全解説2024 - 93の研究が実証する教育効果と実践テクニック](https://tech.jugoya.ai/blog/understanding-kahoot-2024) - 本記事で解説しているスクリプトの元となる記事
- [Kahoot!公式ドキュメント](https://kahoot.com/docs/) - Kahoot!の一般的な使い方や機能の解説
- [openpyxlドキュメント](https://openpyxl.readthedocs.io/) - Pythonでのスプレッドシート操作の詳細
- [Quiz spreadsheet template](https://kahoot.com/library/quiz-spreadsheet-template/) - Kahoot!公式のスプレッドシートテンプレート