3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Bobを使って就活管理アプリをExcel VBAからWebアプリへ移行した話

3
Last updated at Posted at 2026-05-25

本記事の内容は私的に実施したものであり、個人の感想です。如何なる組織・製品を代表するものでもありません。

Summary

  • Excel VBAで作成した就活管理シートの仕様書作成・移行計画・実装をすべてIBM Bobに任せ、約1時間で概ね移行が完了した
  • 移行だけでなく途中からの新機能追加も問題なく対応。壁打ちを重ねながらも無料トライアル(40 Bob coin)の範囲に収まった
  • BobはTodoリスト提示・モード切り替え提案・情報不足している要件定義の追加提案・CI/CD導入提案など、単なるコーディング補助を超えてSDLC全体をカバーする設計になっている

やらないこと

  • Bobと他AIエージェントの詳細な性能比較
  • 各技術スタック(React、Dexie.jsなど)の詳細な解説
  • 完成アプリのデプロイ・公開

本記事における課題

私が学生の頃、就職活動中にExcel VBAで作成した企業研究管理シートを題材に、IBM Bob へWebアプリケーションヘのモダナイゼーションを依頼した。

移行イメージ

移行前

VBAを活用し、企業研究の入力内容を一覧したり、PDF出力・印刷したりできる。

screenshot.png

スクリーンショット 2026-05-25 19.45.46.png

移行後のアプリ

移行前のアプリが持っていた機能に加え、選考フェーズごとの記録追加、データのインポート・エクスポートができるようになっている。

スクリーンショット 2026-05-25 19.48.29.png

スクリーンショット 2026-05-25 19.50.43.png

スクリーンショット 2026-05-25 19.50.59.png

やったこと

Bobへの依頼内容

今回、私自身が行った作業は大きく以下の3ステップのみである。

  1. 既存資産を渡して仕様書を作成させた
    VBAソースコードとスクリーンショットから、まずは現物の仕様書を作成して。 と依頼した。BobはVBAのソースコードとスクリーンショットを読み取り、現物ベースの仕様書を自動生成した。

  2. 仕様書をベースに移行計画を立ててもらった
    生成された仕様書を確認した上で、そのまま移行計画の立案をBobに依頼した。

  3. 移行計画に従って実装させ、途中で新機能を追加させた
    計画書を承認し、実装をBobに委ねた。移行が進む中で選考記録機能を新規に追加させるなど、壁打ちしながら育てていった。

この3ステップで、ソースコードとスクリーンショットを渡してから約1時間で概ね移行が完了した

Bobが生成した現行仕様書(抜粋):

# 企業研究データベース 現行システム仕様書

## 1. システム概要

### 1.1 目的
就職活動における企業研究情報を一元管理し、効率的な企業分析と情報整理を支援するExcel VBAベースの管理システム。

### 1.2 システム構成
- **プラットフォーム**: Microsoft Excel + VBA
- **ファイル構成**: 単一のExcelブック(.xlsm形式)
- **バージョン管理**: 日付ベースの自動バージョニング(ver.YY.MM.DD形式)

### 1.3 対象ユーザー
就職活動中の学生・求職者

---

## 2. ワークシート構成

### 2.1 シート一覧

| シート名 | 用途 | 備考 |
|---------|------|------|
| データベース | 企業一覧の集約表示 | メインインデックス |
| _Template | 企業研究シートのテンプレート | 非表示・コピー元 |
| 企業別シート | 個別企業の詳細情報 | 動的に追加 |

### 2.2 データベースシート

#### レイアウト構成
- **ヘッダー部**: 操作ボタン群とバージョン表示
- **データ部**: 企業情報の一覧表

#### データ項目

| 列 | 項目名 | データ型 | 説明 |
|----|--------|----------|------|
| A | 企業ID | 数値 | 自動採番(1から連番) |
| B | 企業名 | 文字列 | 正式な企業名称(ハイパーリンク付き) |
| C | 本社 | 文字列 | 本社所在地 |
| D | 設立年 | 日付/文字列 | 設立年月日 |
| E | 資本金 | 文字列 | 日本語表記(億・万円単位) |
| F | 売上高 | 文字列 | 日本語表記(億・万円単位) |
| G | 平均年齢 | 数値 | 従業員の平均年齢 |
| H | 平均年収 | 数値 | 従業員の平均年収 |
| I | 初任給 | 数値 | 新卒初任給 |

