Database Microsoft Access ada di mana-mana di UKM Indonesia. Mereka dibangun di akhir tahun 2000-an oleh seseorang yang 'tahu sedikit tentang komputer,' mereka menjalankan fungsi bisnis kritis, dan tidak ada yang sepenuhnya yakin bagaimana cara kerjanya lagi. Database Access memiliki batas ukuran file 2GB, tidak ada dukungan multi-pengguna konkuren, tidak ada API, tidak ada jejak audit, dan keamanan yang hanya berupa kata sandi sistem file. Migrasi ke ERP kustom modern sudah lama tertunda bagi sebagian besar bisnis yang masih menjalankan Access.
Sebelum merencanakan migrasi, audit sistem Access secara detail. Tabel apa yang ada dan apa yang dikandungnya? Formulir dan laporan apa yang digunakan, oleh siapa, seberapa sering? Kueri apa yang ada dan logika bisnis apa yang mereka implementasikan? Apakah ada modul VBA dengan perhitungan atau aturan validasi kustom? Apa yang terintegrasi dengan atau bergantung pada database Access?
Mengekstrak data dari Access secara teknis mudah — database Access adalah file MDB atau ACCDB yang dapat dibaca oleh alat yang kompatibel dengan ODBC. Di Python, gunakan pyodbc atau pustaka msaccessdb. Tantangannya bukan pada ekstraksi — melainkan pada tampilan data setelah diekstrak. Data Access umumnya memiliki: bidang teks yang digunakan untuk nilai numerik, bidang tanggal dengan berbagai format, nilai nol yang sebenarnya adalah string kosong.
Kode VBA Access sering berisi logika bisnis kritis yang harus direplikasi dalam sistem baru. Formula perhitungan, aturan validasi, fungsi transformasi data, logika pembuatan laporan — semua ini perlu dipahami dan diimplementasikan ulang. Untuk setiap modul atau fungsi VBA, dokumentasikan apa yang dilakukannya dalam bahasa biasa, dapatkan validasi dari pengguna bisnis, lalu implementasikan ulang dalam sistem baru dengan tes yang tepat.
Access Database → Modern ERP Migration Pipeline
┌─────────────────────────────────────────────────────────────┐
│ STAGE 1: AUDIT │
│ ● List all tables, forms, reports, VBA modules │
│ ● Interview 5+ users: "What do you do in Access every day?"│
│ ● Map each form → business workflow │
│ ● Identify custom VBA logic (pricing, tax, calculations) │
└────────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ STAGE 2: EXTRACT (Python + pyodbc) │
│ ● Read all .mdb/.accdb tables into staging PostgreSQL DB │
│ ● Preserve original column names for traceability │
│ ● Profile: NULL counts, duplicates, type mismatches │
└────────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ STAGE 3: TRANSFORM │
│ ● Standardize date formats (dd/mm/yyyy → ISO 8601) │
│ ● Convert Yes/No → boolean (Access uses -1/0) │
│ ● Deduplicate records (keep most recent by date) │
│ ● Map old codes → new ERP codes │
│ ● Validate referential integrity │
│ ● Flag rows needing business owner review │
└────────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ STAGE 4: VALIDATE │
│ ● Business data steward reviews flagged records │
│ ● Record count check: source = target (±intentional drops) │
│ ● Financial balance check: AR, AP, inventory totals match │
│ ● Spot check: 20+ records per entity type manually verified│
└────────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ STAGE 5: PARALLEL RUN (4 weeks minimum) │
│ ● Both Access and ERP running simultaneously │
│ ● Compare identical transactions from both systems daily │
│ ● Access = read-only after go-live decision │
└────────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────┐
│ STAGE 6: ARCHIVE + SHUTDOWN │
│ ● Archive Access .mdb file in secure storage │
│ ● Set hard shutdown date (Day 30–60 post go-live) │
│ ● Remove Access from shared drives │
└─────────────────────────────────────────────────────────────┘Dari pengalaman saya mengimplementasikan ERP di Commsult: saat migrasi dari Access, jalankan sistem lama dan ERP baru secara paralel selama setidaknya 4 minggu, bandingkan output untuk set transaksi yang sama. Hasilkan laporan yang sama dari kedua sistem dan bandingkan baris demi baris. Setiap perbedaan adalah bug migrasi atau kasus di mana sistem lama salah.
Pipeline migrasi Access-ke-ERP yang solid memiliki tahapan ini: Tahap 1 — Ekstrak: skrip Python membaca semua tabel Access via pyodbc. Tahap 2 — Profil: kueri SQL mengidentifikasi masalah kualitas data dalam database staging. Tahap 3 — Transform: skrip pembersihan data memperbaiki masalah kualitas dan memetakan skema Access ke skema ERP. Tahap 4 — Validasi: data steward bisnis memverifikasi data yang ditransformasi. Tahap 5 — Load: skrip migrasi menyisipkan data yang divalidasi ke database ERP produksi.
# Python: Extract all tables from Microsoft Access .mdb/.accdb
import pyodbc
import pandas as pd
from sqlalchemy import create_engine
# Connect to Access database (Windows ODBC driver required)
ACCESS_CONN = (
r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};"
r"DBQ=C:\legacy\commsult_legacy.accdb;"
)
conn = pyodbc.connect(ACCESS_CONN)
cursor = conn.cursor()
# List all user tables (exclude system tables)
tables = [row.table_name for row in cursor.tables(tableType='TABLE')
if not row.table_name.startswith('MSys')]
print(f"Found {len(tables)} tables: {tables}")
# PostgreSQL staging database
pg_engine = create_engine(
"postgresql://user:pass@localhost:5432/erp_staging"
)
for table in tables:
df = pd.read_sql(f"SELECT * FROM [{table}]", conn)
# Fix Access-specific type issues
for col in df.columns:
if df[col].dtype == object:
# Handle Yes/No fields stored as True/False
if set(df[col].dropna().unique()).issubset({True, False, -1, 0}):
df[col] = df[col].map({True: True, -1: True, False: False, 0: False})
# Load to staging (preserve Access schema for reference)
df.to_sql(f"access_{table.lower()}", pg_engine,
if_exists='replace', index=False)
print(f"✓ Loaded {len(df):,} rows from [{table}]")
# Profile data quality issues
with pg_engine.connect() as pg_conn:
for table in tables:
tbl = f"access_{table.lower()}"
result = pg_conn.execute(f"""
SELECT
'{table}' as table_name,
COUNT(*) as total_rows,
COUNT(*) - COUNT(DISTINCT *) as potential_duplicates
FROM {tbl}
""").fetchone()
print(f"{result}")
conn.close()Orang-orang yang menggunakan Access setiap hari telah membangun keahlian mereka di sekitarnya. Mereka mengetahui pintasan keyboard, tata letak formulir, lokasi laporan. Mengganti basis pengetahuan itu adalah kerugian nyata, dan itu layak mendapat pengakuan. Komunikasi transisi harus jujur: sistem baru lebih mampu, lebih aman, dan lebih dapat dipelihara. Beberapa minggu pertama akan lebih lambat saat Anda mempelajari alur kerja baru.
Godaan setelah go-live ERP yang berhasil adalah membiarkan database Access tetap berjalan 'untuk berjaga-jaga.' Begitulah sistem bayangan bertahan selama bertahun-tahun. Tetapkan tanggal penutupan yang keras untuk database Access — 30–60 hari setelah go-live ERP — dan komunikasikan dengan jelas kepada semua pengguna sebelum go-live.
Laporan Access sering merupakan output paling kritis secara bisnis dari sistem, dan paling sulit untuk dimigrasikan. Inventarisasi setiap laporan Access: nama, siapa yang menggunakannya, seberapa sering, keputusan apa yang didukungnya. Untuk setiap laporan, tentukan apakah dapat direplikasi dalam pelaporan bawaan ERP, apakah memerlukan laporan kustom yang dibangun dalam ERP, atau apakah harus digantikan oleh laporan yang lebih baik.
90 hari pertama setelah migrasi dari Access ke ERP mengungkapkan kesenjangan migrasi apa pun yang tidak ditangkap pengujian. Jalankan sistem Access dalam mode read-only selama 30 hari pertama. Pantau perbedaan data — jika pengguna bertanya 'mengapa ERP menunjukkan 15 unit tetapi Access menunjukkan 17?' itu adalah bug migrasi yang perlu diselidiki.