Flutterバスケアプリ | CSVインポート機能を実装〜チーム&メンバー管理〜

はじめに

CSVファイルを使ってチームやメンバーを一括登録できる機能を実装しました。この記事では、チームとメンバーのCSVインポート機能の実装方法を解説します。

CSVインポート機能の概要

まずは、CSVファイルを使ってデータをインポートする機能の概要です。以下のような要件を満たす必要があります。

  • CSVファイルを選択し、その内容を読み込む
  • 各行を適切なデータ形式に変換し、重複チェックを行った後、データベースに登録
  • チームメンバーのデータにおいて、重複する項目(チーム名や番号)がある場合はエラーメッセージを表示
  • 正常に登録できた場合は、アプリの画面に反映

チーム登録のCSVインポート機能

まずは、チームの登録画面にCSVインポート機能を実装しました。チーム名や所在地などをまとめてインポートできるようになっています。

チームCSVのサンプル

チーム名,所在地,表示順
Team A,Tokyo,1
Team B,Osaka,2
Team C,Nagoya,3

チーム登録画面のコード

以下のコードは、チームを登録する画面にCSVインポート機能を追加したものです。

Future<void> _importCSV() async {
  try {
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['csv'],
    );

    if (result != null) {
      File file = File(result.files.single.path!);
      String fileContent = await file.readAsString();
      print("File Content: $fileContent");

      List<String> rows = fileContent.split('\n');
      print("Rows after splitting by newline: $rows");

      if (rows.isNotEmpty) {
        rows.removeAt(0); // ヘッダーを削除
        print("Rows after header removal: $rows");

        for (var row in rows) {
          List<String> values = row.split(','); // 各行をカンマで分割
          print("Processing row: $values");

          if (values.length >= 3) {
            String name = values[0].trim();
            String location = values[1].trim();
            int order = int.tryParse(values[2].trim()) ?? _teams.length + 1;

            Team newTeam = Team(
              name: name,
              location: location,
              registrationDate: DateTime.now().toString(),
              lastEditedDate: DateTime.now().toString(),
              displayOrder: order,
            );

            await _teamProvider.insertTeam(newTeam);
            print("Successfully inserted team: $name");
          } else {
            print("Invalid row: $row");
          }
        }

        await _loadTeams();
        print("Teams loaded after CSV import: ${_teams.map((t) => t.name).toList()}");
      } else {
        print("No rows found in CSV.");
      }
    }
  } catch (e) {
    print("Error importing CSV: $e");
  }
}

チーム登録画面のスクリーンショット


メンバー登録のCSVインポート機能

次に、メンバー登録の画面にCSVインポート機能を実装しました。メンバーには、名前、番号、ポジション、身長、体重、表示順といった情報を含めます。

メンバーCSVのサンプル

名前,番号,ポジション,身長,体重,表示順
Player A,10,PG,180,75,1
Player B,11,SG,185,80,2
Player C,12,SF,190,85,3

メンバー登録画面のコード

以下のコードは、メンバー登録画面にCSVインポート機能を追加したものです。チーム内で同じ番号が重複している場合にはエラーを表示するようになっています。

Future<void> _importCSV() async {
  try {
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['csv'],
    );

    if (result != null) {
      File file = File(result.files.single.path!);
      String fileContent = await file.readAsString();
      print("File Content: $fileContent");

      List<String> rows = fileContent.split('\n');
      print("Rows after splitting by newline: $rows");

      if (rows.isNotEmpty) {
        rows.removeAt(0); // ヘッダーを削除
        print("Rows after header removal: $rows");

        for (var row in rows) {
          List<String> values = row.split(','); // 各行をカンマで分割
          print("Processing row: $values");

          if (values.length >= 6) {
            String name = values[0].trim();
            int number = int.tryParse(values[1].trim()) ?? 0;
            String position = values[2].trim();
            double height = double.tryParse(values[3].trim()) ?? 0.0;
            double weight = double.tryParse(values[4].trim()) ?? 0.0;
            int displayOrder = int.tryParse(values[5].trim()) ?? _members.length + 1;

            Member newMember = Member(
              name: name,
              number: number,
              position: position,
              height: height,
              weight: weight,
              teamId: widget.team.id!,
              registrationDate: DateTime.now().toString(),
              lastEditedDate: DateTime.now().toString(),
              displayOrder: displayOrder,
            );

            // 同じ番号が存在するかチェック
            Member? existingMember = await _memberProvider.getMemberByTeamAndNumber(widget.team.id!, number);
            if (existingMember != null) {
              print("重複するメンバーが存在します: $number");
            } else {
              await _memberProvider.insertMember(newMember);
              print("Successfully inserted member: $name");
            }
          } else {
            print("Invalid row: $row");
          }
        }

        await _loadMembers();
        print("Members loaded after CSV import: ${_members.map((m) => m.name).toList()}");
      } else {
        print("No rows found in CSV.");
      }
    }
  } catch (e) {
    print("Error importing CSV: $e");
  }
}

メンバー登録画面のスクリーンショット

まとめ

このようにして、チームとメンバーをCSVファイルから一括でインポートできる機能を実装しました。手作業で1つ1つ登録するのではなく、まとめてデータを投入できるので、効率がアップしました。

関連記事

コメント

タイトルとURLをコピーしました