#### 操作ボタン
- **シート作成**: 新規企業シートの作成
- **データ更新**: 各企業シートから情報を再読み込み
- **バージョン付与**: 現在日付でバージョン更新
- **PDF出力**: 選択企業のPDF出力
- **シート印刷**: 選択企業の印刷プレビュー

### 2.3 企業研究シート(テンプレート)

#### 基本情報セクション
| セル位置 | 項目名 | 説明 |
|---------|--------|------|
| D1 | 企業ID | 自動採番 |
| B3 | 企業名 | 正式名称 |
| B6 | 本社 | 本社所在地 |
| B8 | 設立年 | 設立年月日 |
| B10 | 資本金 | 資本金額 |
| B12 | 売上高 | 年間売上高 |
| B14 | 平均年齢 | 従業員平均年齢 |
| B15 | 平均年収 | 従業員平均年収 |
| B16 | 初任給 | 新卒初任給 |

#### 自由記述セクション
- **企業概要**: 事業内容の概要説明
- **企業理念**: 企業の理念・ビジョン
- **事業内容**: 詳細な事業説明
- **本社**: 本社情報
- **その他主な事業所**: 支社・支店情報
- **設立年**: 設立の経緯
- **従業員数**: 従業員規模
- **資本金**: 資本構成
- **親会社**: グループ企業情報
- **売上高**: 業績推移
- **営業利益**: 収益性
- **平均年齢**: 年齢構成
- **平均年収**: 給与水準
- **初任給**: 新卒待遇
- **業界内での立ち位置やシェア**: 市場ポジション
- **採用競合と比べた企業の強み、弱み、違い、特徴など**: 競合分析
- **成長性**: 将来性評価
- **企業の課題と解決・現状**: 課題認識
- **興味を持った企業・大学時代に学んだことがどのように活かせるか**: 志望動機
- **入社後に挑戦したいこと、自分の将来像、望みたい部署など**: キャリアビジョン
- **インターン参加の有無**: インターン経験
- **インターンの内容**: インターン詳細
- **説明会・セミナー、職場見学、インターンなど、社員やOB/OGと話して気付いたこと**: 接触記録
- **感想、ニュース等情報まとめなど**: その他メモ

---

## 3. 主要機能

### 3.1 企業シート管理機能

#### 3.1.1 新規企業シート作成([`make_new()`](original/main.vb:53))

**処理フロー**:
```mermaid
graph TD
    A[開始] --> B[企業名入力ダイアログ表示]
    B --> C[テンプレートシートをコピー]
    C --> D[シート名を企業名に変更]
    D --> E[企業IDを自動採番]
    E --> F[データベースシートに企業情報を追加]
    F --> G[ハイパーリンク設定]
    G --> H[終了]
```

**機能詳細**:
- テンプレートシートを最後尾にコピー
- 企業IDは「総シート数 - 3」で自動計算
- データベースシートに企業名とIDを自動登録
- 企業名セルにハイパーリンクを自動設定

**制約事項**:
- 企業名の重複チェックなし
- 入力キャンセル時の処理なし

#### 3.1.2 データ更新機能([`read_Info()`](original/main.vb:69))

**処理フロー**:
```mermaid
graph TD
    A[開始] --> B[全企業シートをループ]
    B --> C[各シートから基本情報を読み取り]
    C --> D[金額データを日本語形式に変換]
    D --> E[データベースシートに書き込み]
    E --> F[ハイパーリンク再設定]
    F --> G{次のシートあり?}
    G -->|Yes| B
    G -->|No| H[終了]
```

**読み取り対象データ**:
- 企業ID、企業名、本社、設立年
- 資本金、売上高(金額変換処理あり)
- 平均年齢、平均年収、初任給

**データ変換処理**:
- [`conv_Num()`](original/main.vb:12)関数による金額の日本語表記変換
- 「億」「万」「円」単位での表示

### 3.2 ナビゲーション機能

#### 3.2.1 シート移動
- **トップへ移動**([`go_Top()`](original/main.vb:113)): データベースシートへ移動
- **前へ移動**([`go_Back()`](original/main.vb:117)): 1つ前のシートへ移動
- **次へ移動**([`go_Next()`](original/main.vb:121)): 1つ次のシートへ移動

**制約事項**:
- シート範囲外への移動時のエラーハンドリングなし

### 3.3 出力機能

#### 3.3.1 PDF出力([`print_Pdf()`](original/main.vb:154))

