VBAでデータベースに接続し、テーブル定義書を作る

データベースのテーブル定義書は未だにExcelで作成をしているプロジェクトが多いかと思います。

ほとんどの場合は、「テーブル定義書を作る→テーブルを作る」という順序になるので、Excelの定義書からCreate文を作るということは多いです。

ただ、稀に「テーブル定義書は存在しない。」と言われることもあります。

その際に、自分用にテーブルのカラム一覧などを作成したことが何度かありました。

今後も同じことが起こった時の備忘として対応方法を記載しておこうと思います。

取り急ぎ、VBAでMySQLに接続し、テーブル定義を作成するという方法について記載をいたします。機会があればPostgresSQLやOracleの方法も記載します。

ODBCをインストールする

VBAからデータベースに接続する際ですが、データベースに接続するためのドライバは必ず必要になります。

今回はODBCを使用して接続をすることにします。前述したとおりMySQLに接続するための手順を記載したいと思います。

  1. 下記のMySQL公式サイトに接続し、ODBCをダウンロードします。

https://dev.mysql.com/downloads/connector/odbc/

使用しているPCのOSとExcelのBit数に合致しているインストーラをダウンロードします。

自分の場合は、WindowsでExcel64Bitなので下記になります。

2.オラクルアカウントでログインするように促されますが、下部の「No thanks,just start my download」をクリックすればログインせずに続行できます。

3.ダウンロードしたインストーラを使用してODBCのインストールを行います。

4.セットアップタイプはComplateでいいかなと思います。(Customを選んでも結局ODBCしかインストールするものがないので、どれを選んでも同じかと思います。)

5.Windowsロゴ横の検索窓に「ODBC」と入力すると、ODBCデータソースがヒットするので、使用しているExcelと同じビット数のほうを開きます。(64Bit版Excelであれば64Bitのほうを開く)

6.追加をクリックします。

7.MySQL ODBC Unicode Driverを選択します。

8.DBの接続情報を入力してOKボタンをクリックします。ここでData Source Name設定した名前は、後で使うので控えておきます。

これでODBC接続の準備は完了となります。

VBAでデータベースのテーブル一覧を取得する

ODBCの準備ができたので、早速VBAからデータベースに接続していきたいと思います。

下準備として、VBEのツール→参照設定から「Microsoft ActiveX Data Object 6.1 Library」にチェックを入れます。

まずは、SQLを呼び出すための関数を作成しました。

Function execute_sql(sql As String) As ADODB.Recordset
    'ODBCで作成したDNS名を使用してMySQLに接続する
    Dim cn As New ADODB.Connection
    cn.ConnectionString = "Provider=MSDASQL;DSN=MySQL;"
    cn.Open

    '引数で渡されたSQLを実行する
    Dim rs As New ADODB.Recordset
    rs.Open sql, cn
    Set execute_sql = rs
End Function

ODBCで作成した「MySQL」という接続情報を使用してデータベースに接続し、引数で渡されたSQLを実行します。

戻り値として結果のレコードセットを返します。

※作法にのっとればADODB.Connectionを閉じる必要があるのですが、関数終了時にどうせ閉じられるので、特に対応していません。

Google検索するとデータベース接続は、CreateObjectでADODBのオブジェクトを作成するコードが多いですが、やはりインテリセンスが使えるようになるのでNewしたほうが良いと思います。

次に、この上記関数を使用してテーブルの一覧を取得する関数を作成します。

Function execute_sql(sql As String) As ADODB.Recordset
    'ODBCで作成したDNS名を使用してMySQLに接続する
    Dim cn As New ADODB.Connection
    cn.ConnectionString = "Provider=MSDASQL;DSN=MySQL;"
    cn.Open

    '引数で渡されたSQLを実行する
    Dim rs As New ADODB.Recordset
    rs.Open sql, cn
    Set execute_sql = rs
End Function

Sub get_table_names()
    Dim sql As String
    
    'テーブルの一覧を取得するSQL
    sql = " SELECT table_name, table_comment"
    sql = sql + " FROM information_schema.tables"
    sql = sql + " WHERE table_schema = database();"

    'SQLの実行結果を取得する
    Dim rs As ADODB.Recordset
    Set rs = execute_sql(sql)
    
    'Sheet1に結果を書き出す
    Dim sh As Worksheet
    Set sh = ThisWorkbook.Worksheets("Sheet1")
    sh.Cells.Clear
    
    'データベースから取得したカラムの名称を1行目に書き出す
    Dim col As Long
    Dim row As Long
    row = 1
    For col = 1 To rs.Fields.Count
        sh.Cells(row, col).Value = rs.Fields(col - 1).Name
        sh.Cells(row, col).Font.Bold = True
    Next col
    row = row + 1
    
    'データベースから取得した値を2行目以降に書き出す
    Do Until rs.EOF
        For col = 1 To rs.Fields.Count
            sh.Cells(row, col).Value = rs.Fields(col - 1).Value
        Next col
        row = row + 1
        rs.MoveNext
    Loop
    
End Sub
    

このget_table_namesを実行すると、以下のようにデータベースからテーブルの一覧を取得して記載してくれるので、テーブル定義書の目次とかにします。


