1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Excel VBA : ループ処理で任意の数のテーブルをマージするSQLを作成

Last updated at Posted at 2023-01-24

はじめに

Excel VBAを用いてSQL文を実行し、
シート上のテーブルを結合する方法について紹介します。
(未だ制限の多い関数となっており、さらなる改良が必要です。詳しい方がいらっしゃれば、是非ご教授ください。)

「master」と「tbl_one」「tbl_two」「tbl_three」をマージしています。
image.png

コードの細かい部分は以下をご参照ください。

VBA

関数の準備

Public Function sql_master_left_join(ByVal sheetname As String, _
                                                            ByVal masterName As String, ByVal tblNames As Variant, _
                                                            ByVal leftcol As String, ByVal rightcol As String) As String
        '''
        ' 「マスタテーブルの名前」、「結合するテーブル名が格納された配列」、「結合につかうカラム名」を受けて、
        ' LEFT JOINするSQL文を作成
        '
        ' Parameters
        ' ------------
        ' sheetname: 各種テーブルが配置されたシートの名前(今回は同じシート上にテーブルがある想定)
        ' masterName: マスタとなるテーブルの名前(特になければ、結合するテーブル・カラムの値のユニークな値で作る?)
        ' tblNames: 結合するテーブルを格納した配列
        ' leftcol: 結合で使用するカラム名(マスタ側)
        ' rightcol: 結合で使用するカラム名(結合されるテーブル側)
        '
        ' Returns
        ' --------
        ' SQL文. String
        '''
        Dim strSQL As String ' 最終的に得られるSQL文
        Dim selectSQL As String 'ループ処理で作成するSQLのパーツ①
        Dim frombraSQL As String 'ループ処理で作成するSQLのパーツ②
        Dim frombodySQL As String 'ループ処理で作成するSQLのパーツ③
        
        Dim i As Integer
        i = 1
        
        ''(1)初期値を設定(ループ処理で更新していく)
        '' SELECTの部分
        selectSQL = "SELECT " & masterName & ".*, "
        
        '' 複数くっつける際に使うFROMの前のbra(cket)
        frombraSQL = "["
        
        '' FROMの中身
        frombodySQL = Worksheets(sheetname).ListObjects(masterName).Range.Address(False, False) & "] as " & masterName & " "
        
        '' (2)ループ処理で初期値を更新していく
        Dim tblName As Variant
        For Each tblName In tblNames
            '' テーブルを格納した配列における最初、真ん中、最後で処理を分岐
            
            '' 最初
            If i = 1 Then
                ' SELECT
                selectSQL = selectSQL & tblName & "." & rightcol & ", "
                
                ' FROMの前のbracket
                frombraSQL = "(" & frombraSQL
                
                ' FROMの中身
                frombodySQL = frombodySQL & "LEFT JOIN "  '今回はLEFT JOIN
                frombodySQL = frombodySQL & "[" & Worksheets(sheetname).ListObjects(tblName).Range.Address(False, False)
                frombodySQL = frombodySQL & "] as " & tblName & " "
                frombodySQL = frombodySQL & "ON "
                frombodySQL = frombodySQL & masterName & "." & leftcol & " = " & tblName & "." & leftcol
                
            '' 真ん中
            ElseIf i <> UBound(tblNames) - LBound(tblNames) + 1 Then
                ' SELECT
                selectSQL = selectSQL & tblName & "." & rightcol & ", "
                
                ' FROMの前のbracket
                frombraSQL = "(" & frombraSQL
                
                ' FROMの中身
                frombodySQL = frombodySQL & ")LEFT JOIN "
                frombodySQL = frombodySQL & "[" & Worksheets(sheetname).ListObjects(tblName).Range.Address(False, False)
                frombodySQL = frombodySQL & "] as " & tblName & " "
                frombodySQL = frombodySQL & "ON "
                frombodySQL = frombodySQL & masterName & "." & leftcol & " = " & tblName & "." & leftcol
            
            '' 最後
            Else
                'SELECT
                selectSQL = selectSQL & tblName & "." & rightcol & " "
                
                ' FROMの前のbracket
                frombraSQL = "(" & frombraSQL
                
                ' FROMの中身
                frombodySQL = frombodySQL & ")LEFT JOIN "
                frombodySQL = frombodySQL & "[" & Worksheets(sheetname).ListObjects(tblName).Range.Address(False, False)
                frombodySQL = frombodySQL & "] as " & tblName & " "
                frombodySQL = frombodySQL & "ON "
                frombodySQL = frombodySQL & masterName & "." & leftcol & " = " & tblName & "." & leftcol & ")"
                
            End If
            i = i + 1
        Next
        
        '' 結合
        strSQL = ""
        strSQL = strSQL & selectSQL
        strSQL = strSQL & "FROM "
        strSQL = strSQL & frombraSQL
        strSQL = strSQL & frombodySQL
                                    
        sql_master_left_join = strSQL
End Function

実行

Sub run_left_join()
    '' ■sql_master_left_joinを実行し、「master」「tbl_one」「tbl_two」「tbl_three」をマージして出力
    
    ''(1)SQL文の作成
    Dim strSQL As String
    Dim masterName As String
    Dim tblNames() As Variant
    Dim sheetname As String
    Dim leftcol As String
    Dim rightcol As String
    
    sheetname = "Sheet1"
    masterName = "master"
    tblNames = Array("tbl_one", "tbl_two", "tbl_three")
    leftcol = "名前"
    rightcol = "体重"
    
    strSQL = sql_master_left_join(sheetname, masterName, tblNames, leftcol, rightcol)
    
    ''(2)接続
    Dim objCn As ADODB.Connection
    Set objCn = New ADODB.Connection
    With objCn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .Properties("Extended Properties") = "Excel 12.0 Macro; data sorce= "
        .Open ThisWorkbook.FullName '現在のワークシート上
    End With

    ''(3)読み込み
    Dim objRS As ADODB.Recordset
    Set objRS = New ADODB.Recordset
    objRS.Open strSQL, objCn, adOpenStatic
    
    ''(4)出力
    With Worksheets(sheetname)
        .Range(.Cells(10, 2), .Cells(10 + .ListObjects(masterName).ListRows.Count - 1, 2 + UBound(tblNames) - LBound(tblNames) + 1)) = objRS.GetRows()
    End With
    
    ''(5)閉じる
    objRS.Close
    Set objRS = Nothing
    
    objCn.Close
    Set objCn = Nothing
End Sub

さいごに

まだまだ実用に耐えない関数ですが、皆さんのご意見いただければと思い投稿させていただきました。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?