**処理フロー**:
```mermaid
graph TD
    A[開始] --> B[企業選択ダイアログ表示]
    B --> C[選択企業のシートを特定]
    C --> D[ページ設定を構成]
    D --> E[PDF出力パス生成]
    E --> F[PDFファイル出力]
    F --> G[完了メッセージ表示]
    G --> H[終了]
```

**ページ設定**:
- 印刷範囲: A1:D28
- 向き: 縦(Portrait)
- ページ収め: 横1ページ × 縦2ページ
- ヘッダー右: バージョン情報
- フッター中央: ページ番号(現在/総数)

**出力先**: ブックと同じディレクトリに「企業名.pdf」

#### 3.3.2 印刷プレビュー([`print_Paper()`](original/main.vb:180))

**処理内容**:
- PDF出力と同じページ設定
- 印刷プレビュー画面を表示
- 実際の印刷はユーザーが実行

### 3.4 バージョン管理機能

#### 3.4.1 バージョン生成([`get_Version()`](original/main.vb:125))
- 形式: `ver.YY.MM.DD`
- 現在日付から自動生成
- 例: `ver.18.01.27`

#### 3.4.2 バージョン書き込み([`write_Version()`](original/main.vb:150))
- データベースシートのC1セルに書き込み

### 3.5 金額変換機能

#### 3.5.1 日本語金額表記変換([`conv_Num()`](original/main.vb:12))

**入力形式**:
- 数値文字列(カンマ区切り可)
- 日本語単位付き(億、千万、百万、万、千、円)
- 全角・半角混在可
- 特殊値: "N/A"、空文字列

**変換処理**:
1. 全角→半角変換
2. カンマ除去
3. 日本語単位を数式に変換(例: "億" → "* 100000000 +")
4. Evaluate関数で計算
5. 結果を日本語表記に再変換

**出力形式**:
- 兆円単位: "X兆Y億Z万W円"
- 億円単位: "X億Y万Z円"
- 万円単位: "X万Y円"

**制約事項**:
- 小数点以下は切り捨て
- 負の値は未対応

---

## 4. ユーザーインターフェース

### 4.1 企業選択ダイアログ(UserForm1)

#### 4.1.1 構成要素
- **ComboBox1**: 企業名選択ドロップダウン
- **CommandButton1**: 決定ボタン
- **CommandButton2**: キャンセルボタン

#### 4.1.2 動作仕様

**初期化処理**([`UserForm_Initialize()`](original/form.vb:3)):
- データベースシートから企業名を読み込み
- ComboBoxに企業名リストを設定

**決定ボタン処理**([`CommandButton1_Click()`](original/form.vb:11)):
- 選択された企業のインデックスを取得
- 未選択時はエラーメッセージ表示
- 選択時はグローバル変数`ret_ID`に格納

**キャンセルボタン処理**([`CommandButton2_Click()`](original/form.vb:26)):
- キャンセルメッセージ表示
- フォームを閉じる

**フォームクローズ処理**([`UserForm_QueryClose()`](original/form.vb:31)):
- 決定ボタン以外でのクローズ時はアプリケーション終了

---

## 5. データ仕様

### 5.1 データ型定義

| 項目 | データ型 | 形式 | 必須 | 備考 |
|------|----------|------|------|------|
| 企業ID | Integer | 数値 | ○ | 自動採番 |
| 企業名 | String | 文字列 | ○ | 255文字以内 |
| 本社 | String | 文字列 | - | 住所形式 |
| 設立年 | Date/String | 日付 | - | 和暦・西暦混在可 |
| 資本金 | String | 日本語金額 | - | 億・万円単位 |
| 売上高 | String | 日本語金額 | - | 億・万円単位 |
| 平均年齢 | Double | 数値 | - | 小数点1桁 |
| 平均年収 | Long | 数値 | - | 整数(円) |
| 初任給 | Long | 数値 | - | 整数(円) |

### 5.2 金額表記ルール

#### 入力可能形式
- 数値のみ: `1000000`
- カンマ区切り: `1,000,000`
- 日本語単位: `100万円`、`1億円`
- 混在形式: `1億2,000万円`
- 特殊値: `N/A`(データなし)

#### 出力形式
- 1兆円以上: `X兆Y億Z万W円`
- 1億円以上: `X億Y万Z円`
- 1万円以上: `X万Y円`
- 1万円未満: 表示なし(0円扱い)