テーブルのカラム一覧を作成する

データベースからテーブルの一覧は作成できたので、次に個別のテーブルの定義を作成します。

テーブルの定義取得用に以下の関数を作成しました。

Function execute_sql(sql As String) As ADODB.Recordset
    'ODBCで作成したDNS名を使用してMySQLに接続する
    Dim cn As New ADODB.Connection
    cn.ConnectionString = "Provider=MSDASQL;DSN=MySQL;"
    cn.Open

    '引数で渡されたSQLを実行する
    Dim rs As New ADODB.Recordset
    rs.Open sql, cn
    Set execute_sql = rs
End Function

Sub get_table_columns()
    '取得対象のテーブル名
    Const TABLE_NAME As String = "django_admin_log"

    'テーブル定義を書き出すシートを作成する(対象テーブル名で作成)
    Dim sh As Worksheet
    Set sh = create_WorkSheet(TABLE_NAME)
    
    'カラムの一覧を取得するSQL
    Dim sql As String
    sql = " select * from INFORMATION_SCHEMA.COLUMNS "
    sql = sql & "where TABLE_SCHEMA = database() and TABLE_NAME = '" & TABLE_NAME & "'"
    
    'SQLの実行結果を取得する
    Dim rs As ADODB.Recordset
    Set rs = execute_sql(sql)
    
    'データベースから取得したカラムの名称を1行目に書き出す
    Dim col As Long
    Dim row As Long
    row = 1
    For col = 1 To rs.Fields.Count
        sh.Cells(row, col).Value = rs.Fields(col - 1).Name
        sh.Cells(row, col).Font.Bold = True
    Next col
    row = row + 1
    
    'データベースから取得した値を2行目以降に書き出す
    Do Until rs.EOF
        For col = 1 To rs.Fields.Count
            sh.Cells(row, col).Value = rs.Fields(col - 1).Value
        Next col
        row = row + 1
        rs.MoveNext
    Loop
    
End Sub

'引数で渡したシート名のワークシートを新規に作成する。(既に存在すればそのシートを返す)
Function create_WorkSheet(sheet_name As String) As Worksheet
    On Error GoTo errProc
        Set create_WorkSheet = ThisWorkbook.Worksheets(sheet_name)
    Exit Function
    
errProc:
    Err.Clear
    Set create_WorkSheet = ThisWorkbook.Worksheets.Add()
    create_WorkSheet.Name = sheet_name
End Function

Const TABLE_NAMEの定数で定義したテーブル名のカラム一覧を作成します。結果は以下のようになります。

メタ情報を含めてカラムのデータをごっそり取得することができます。

よく使いそうなカラムだけに限定するなら、物理名、論理名、カラムの種類、デフォルト、プライマリキー、NOT NULLくらいですかね。

select文でカラムを指定してあげればよいです。

Function execute_sql(sql As String) As ADODB.Recordset
    'ODBCで作成したDNS名を使用してMySQLに接続する
    Dim cn As New ADODB.Connection
    cn.ConnectionString = "Provider=MSDASQL;DSN=MySQL;"
    cn.Open

    '引数で渡されたSQLを実行する
    Dim rs As New ADODB.Recordset
    rs.Open sql, cn
    Set execute_sql = rs
End Function



Sub get_table_columns()
    '取得対象のテーブル名
    Const TABLE_NAME As String = "django_admin_log"

    'テーブル定義を書き出すシートを作成する(対象テーブル名で作成)
    Dim sh As Worksheet
    Set sh = create_WorkSheet(TABLE_NAME)
    
    'カラムの一覧を取得するSQL
    Dim sql As String
    sql = " select COLUMN_NAME,DATA_TYPE,COLUMN_TYPE,COLUMN_COMMENT,COLUMN_DEFAULT,IS_NULLABLE,COLUMN_KEY from INFORMATION_SCHEMA.COLUMNS "
    sql = sql & "where TABLE_SCHEMA = database() and TABLE_NAME = '" & TABLE_NAME & "'"
    
    'SQLの実行結果を取得する
    Dim rs As ADODB.Recordset
    Set rs = execute_sql(sql)
    
    'データベースから取得したカラムの名称を1行目に書き出す
    Dim col As Long
    Dim row As Long
    row = 1
    For col = 1 To rs.Fields.Count
        sh.Cells(row, col).Value = rs.Fields(col - 1).Name
        sh.Cells(row, col).Font.Bold = True
    Next col
    row = row + 1
    
    'データベースから取得した値を2行目以降に書き出す
    Do Until rs.EOF
        For col = 1 To rs.Fields.Count
            sh.Cells(row, col).Value = rs.Fields(col - 1).Value
        Next col
        row = row + 1
        rs.MoveNext
    Loop
    
End Sub

'引数で渡したシート名のワークシートを新規に作成する。(既に存在すればそのシートを返す)
Function create_WorkSheet(sheet_name As String) As Worksheet
    On Error GoTo errProc
        Set create_WorkSheet = ThisWorkbook.Worksheets(sheet_name)
    Exit Function
    
errProc:
    Err.Clear
    Set create_WorkSheet = ThisWorkbook.Worksheets.Add()
    create_WorkSheet.Name = sheet_name
End Function

結果


コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)