サイトアイコン あきらちんの技術メモ

EXCEL VBAでSQL文を使う

EXCEL VBAでSQL文を使って集計するでは、SELECT文を利用できましたが、INSERTやUPDATEにDELETEなどは利用できるのか試してみました。

集計で利用したEXCELシートにボタンを3つ追加してみました。

以下がテーブルになります。

INSERT文

「INSERT」ボタンが押されたときにデータを1件追加するようにしました。

7/20の日付でZさんが追加される予定です。

Private Sub cmdInsert_Click()
    Dim cn As ADODB.Connection
    Dim xl_file As String
    Dim sql As String
    Dim curRow As Integer

    xl_file = ThisWorkbook.FullName
    
    Set cn = New ADODB.Connection
    cn.Provider = "MSDASQL"
    #If Win64 Then
        ' 64bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #Else
        ' 32bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #End If
    cn.Open

    sql = "INSERT INTO [Sheet1$] " _
        & "  (日付, 名前, 勤務時間, 時給)" _
        & "  VALUES" _
        & "  ('2020/07/20', 'Zさん', 8, 850)"
    cn.Execute sql


    On Error Resume Next
    cn.Close
    Set cn = Nothing

End Sub

INSERTボタンを押してから、Sheet1を表示したら一番下に追加されておりました。

UPDATE文

「UPDATE」ボタンが押されたときにZさんデータが更新されるようにしました。

勤務時間が8から10に更新される予定です。

Private Sub Private Sub cmdUpdate_Click()
    Dim cn As ADODB.Connection
    Dim xl_file As String
    Dim sql As String
    Dim curRow As Integer

    xl_file = ThisWorkbook.FullName
    
    Set cn = New ADODB.Connection
    cn.Provider = "MSDASQL"
    #If Win64 Then
        ' 64bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #Else
        ' 32bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #End If
    cn.Open

    sql = "UPDATE [Sheet1$] " _
        & "  SET 勤務時間=10" _
        & "  WHERE 日付=#2020/07/20# AND 名前='Zさん'"
    cn.Execute sql


    On Error Resume Next
    cn.Close
    Set cn = Nothing
End Sub

UPDATE ボタンを押してから、Sheet1を表示したら一番下のZさんの勤務時間が更新されておりました。

DELETE文

「DELETE」ボタンが押されたときにZさんデータが削除されるようにしました。

Private Sub Private Sub cmdDelete_Click()
    Dim cn As ADODB.Connection
    Dim xl_file As String
    Dim sql As String
    Dim curRow As Integer

    xl_file = ThisWorkbook.FullName
    
    Set cn = New ADODB.Connection
    cn.Provider = "MSDASQL"
    #If Win64 Then
        ' 64bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #Else
        ' 32bit
        cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls)};" & "DBQ=" & xl_file & "; ReadOnly=False;"
    #End If
    cn.Open

    sql = "DELETE FROM [Sheet1$] " _
        & "  WHERE" _
        & "  日付=#2020/07/20# AND 名前='Zさん'"
    cn.Execute sql
    
    On Error Resume Next
    cn.Close
    Set cn = Nothing

End Sub

エラーメッセージが表示され削除出来ませんでした。

「 このISAMでは、リンクテーブル内のデータを削除することはできません。 」

とりあえずUPDATE文で全ての項目にnullをセットして更新するしかないかも。

更新後は空の行として残ってしまうのでソートして最下行に移動させる様にします。

その後、追加すると空行の次にデータが追加されるのでもう一工夫します。

空行を削除してしまえば良いのですが、削除データが複数レコードになる場合も想定し、ソートして最下行になった空行からデータの範囲選択( CTRL+SHIFT+ENDキーを押したときの動き)して取得できた最終行までを削除します。

Private Sub Private Sub cmdDelete_Click()
    Dim cn As ADODB.Connection
    Dim xl_file As String
    Dim sql As String
    Dim curRow As Integer
    Dim lastRow As Integer
xl_file = ThisWorkbook.FullName Set cn = New ADODB.Connection cn.Provider = "MSDASQL" #If Win64 Then ' 64bit cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & "DBQ=" & xl_file & "; ReadOnly=False;" #Else ' 32bit cn.ConnectionString = "Driver={Microsoft Excel Driver (*.xls)};" & "DBQ=" & xl_file & "; ReadOnly=False;" #End If cn.Open ' sql = "DELETE FROM [Sheet1$] " _ ' & " WHERE" _ ' & " 日付=#2020/07/20# AND 名前='Zさん'" ' cn.Execute sql sql = "UPDATE [Sheet1$] " _ & " SET 日付=null, 名前=null, 勤務時間=null, 時給=null, 給料=null" _ & " WHERE 日付=#2020/07/20# AND 名前='Zさん'" cn.Execute sql Sheets("Sheet1").Select Sheets("Sheet1").Range("A1").Select Sheets("Sheet1").Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("A2:A16") _ , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Add2 Key:=Range("B2:B16") _ , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal With ActiveWorkbook.Worksheets("Sheet1").Sort .SetRange Range("A1:E16") .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With Sheets("Sheet1").Range("A1").Select ' 空ではない最終行 Selection.End(xlDown).Select ' 次の行の行番号 curRow = ActiveCell.Row + 1 ' 次の行のセル選択 Sheets("Sheet1").Range("A" & curRow).Select ' CTRL+SHIFT+ENDキーを押したときの範囲選択 Sheets("Sheet1").Range(Selection, ActiveCell.SpecialCells(xlLastCell)).Select ' 選択行の最終行アドレスを取得 lastRow = Selection.Cells.Rows.Count + curRow - 1 ' 空行の先頭から最終行の行選択 Sheets("Sheet1").Rows(curRow & ":" & lastRow).Select ' 行削除を実施 Selection.Delete Shift:=xlUp Sheets("Sheet1").Range("A1").Select Sheets("Sheet2").Select On Error Resume Next cn.Close Set cn = Nothing End Sub

これでなんちゃって削除が動くようになりました。

ソートしたくない場合は、ループで回して空行を見つけたら削除するような仕組みが必要だと思います。

 

モバイルバージョンを終了