### 5.3 データ整合性

**現状の制約**:
- 企業名の重複チェックなし
- データ型バリデーションなし
- 必須項目チェックなし
- 参照整合性チェックなし

(中略)

Bobが生成した移行計画書(抜粋):

# 企業研究データベース 移行システム仕様書

## 1. 移行システム概要

### 1.1 基本方針

現行のExcel VBAベースのシステムを、モダンなWebアプリケーションに移行します。

**主要な特徴**:
- ✅ **Webブラウザのみで動作**: インストール不要
- ✅ **PWA対応**: スマートフォンのホーム画面に追加可能
- ✅ **クライアントサイド完結**: サーバー不要、個人環境でデータ管理
- ✅ **オフライン対応**: インターネット接続不要で動作
- ✅ **プライバシー重視**: データは各ユーザーのブラウザにのみ保存
- ✅ **クロスプラットフォーム**: Windows/Mac/Linux/iOS/Android対応

### 1.2 システム要件

#### ユーザー要件
- モダンなWebブラウザ(Chrome、Firefox、Edge、Safari最新版)
- JavaScript有効化
- LocalStorage/IndexedDB対応ブラウザ

#### 非要件(不要なもの)
- ❌ サーバーのセットアップ
- ❌ データベースのインストール
- ❌ ユーザー登録・ログイン
- ❌ インターネット接続(初回アクセス後)

---

## 2. アーキテクチャ設計

### 2.1 システム構成

```
┌─────────────────────────────────────────┐
│         ユーザー環境(ブラウザ)          │
├─────────────────────────────────────────┤
│  ┌─────────────────────────────────┐   │
│  │   React 18 + TypeScript         │   │
│  │   (SPA フロントエンド)           │   │
│  └─────────────────────────────────┘   │
│           ↓              ↓              │
│  ┌──────────────┐  ┌──────────────┐   │
│  │ LocalStorage │  │  IndexedDB   │   │
│  │  (設定情報)   │  │ (企業データ)  │   │
│  └──────────────┘  └──────────────┘   │
│           ↓                             │
│  ┌─────────────────────────────────┐   │
│  │  File System Access API         │   │
│  │  (インポート/エクスポート)        │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘
         ↑ 初回アクセス時のみ
┌─────────────────────────────────────────┐
│      静的ホスティング(CDN)              │
│  GitHub Pages / Netlify / Vercel       │
│  HTML / CSS / JavaScript (React)       │
└─────────────────────────────────────────┘
```

### 2.2 技術スタック

#### フロントエンド
| カテゴリ | 採用技術 | 理由 |
|---------|---------|------|
| フレームワーク | **React 18+** | エコシステムが豊富、TypeScript統合が優れている |
| 言語 | **TypeScript** | 型安全性、開発効率向上 |
| UIライブラリ | **Tailwind CSS** | ユーティリティファースト、カスタマイズ性が高い |
| 状態管理 | **Zustand** | シンプル、軽量、学習コストが低い |
| ルーティング | **React Router v6** | 標準的、ドキュメントが充実 |
| フォーム管理 | **React Hook Form** | パフォーマンスが良い、バリデーション統合 |
| バリデーション | **Zod** | TypeScriptとの相性が良い、型推論 |

#### データ管理
| 用途 | 技術 | 容量制限 |
|------|------|---------|
| 設定情報 | LocalStorage | 5-10MB |
| 企業データ | IndexedDB | 数百MB〜数GB |
| ファイル操作 | File System Access API | 制限なし |

#### ビルド・デプロイ
| カテゴリ | 採用技術 | 理由 |
|---------|---------|------|
| ビルドツール | **Vite** | 高速、React + TypeScriptのテンプレート充実 |
| PWAプラグイン | **vite-plugin-pwa** | Vite用PWAプラグイン、自動Service Worker生成 |
| パッケージマネージャー | **pnpm** | 高速、ディスク効率が良い |
| リンター | **ESLint** | コード品質維持 |
| フォーマッター | **Prettier** | コードスタイル統一 |
| ホスティング | **GitHub Pages** | 無料、簡単、GitHub統合、HTTPS対応(PWA必須) |
| CI/CD | **GitHub Actions** | 自動デプロイ、無料枠が充実 |

### 2.3 データストレージ戦略

