導入(問題提起)

共有フォルダのAccessやExcelが“事実上の業務システム”になっている——多くの中小企業で見られる光景です。ファイル破損、同時編集の競合、履歴/権限の弱さ、そして担当者のVBAに依存したブラックボックス。データが資産である以上、このままでは拡張も統制も難しく、事故の潜在リスクが常に存在します。今こそExcel Web化を含む「Webシステム開発」への段階移行を検討すべきタイミングです。

本記事では、既存のAccess/共有Excelから安全に業務システムへ移行するための実務的な手順を、計画・データ・アプリ・運用の4観点で解説します。Pythonを用いた最小構成と、ダウンタイムをほぼゼロにする並走運用のやり方も具体例で示します。

課題の詳細説明

移行に立ちはだかる典型的な課題は次のとおりです。

  • 移行時の業務停止を避けたい
  • - 曜日・締め処理・ピーク時間帯など、止められない時間がある

  • データの不整合や重複
  • - シートごとに列名・型・コードが微妙に異なる。突合に時間がかかる

  • 過去マクロ/VBA依存
  • - ビジネスルールがVBAに埋もれており、仕様書が存在しない

  • セキュリティ/コンプライアンス
  • - 誰がいつ閲覧/更新したかの監査ができない、持ち出し制御が難しい

  • ユーザー教育/定着
  • - 新しいUIに抵抗があり、併用期間が長引くとカオス化する

これらに対しては、「現状の正確な棚卸し」と「段階移行(並走運用)」が有効です。いきなり“全置き換え”を狙わず、特に重要なデータと機能からスライスして移すのが安全です。

解決方法

安全な移行の骨子は次の5段階です。

  1. 現状棚卸:データ・機能・周辺連携の見える化
  2. - Accessのテーブル/クエリ/フォーム、Excelのシート/列/数式/マクロをリスト化 - データ定義書(列名/型/コード/必須/一意/外部キー相当)を作成

  3. 標準化/正規化:コード体系と言葉の統一
  4. - 顧客/製品/担当/拠点などのマスタを整理し、コードの重複や表記揺れを排除

  5. 技術基盤の最小構築:Python+SQLite(→MySQL/PostgreSQL)
  6. - まずはSQLiteでモデル/API/認証を実装し、PoCを短期で回す - 成長に合わせてMySQL/PostgreSQLへ移行(スキーマ互換を意識)

  7. 段階移行:参照→登録→更新の順に切替
  8. - 先に「参照系(照会・レポート)」を新システムで提供し、業務影響を抑える - 次に「登録」を新システムへ、最後に「更新/一括処理」を移す

  9. 並走運用とカットオーバー:短時間切替
  10. - 二重入力を最小化する期間を定め、差分同期/凍結期間を計画 - リハーサル→本番切替→旧資産のアーカイブ/リードオンリー化

具体例

現実の現場で有効だったケースを3つ紹介します。

  • ケースA:見積/受注台帳のAccessをWeb化
  • - 先に“参照用ダッシュボード”を公開(営業はスマホで検索可能に) - 1か月後に「新規見積の登録」をWebへ移し、最終月に更新系を切替

  • ケースB:共有Excelの在庫管理を分割移行
  • - マスタ(SKU/倉庫)→入出庫履歴→調整/棚卸の順で移管し、二重入力を2週間に限定 - Excel側は参照専用に凍結、CSV出力で既存帳票に連携

  • ケースC:VBA帳票の置き換え
  • - 既存VBAのルールを読み取り、Pythonで帳票APIを実装 - 帳票のテンプレートは共通化し、将来の改修コストを半減

技術的な解説

Pythonでの最小実装と、データ移行の断片を示します。ポイントは「移行しやすいスキーマ」と「監査/RBACの標準実装」です。


-- 代表的なマスタ/トランザクションの最小モデル
CREATE TABLE customers (
  id INTEGER PRIMARY KEY,
  code TEXT UNIQUE NOT NULL,
  name TEXT NOT NULL
);

CREATE TABLE orders (
  id INTEGER PRIMARY KEY,
  order_no TEXT UNIQUE NOT NULL,
  customer_id INTEGER NOT NULL REFERENCES customers(id),
  order_date DATE NOT NULL,
  amount DECIMAL(12,2) NOT NULL,
  status TEXT CHECK (status IN ('new','confirmed','shipped','canceled'))
);

CREATE TABLE audit_logs (
  id INTEGER PRIMARY KEY,
  user_id INTEGER,
  action TEXT,
  meta TEXT,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

# Bottleでの最小API(登録/参照)
from bottle import Bottle, request
import sqlite3, json

app = Bottle()

def db():
    return sqlite3.connect('app.db')

@app.get('/api/orders')
def orders_list():
    con=db(); cur=con.cursor(); cur.execute('SELECT order_no, order_date, amount FROM orders ORDER BY order_date DESC LIMIT 200')
    rows=cur.fetchall(); con.close()
    return [{'order_no':r[0], 'date':r[1], 'amount':float(r[2])} for r in rows]

@app.post('/api/orders')
def create_order():
    data = request.json
    con=db(); cur=con.cursor()
    cur.execute('INSERT INTO orders(order_no, customer_id, order_date, amount, status) VALUES (?,?,?,?,?)',
                (data['order_no'], data['customer_id'], data['order_date'], data['amount'], 'new'))
    con.commit(); con.close()
    return {'ok': True}

# CSV→DBの段階移送(Pandasを使わない最小形)
import csv, sqlite3

def load_customers(csv_path):
    con=sqlite3.connect('app.db'); cur=con.cursor()
    with open(csv_path, newline='', encoding='utf-8') as f:
        for row in csv.DictReader(f):
            cur.execute('INSERT OR IGNORE INTO customers(code, name) VALUES (?,?)', (row['code'], row['name']))
    con.commit(); con.close()

RBAC(Role-Based Access Control)は、閲覧/登録/更新/エクスポートをロールで制御。エクスポート時は監査ログにファイル名/件数/フィルタ条件を記録します。これは業務システムの基本であり、コンプライアンスの観点でも重要です。

導入の流れ

短期で安全に移行するための標準ロードマップです。

  1. 1週目:現状棚卸&方針決定
  2. - テーブル/シート/マクロ/帳票/連携を洗い出し、優先順位を決定 - 新旧の“言葉/コード”を統一(辞書化)

  3. 2週目:PoC(Python+SQLite)
  4. - 最小スキーマ、認証、参照API、ダッシュボード(KPI 3枚) - CSV移送の雛形を作り、ボリューム/品質を測る

  5. 3週目:段階移行(参照→登録)
  6. - 現場公開しフィードバック収集。エクスポート/帳票を追加

  7. 4週目:カットオーバー準備と本番切替
  8. - 二重入力の凍結期間を設定、最終同期→本番切替→旧資産は参照専用に

まとめ

Access/共有Excelからの移行は、全置換ではなく“段階移行+並走運用”が成功パターンです。Pythonを活用した最小構成と、標準的なスキーマ/マイグレーション/監査/RBACを最初から入れることで、後戻りなく拡張できます。Excel Web化の次の一歩として、業務システムへの移行を現実的・安全に進めましょう。

移行計画の策定から実装まで伴走します。ご相談は以下よりどうぞ。

Webシステム開発のご相談は monou まで ※お問い合わせはこちら