ねらい:Excelを「DBのフロントエンド」にするための型を持つ
DB連携テンプレのゴールは、こうです。
「毎回ググりながらADOコードを書く」のをやめて、
接続・SELECT・INSERT/UPDATE・切断までを“いつも同じ型”で書けるようにすることです。
ここでは、いちばん現場で使いやすい「Excel VBA+ADO」のテンプレを、
プログラミング初心者でも真似できる形でまとめます。
全体像:DB連携の基本フローと設計方針
DB連携の4ステップ
Excelから外部DB(SQL Server、Access、MySQLなど)に接続するとき、流れはいつも同じです。
- 接続オブジェクト(Connection)を作る
- 接続文字列(ConnectionString)を指定して DB に接続する
- SQL を実行して、結果を Recordset で受け取る(SELECT)
- 結果をシートに展開したり、更新系(INSERT/UPDATE/DELETE)を実行したりする
この「4ステップ」を、毎回コピペではなく“テンプレ関数”として持っておくのが、DB連携テンプレの狙いです。
設計方針:3つのレイヤーに分ける
DB連携コードは、次の3つに分けておくと、あとで圧倒的に楽になります。
接続まわり(共通の Connection ヘルパー)
SQL実行まわり(SELECT用・更新用の共通関数)
業務ロジック(「何を取りたいか」「どこに出すか」)
重要なのは、「業務ロジックの中に生の接続コードをベタ書きしない」ことです。
接続とSQL実行は“部品”、業務ロジックは“部品の組み合わせ”という意識を持つと、再利用性が一気に上がります。
コア部品1:接続ヘルパー(Connection)テンプレ
まずは「Accessに接続する」一番シンプルな例
例として、同じフォルダにある Sample.accdb(Access DB)に接続するテンプレからいきます。
' ModDb.bas
Option Explicit
Public Function OpenAccessConnection() As Object
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
Dim dbPath As String
dbPath = ThisWorkbook.Path & "\Sample.accdb"
Dim connStr As String
connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & dbPath & ";"
conn.Open connStr
Set OpenAccessConnection = conn
End Function
VB初心者向けにポイントをかみ砕きます。
CreateObject(“ADODB.Connection”) で「接続用の箱」を作る
ConnectionString に「どのDBに、どのプロバイダでつなぐか」を書く
Open で実際に接続する
最後に、その Connection を戻り値として返す
この関数を作っておけば、「Accessに接続する」という作業はどこからでも一行で呼べます。
Dim conn As Object
Set conn = OpenAccessConnection()
VBSQL Server や他のDBでも、基本は同じで「ConnectionString だけが違う」と考えてOKです。
コア部品2:SELECT用テンプレ(Recordset→シート)
「SQLを投げて、結果をシートに出す」共通関数
次に、「SELECT文を実行して、結果を指定シートに貼る」テンプレを作ります。
Public Sub RunSelectToSheet( _
ByVal sql As String, _
ByVal targetSheetName As String, _
Optional ByVal startCellAddress As String = "A1")
Dim conn As Object
Set conn = OpenAccessConnection()
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
rs.Open sql, conn, 1, 1 ' 1=adOpenKeyset, 1=adLockReadOnly(簡易指定)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(targetSheetName)
ws.Range(startCellAddress).CurrentRegion.Clear
ws.Range(startCellAddress).CopyFromRecordset rs
rs.Close
conn.Close
End Sub
VBここでの重要ポイントは、次の通りです。
Recordset を使って SQL の結果を受け取る
CopyFromRecordset で、一気にシートに貼り付ける
終わったら rs.Close と conn.Close で必ず閉じる
この Sub を持っておけば、「SQLを書くだけでシートに結果を出せる」状態になります。
例題:顧客マスタを Excel に取り込む
Access 側に M_Customer テーブルがあるとします。
顧客コードと顧客名を Excel の Customer シートに取り込みたい場合は、こう書くだけです。
Sub LoadCustomerFromDb()
Dim sql As String
sql = "SELECT CustomerCode, CustomerName FROM M_Customer ORDER BY CustomerCode"
RunSelectToSheet sql, "Customer", "A1"
End Sub
VB業務ロジック側は「どのテーブルから、どの列を、どんな条件で取るか」だけに集中できて、
接続やRecordsetの細かい処理はテンプレに隠せます。
コア部品3:INSERT/UPDATE/DELETE用テンプレ(更新系)
「件数だけ返す」更新系テンプレ
SELECT 以外(INSERT/UPDATE/DELETE)は、Recordset は不要で、
「何件影響したか」だけ分かれば十分なことが多いです。
Public Function ExecuteNonQuery(ByVal sql As String) As Long
Dim conn As Object
Set conn = OpenAccessConnection()
Dim affected As Long
conn.Execute sql, affected
conn.Close
ExecuteNonQuery = affected
End Function
VBポイントは、Connection.Execute の第2引数に「影響行数」が返ってくることです。
これをそのまま戻り値にしておけば、「何件更新されたか」を呼び出し側で確認できます。
例題:ExcelのデータをDBにINSERTする
例えば、Excel の Upload シートに、A列:顧客コード、B列:顧客名 が入っていて、
それを M_Customer テーブルにINSERTしたいとします。
Sub UploadCustomerToDb()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Upload")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
If lastRow < 2 Then Exit Sub
Dim i As Long
For i = 2 To lastRow
Dim code As String
Dim name As String
code = Replace(CStr(ws.Cells(i, 1).Value), "'", "''")
name = Replace(CStr(ws.Cells(i, 2).Value), "'", "''")
Dim sql As String
sql = "INSERT INTO M_Customer (CustomerCode, CustomerName) " & _
"VALUES ('" & code & "', '" & name & "')"
ExecuteNonQuery sql
Next i
End Sub
VBここではシンプルさを優先して「1行ずつINSERT」していますが、
実務ではトランザクションや一括INSERTを検討しても良い場面です。
重要なのは、「更新系も ExecuteNonQuery に隠す」という型を持つことです。
コア部品4:設定シート方式と組み合わせる(DB版)
接続情報を「設定シート」に逃がす
実務では、接続文字列の中に「サーバー名」「DB名」「ユーザー名」「パスワード」などが入ります。
これをコードにベタ書きすると、環境が変わるたびにVBAを開いて修正することになり、危険でもあります。
そこで、「ConfigDb」シートを用意して、こんな感じで持たせます。
A列:キー名(Server, Database, User, Password, Provider など)
B列:値
そして、OpenAccessConnection の中で、ConfigDb から値を読むようにします。
Private Function GetDbConfig(ByVal keyName As String) As String
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("ConfigDb")
Dim rng As Range
Set rng = ws.Range("A:A").Find(What:=keyName, LookAt:=xlWhole)
If rng Is Nothing Then
GetDbConfig = ""
Else
GetDbConfig = CStr(rng.Offset(0, 1).Value)
End If
End Function
Public Function OpenSqlServerConnection() As Object
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
Dim connStr As String
connStr = "Provider=" & GetDbConfig("Provider") & ";" & _
"Data Source=" & GetDbConfig("Server") & ";" & _
"Initial Catalog=" & GetDbConfig("Database") & ";" & _
"User ID=" & GetDbConfig("User") & ";" & _
"Password=" & GetDbConfig("Password") & ";"
conn.Open connStr
Set OpenSqlServerConnection = conn
End Function
VBこうしておけば、「接続先が変わったときは ConfigDb の値だけ変えればいい」という状態になります。
DB連携テンプレを“実務で回る仕組み”にするうえで、ここはかなり重要なポイントです。
例題:DBから取得→Excelで加工→DBに戻す一連の流れ
シナリオ
SQL Server 上の T_Sales テーブルから売上明細を取得し、
Excelで集計やクリーニングを行い、
結果を T_SalesSummary テーブルに書き戻す——という一連の流れを、テンプレで組み立ててみます。
1. 明細を取得してシートに展開
Sub LoadSalesFromDb()
Dim sql As String
sql = "SELECT SalesDate, CustomerCode, Amount " & _
"FROM T_Sales " & _
"WHERE SalesDate BETWEEN '2025-01-01' AND '2025-01-31'"
RunSelectToSheet sql, "SalesRaw", "A1"
End Sub
VB2. Excel側で集計(ここはこれまでの配列・辞書テンプレを使う)
ここは、すでに作った「辞書×配列の集計テンプレ」を使うイメージです。
顧客別合計を SalesAgg シートに出す、など。
3. 集計結果をDBにINSERT
Sub UploadSalesSummaryToDb()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("SalesAgg")
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
If lastRow < 2 Then Exit Sub
Dim i As Long
For i = 2 To lastRow
Dim cust As String
Dim totalAmt As Double
cust = Replace(CStr(ws.Cells(i, 1).Value), "'", "''")
If IsNumeric(ws.Cells(i, 2).Value) Then
totalAmt = CDbl(ws.Cells(i, 2).Value)
Else
totalAmt = 0
End If
Dim sql As String
sql = "INSERT INTO T_SalesSummary (CustomerCode, TotalAmount) " & _
"VALUES ('" & cust & "', " & CStr(totalAmt) & ")"
ExecuteNonQuery sql
Next i
End Sub
VBこのように、「DB→Excel→DB」の往復も、
接続・SELECT・更新をテンプレ化しておけば、業務ロジックだけに集中して組み立てられます。
重要ポイントの深掘り:DB連携テンプレを“怖くないもの”にする
例外(エラー)処理と切断を必ずセットにする
DB連携で一番やってはいけないのは、「エラーが出たときに接続を開きっぱなしにする」ことです。
理想は、共通のラッパを用意して、こういう形にしておくことです。
Public Sub SafeRunSelectToSheet( _
ByVal sql As String, _
ByVal targetSheetName As String, _
Optional ByVal startCellAddress As String = "A1")
On Error GoTo ErrHandler
Dim conn As Object
Set conn = OpenAccessConnection()
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
rs.Open sql, conn, 1, 1
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(targetSheetName)
ws.Range(startCellAddress).CurrentRegion.Clear
ws.Range(startCellAddress).CopyFromRecordset rs
rs.Close
conn.Close
Exit Sub
ErrHandler:
On Error Resume Next
If Not rs Is Nothing Then
If rs.State <> 0 Then rs.Close
End If
If Not conn Is Nothing Then
If conn.State <> 0 Then conn.Close
End If
MsgBox "DB処理中にエラーが発生しました。", vbExclamation
End Sub
VB「エラーが起きても必ず Close する」という型を一度作ってしまえば、
あとはこのラッパを使うだけで安全性がぐっと上がります。
SQLは「文字列を組み立てる」ことに慣れる
VBAからDBを触るとき、避けて通れないのが「SQL文字列の組み立て」です。
初心者がつまずきやすいポイントは、主にここです。
日付や文字列をシングルクォートで囲む
文字列中のシングルクォートを '' にエスケープする
WHERE句の条件を & でつなぐ
最初は少し面倒に感じますが、
「SQLはただの文字列」「VBAでその文字列を作っているだけ」と割り切ると、だんだん慣れてきます。
「Excelでやるべきこと」と「DBに任せるべきこと」を分ける
DB連携テンプレを使い始めると、「全部Excelでやる」か「全部DBでやる」か、極端になりがちです。
現実的には、こう分けるのがおすすめです。
大量データの絞り込み・集計・JOIN:できるだけDB側のSQLでやる
見せ方の調整・レイアウト・細かい加工:Excel側でやる
この線引きを意識すると、「DBはエンジン、Excelはフロント」という役割分担がはっきりして、
全体の設計がすっきりします。
まとめ:DB連携テンプレは「接続・SELECT・更新・設定シート」を型にすること
今日のDB連携テンプレを一言でまとめると、こうなります。
接続ヘルパー(Open○○Connection)を1つ作る
SELECT用の RunSelectToSheet(または SafeRunSelectToSheet)を持つ
更新用の ExecuteNonQuery を持つ
接続情報は ConfigDb シートに逃がす
この“4点セット”さえ一度作ってしまえば、
「このテーブルをExcelに持ってきたい」「この集計結果をDBに戻したい」といった要望に、
落ち着いて、同じパターンで応えられるようになります。