#### LocalStorage(軽量データ)
```javascript
// 設定情報の保存例
{
  "theme": "light",
  "language": "ja",
  "lastExportDate": "2026-05-23",
  "searchHistory": ["企業A", "企業B"],
  "viewPreferences": {
    "listView": "grid",
    "sortBy": "name"
  }
}
```

#### IndexedDB(企業データ)
```javascript
// データベーススキーマ
const schema = {
  companies: {
    keyPath: "id",
    indexes: [
      { name: "companyName", unique: false },
      { name: "foundedYear", unique: false },
      { name: "capital", unique: false },
      { name: "createdAt", unique: false }
    ]
  }
};

// 企業データの例
{
  id: "uuid-v4",
  companyName: "株式会社サンプル",
  headquarters: "東京都千代田区",
  foundedYear: "2000-04-01",
  capital: "10億円",
  revenue: "100億円",
  averageAge: 35.5,
  averageSalary: 6000000,
  startingSalary: 250000,
  overview: "企業概要...",
  businessDescription: "事業内容の詳細...",
  philosophy: "企業理念...",
  // ... その他のフィールド
  createdAt: "2026-05-23T09:00:00Z",
  updatedAt: "2026-05-23T09:30:00Z"
}
```

---

## 3. 機能仕様

### 3.1 現行機能の移行

#### 3.1.1 企業管理機能

| 現行機能 | 移行後の実装 | 備考 |
|---------|-------------|------|
| 新規企業シート作成 | 企業追加フォーム | モーダルまたは専用ページ |
| 企業情報編集 | インライン編集 | 即座に保存 |
| 企業削除 | 削除ボタン + 確認ダイアログ | 論理削除も検討 |
| データ更新 | 自動保存 | 入力時に即座に保存 |

#### 3.1.2 ナビゲーション機能

| 現行機能 | 移行後の実装 |
|---------|-------------|
| トップへ移動 | ホームボタン / ロゴクリック |
| 前へ/次へ移動 | ブラウザの戻る/進む、またはナビゲーションボタン |
| 企業間移動 | 企業一覧からクリック、または検索 |

#### 3.1.3 出力機能

| 現行機能 | 移行後の実装 | ライブラリ |
|---------|-------------|-----------|
| PDF出力 | ブラウザ印刷 + PDF保存 | jsPDF / pdfmake |
| 印刷プレビュー | ブラウザ標準の印刷機能 | @media print CSS |

#### 3.1.4 金額変換機能

```javascript
// 日本語金額表記の変換関数
function formatCurrency(value) {
  if (!value || value === "N/A") return value;
  
  const num = parseFloat(value.replace(/[^\d.]/g, ''));
  
  if (num >= 1e12) {
    return `${(num / 1e12).toFixed(1)}兆円`;
  } else if (num >= 1e8) {
    return `${(num / 1e8).toFixed(1)}億円`;
  } else if (num >= 1e4) {
    return `${(num / 1e4).toFixed(1)}万円`;
  }
  return `${num.toLocaleString()}円`;
}
```

### 3.2 新規追加機能

#### 3.2.1 検索機能(新規)

**機能概要**:
- 全文検索: すべてのフィールドを対象
- インクリメンタルサーチ: 入力中にリアルタイム検索
- 複数条件検索: AND/OR条件の組み合わせ
- 検索履歴: 過去の検索条件を保存

**実装方針**:
```javascript
// 検索処理の例
async function searchCompanies(query) {
  const db = await openDB();
  const companies = await db.getAll('companies');
  
  return companies.filter(company => {
    const searchText = Object.values(company)
      .join(' ')
      .toLowerCase();
    return searchText.includes(query.toLowerCase());
  });
}
```

**UI設計**:
- 検索バー: ヘッダーに常時表示
- フィルター: サイドバーまたはドロップダウン
- 結果表示: カード形式またはテーブル形式
- ハイライト: 検索キーワードを強調表示

#### 3.2.2 インポート/エクスポート機能(新規)

**エクスポート機能**:
```javascript
// JSON形式でエクスポート
async function exportData() {
  const db = await openDB();
  const companies = await db.getAll('companies');
  
  const exportData = {
    version: "1.0",
    exportDate: new Date().toISOString(),
    companies: companies
  };
  
  const blob = new Blob(
    [JSON.stringify(exportData, null, 2)],
    { type: 'application/json' }
  );
  
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `companies_${Date.now()}.json`;
  a.click();
}
```

**インポート機能**:
```javascript
// JSONファイルからインポート
async function importData(file) {
  const text = await file.text();
  const data = JSON.parse(text);
  
  // バージョンチェック
  if (data.version !== "1.0") {
    throw new Error("Unsupported version");
  }
  
  // データ検証
  validateImportData(data);
  
  // IndexedDBに保存
  const db = await openDB();
  for (const company of data.companies) {
    await db.put('companies', company);
  }
}
```

**ファイル形式**:
```json
{
  "version": "1.0",
  "exportDate": "2026-05-23T09:00:00Z",
  "companies": [
    {
      "id": "uuid",
      "companyName": "企業名",
      "headquarters": "本社",
      "foundedYear": "2000-01-01",
      "capital": "10億円",
      "revenue": "100億円",
      "averageAge": 35.5,
      "averageSalary": 6000000,
      "startingSalary": 250000,
      "overview": "企業概要",
      "businessDescription": "事業内容",
      "createdAt": "2026-05-23T09:00:00Z",
      "updatedAt": "2026-05-23T09:00:00Z"
    }
  ]
}
```

---

## 4. データ移行計画

### 4.1 移行ツールの開発

#### Excel → JSON 変換マクロ

```vba
' Excel VBAマクロ(移行用)
Sub ExportToJSON()
    Dim json As String
    Dim i As Integer
    Dim ws As Worksheet
    
    json = "{" & vbCrLf
    json = json & "  ""version"": ""1.0""," & vbCrLf
    json = json & "  ""exportDate"": """ & Format(Now, "yyyy-mm-ddThh:nn:ss") & "Z""," & vbCrLf
    json = json & "  ""companies"": [" & vbCrLf
    
    For i = 3 To Worksheets.Count
        Set ws = Worksheets(i)
        If ws.Name <> "_Template" And ws.Name <> "データベース" Then
            json = json & "    {" & vbCrLf
            json = json & "      ""id"": """ & CreateUUID() & """," & vbCrLf
            json = json & "      ""companyName"": """ & EscapeJSON(ws.Cells(3, 2).Value) & """," & vbCrLf
            json = json & "      ""headquarters"": """ & EscapeJSON(ws.Cells(6, 2).Value) & """," & vbCrLf
            ' ... 他のフィールド
            json = json & "    }"
            If i < Worksheets.Count Then json = json & ","
            json = json & vbCrLf
        End If
    Next i
    
    json = json & "  ]" & vbCrLf
    json = json & "}" & vbCrLf
    
    ' ファイルに保存
    SaveToFile json, ThisWorkbook.Path & "\export.json"
End Sub
```

### 4.2 移行手順

1. **準備**
   - 現行Excelファイルのバックアップ
   - データの整合性確認

2. **エクスポート**
   - 移行用VBAマクロを実行
   - JSON形式でエクスポート
   - エクスポートファイルの確認

3. **インポート**
   - 新システムにアクセス
   - 「データをインポート」を選択
   - JSONファイルをアップロード
   - インポート結果の確認

4. **検証**
   - 企業数の一致確認
   - 各企業の詳細情報確認
   - 特殊文字の表示確認
   - 金額表記の確認

### 4.3 データクレンジング

#### 移行前の確認事項
- [ ] 企業名の重複チェック
- [ ] 必須項目の欠損確認
- [ ] 金額表記の統一
- [ ] 日付形式の統一
- [ ] 特殊文字のエスケープ

#### データ変換ルール
| 項目 | 変換前 | 変換後 |
|------|--------|--------|
| 金額 | "10億円" | "1000000000" または "10億円"(表示用) |
| 日付 | "平成12年4月1日" | "2000-04-01" |
| 改行 | Excel改行 | "\n" |
| 引用符 | " | \" |

---

## 5. ユーザーインターフェース設計

### 5.1 画面構成

#### 5.1.1 ホーム画面(企業一覧)

```
┌─────────────────────────────────────────────┐
│ [ロゴ] 企業研究データベース    [検索バー]  [+新規] │
├─────────────────────────────────────────────┤
│ [フィルター]                                 │
│ ┌─────────────────────────────────────────┐ │
│ │ 企業カード                                │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ 企業A                    [編集][削除] │ │ │
│ │ │ 本社: 東京都              資本金: 10億 │ │ │
│ │ │ 設立: 2000年              売上: 100億  │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ 企業B                    [編集][削除] │ │ │
│ │ │ ...                                   │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ [エクスポート] [インポート] [設定]           │
└─────────────────────────────────────────────┘
```

#### 5.1.2 企業詳細画面

```
┌─────────────────────────────────────────────┐
│ [←戻る] 企業A                  [編集][PDF]  │
├─────────────────────────────────────────────┤
│ 基本情報                                     │
│ ┌─────────────────────────────────────────┐ │
│ │ 企業名: 株式会社A                         │ │
│ │ 本社: 東京都千代田区                      │ │
│ │ 設立年: 2000年4月1日                      │ │
│ │ 資本金: 10億円                            │ │
│ │ 売上高: 100億円                           │ │
│ │ 平均年齢: 35.5歳                          │ │
│ │ 平均年収: 600万円                         │ │
│ │ 初任給: 25万円                            │ │
│ └─────────────────────────────────────────┘ │
│                                              │
│ 詳細情報                                     │
│ ┌─────────────────────────────────────────┐ │
│ │ [企業概要]                                │ │
│ │ テキストエリア...                         │ │
│ │                                           │ │
│ │ [事業内容]                                │ │
│ │ テキストエリア...                         │ │
│ │                                           │ │
│ │ [企業理念]                                │ │
│ │ テキストエリア...                         │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
```

### 5.2 レスポンシブデザイン

#### デスクトップ(1920x1080以上)
- 3カラムレイアウト
- サイドバーでフィルター表示
- カード形式で企業一覧

#### タブレット(768x1024)
- 2カラムレイアウト
- フィルターは折りたたみ
- カード形式を維持

#### スマートフォン(375x667以上)
- 1カラムレイアウト
- ハンバーガーメニュー
- リスト形式で企業一覧

### 5.3 ダークモード対応

```css
/* ライトモード */
:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f5f5f5;
  --text-primary: #333333;
  --text-secondary: #666666;
  --border-color: #e0e0e0;
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  :root {
    --bg-primary: #1a1a1a;
    --bg-secondary: #2d2d2d;
    --text-primary: #ffffff;
    --text-secondary: #b0b0b0;
    --border-color: #404040;
  }
}
```

Bobが移行計画を元に提案したTodoリスト:

最初にタスクを投げた時点でTodoリストは作成されているが、移行計画に沿って実装を支持すると、自らTodoリストを更新し承認を求めてくれる。

image.png

上記のタスクに沿って実装を進める中で、以下のように不足している要件(今回はフロントエンドフレームワークの選定)の確認やモード切り替えの提案を挟んでくれた。

スクリーンショット 2026-05-25 20.30.29.png

スクリーンショット 2026-05-25 20.30.44.png

Bobがやったこと

技術スタック

Bobが選定した構成は以下の通りである。

カテゴリ 採用技術
UIライブラリ React 19
言語 TypeScript
ビルドツール Vite
CSS Tailwind CSS 4
ルーティング React Router v7
フォーム React Hook Form + Zod
DB IndexedDB (Dexie.js)
状態管理 Zustand
PWA vite-plugin-pwa
PDF出力 jsPDF + html2canvas

企業情報管理(CRUD)

BobはVBA版の入力項目を仕様書から読み取り、そのままWebアプリのデータモデルに変換した。(企業名・理念・財務情報・競合分析・志望動機・インターン記録など)

export interface Company {
  id: string;
  companyName: string;
  philosophy?: string;
  businessDescription?: string;
  revenue?: string;
  operatingIncome?: string;
  motivation?: string;
  careerVision?: string;
  internshipParticipated?: boolean;
  // ...他フィールド省略
  createdAt: string;
  updatedAt: string;
}

選考記録機能

移行が一段落したタイミングで、私自身が「選考フェーズごとの記録機能を追加したい」と指示して実装させた機能である。移行だけでなく新規機能の追加もBobが問題なく対応できることを確認できた。カジュアル面談・一次面接・二次面接などのフェーズと結果(通過/不合格/待機中)を管理できる。

export interface SelectionRecord {
  id: string;
  companyId: string;
  phase: string;
  date: string;
  content: string;
  result?: string;
  createdAt: string;
  updatedAt: string;
}

IndexedDBによるデータ永続化

クライアント環境で独立して動作させるため、BobはDexie.jsを採用してIndexedDBを扱う構成を選択した。バックエンドなしにデータが永続化できる。

export class CompanyDatabase extends Dexie {
  companies!: Table<Company, string>;
  selectionRecords!: Table<SelectionRecord, string>;

  constructor() {
    super('CompanyResearchDB');
    this.version(3).stores({
      companies: 'id, companyName, foundedYear, capital, createdAt, updatedAt',
      selectionRecords: 'id, companyId, date, createdAt, updatedAt'
    });
  }
}

PDF出力(日本語対応)

jsPDFは標準で日本語フォントを持たない。Bobはこの問題を自律的に検知し、「カスタムフォント埋め込みはバンドルサイズが増大するため、html2canvasでHTMLを画像化してPDF変換する方式を採用する」と説明した上で実装した。

export async function exportCompanyToPDF(company: Company, selectionRecords: SelectionRecord[]) {
  const container = document.createElement('div');
  container.style.position = 'absolute';
  container.style.left = '-9999px';
  container.style.width = '210mm';
  document.body.appendChild(container);

  container.innerHTML = `<!-- 企業情報HTML -->`;

  try {
    const canvas = await html2canvas(container, { scale: 2, backgroundColor: '#ffffff' });
    const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' });

    const imgWidth = 210;
    const pageHeight = 297;
    const imgHeight = (canvas.height * imgWidth) / canvas.width;
    let heightLeft = imgHeight;
    let position = 0;

    pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight);
    heightLeft -= pageHeight;

    while (heightLeft > 0) {
      position = heightLeft - imgHeight;
      pdf.addPage();
      pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight);
      heightLeft -= pageHeight;
    }

    pdf.save(`${company.companyName}_企業研究シート.pdf`);
  } finally {
    document.body.removeChild(container);
  }
}

今回Skipしたこと:デプロイワークフローの実装

BobのTodoリストには本番環境へのデプロイワークフロー(CI/CD)の実装も提案として含まれていた。今回はスコープ外としてSkipしたが、これはBobが単なるコーディング補助ではなく、CI/CDを含む開発後のフローまでを視野に入れて設計されていることの表れだと感じた。BobのスコープがコーディングからデプロイまでのSDLC全体をカバーしようとしていることは、この提案からも実感できた。

Bobを使って気づいたこと

事前にTodoリストを提示してから動く

作業を依頼すると、即座に実装へ入るのではなく、まず計画をTodoリスト形式で提示する。承認後に初めて実装が開始されるため、何が行われるかを事前に把握できる。今回のような「既存コードを渡して仕様書を作れ」という雑な要件であっても、Bobが必要な作業を整理して明示してくれた。

モードの切り替えをBob自身が提案する

BobにはPlan・Code・Orchestratorなどのモードが存在するが、利用者がモードを意識する必要はほとんどない。状況に応じてBob自身が最適なモードへの切り替えを提案してくれるため、迷わず作業を進められる。

エラーの自律修正がほぼ機能する

実装中にモーダルが表示されないなどのエラーが何度か発生したが、ほとんどBob自身が解消した。途中の機能改善依頼も都度対応してくれた。これだけの壁打ちを経ても、無料トライアルの40 Bob coin以内に収まった点は、コスト感覚の把握という意味でも参考になった。

ただし、ライト/ダークモードの手動切り替え実装だけは完遂できなかった。Tailwind CSS 4でのダークモード制御とhtmlbody要素へのクラス付与が絡む実装で、私の指示の出し方に問題があった可能性も否定できないが、他の実装と比べると明らかに苦戦した箇所であった。

まとめ・所感

私がやったことは「モダナイゼーションしたい」と伝えて既存コードとスクリーンショットを渡しただけで、仕様書・移行計画・技術選定・実装のすべてをBobが主導し、約1時間で概ね動くものができた。移行中に新規機能を追加させても対応でき、壁打ちを重ねても無料トライアルの範囲に収まった。

Bobの設計思想は、コード補完に留まらずSDLC全体(要件定義・設計・実装・テスト・デプロイ)をカバーする点にある。GitHub CopilotやCursorが「IDEの中でコードを書く速度を上げるツール」であるのに対し、Bobは「開発ワークフローの土台ごと置き換えようとするツール」となりうる。CI/CDのデプロイワークフローまでTodoに挙げてくる点が、その設計思想を示していた。

今回は試せていないが、Bob Shellによるエージェント型プロセスの自己文書化や、管理者向けに自動収集される監査ログといった機能は、アーキテクチャレベルで「AIが何をしたか追跡できない」という課題に応えている点は、エンタープライズでの活用が期待される。

実際に消費したコイン・トークン:

image.png


参考リンク

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?