VB.NETからAccessデータベースのレコードを削除する
DataGridView に読み込んだ、Accessのデータベースをいじっていきます! 今回はレコードの削除についてです。
関連記事
- DataGridViewへAccessのデータベースファイルを読み込む
- AccessDBテーブルの主キー情報を取得する
- DataGridViewに読み込んだDB情報を再取得する
- DataGridViewをセル編集したときの行数を格納する
- Accessのデータベースファイルへ書き込むための接続・切断
- Accessデータベースのレコードを削除する ←NOW!
- Accessデータベースを更新する
ガッツリ続き物になってしまいました…。過去の分と合わせて順番に読んでいただけると分かりやすいかと思います。
なるべく簡素に書いているので、例外処理は甘いと思われます。ご参考にする際は、ご自分の環境に合わせてご修正ください。
解説のためツギハギしちゃったので、最後の記事(7回め)に全コードまとめてあります。書いたときの環境
- Visual Studio 2010
- .NET Framework 4.0
です。
コード
図のようにどこかが選択されているとして、その行を削除します。
Form2.vb
前回のButton3のクリックイベントを拡張します。
'### Form2.vb ### Public Class Form2 '略 '---------------------------------------------------- ' メソッド '---------------------------------------------------- '略 '---------------------------------------------------- ' Formイベント '---------------------------------------------------- '略 '---------------------------------------------------- ' Buttonクリックイベント '---------------------------------------------------- Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click '再読込ボタン(Button1)クリック時(略) End Sub Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click '保存ボタン(Button2)クリック時(略) End Sub Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click '削除ボタン(Button3)クリック時 '未保存データ確認 If list.hasUpdateList = True Or list.hasInsertList = True Then MessageBox.Show("編集中のデータがあります。先に「保存」か「再読込」を行なってください。") Exit Sub End If 'どこも選択されていない場合 If dgv.CurrentCellAddress.X = -1 Then MessageBox.Show("削除したい行を選択してください。", "確認", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Exit Sub End If '削除前確認 DataGridView1.CurrentRow.Selected = True '対象行をすべて選択 If MessageBox.Show("選択されている行のデータを削除します。よろしいですか?", "確認", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) <> 1 Then Exit Sub End If 'DELETEのSQL文リストを取得 Dim sqlList As New List(Of String) sqlList = db.getDeleteSql(dgv.CurrentRow.Index) 'SQLを実行() If db.runSQL(sqlList) = True Then '成功したら '再読込 db.Dispose() Call setTable() 'メッセージ MessageBox.Show("削除しました。") End If End Sub '---------------------------------------------------- ' DataGridViewイベント '---------------------------------------------------- '略 End Class
編集中のデータがあったり、どこも選択されていなかったりなど例外処理をしてから、確認メッセージを出して処理に入ります。
49行目、getDeleteSql
を呼び出して DELETE 文を生成します。前回、複数処理を踏まえて型を List にしたので、DELETE 文も List 型になるように作ります。
2018/5/31追記:新規行が選択されていた場合
コメント欄でご指摘いただいて、新規行(最後の*行)を選択してるときに「削除」ボタンを押すと、1つ前の行(データが入っている最終行)がにフォーカスが移ってしまうのに気がつきました。IsNewRow 関数使えないのかなと思ったのですがどうにも False になってしまう…、なぜだ…。。と、検証していろいろ調べてみたところ、こちらのサイトで原因と解決方法を知ることができました。
どうやら DataGridView のデフォルトの仕様として、今回のような場合はフォーカスはそのまま、カレントは新規行-1の位置に戻ってしまうらしいんですね。このおかげで IsNewRow 関数も False になってしまうという…。
それで上記サイトに記載されていたとおり、DataGridView の CausesValidation プロパティを True にしたら、IsNewRow が True で取得することができました!
というわけで、その設定にしてから、上記コードの 35 ~ 39 行目のチェック条件に以下のように付け足すことで、新規行が選択されていたときも検出して中断することができます。
'どこも選択されていない場合 If dgv.CurrentCellAddress.X = -1 Or dgv.CurrentRow.IsNewRow Then MessageBox.Show("削除したい行を選択してください。", "確認", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) Exit Sub End If
追記はここまでです。お試しください。
DBtable.vb
DELETE 文を生成するために、いろいろ関数を書いていきます。
'### DBtable.vb ### Imports System.Data.OleDb Class DBtable '略 '---------------------------------------------------- ' テーブルに関すること '---------------------------------------------------- '略 '---------------------------------------------------- ' SQL文生成に関すること '---------------------------------------------------- Public Function getDeleteSql(ByVal targetRow As Integer) As List(Of String) 'DELETE文生成 Dim list As New List(Of String) Dim strSQL As String 'DELETE句 strSQL = "DELETE FROM " & tableName 'WHERE句 strSQL &= getWhereTxt(targetRow) 'WHERE句を足す list.Add(strSQL) 'リストに追加 Return list End Function Private Function getWhereTxt(ByVal targetRow As Integer) As String 'WHERE句生成 Dim encloseTxt As String Dim whereTxt As String = "" For Each clm In primaryKeyArray '主キーの列をループ If clm.Ordinal = 0 Then whereTxt = " WHERE " Else '主キーがふたつ以上ある場合 whereTxt &= " AND " End If Dim TypeName As String = tableData.Columns(clm.Ordinal).DataType.Name '主キーの型タイプ encloseTxt = getEncloseTxt(TypeName) '囲み文字を取得 whereTxt &= dgv.Columns(clm.Ordinal).HeaderCell.Value & "=" & encloseTxt & dgv.Rows(targetRow).Cells(clm.Ordinal).Value & encloseTxt Next Return whereTxt End Function Private Function getEncloseTxt(ByVal TypeName As String) As String '囲み文字の判定 Dim encloseTxt As String Select Case TypeName Case "String" encloseTxt = "'" Case "DateTime" encloseTxt = "#" Case Else encloseTxt = "" End Select Return encloseTxt End Function End Class
15行目、getDeleteSql
という関数で DELETE 文を List 型に入れて返します。SQL の WHERE 句を生成する処理は、他でも使えるのでそこも関数にして23行目で呼び出しています。
30行目が、WHERE 句を生成して取得するgetWhereTxt
関数です。主キーとなるフィールドの数だけ組み立てます。このとき、型によって囲み文字(文字列なら「’」とか)が違うので、そこを判定する関数も別に作って42行目で呼び出しています。
49行目が、囲み文字を取得するgetEncloseTxt
関数です。と言っても文字列型と日付型しか処理してませんが…。例外が出てきたらここに追記かなー。
動作確認
ここまでコードを書いてから動かしてみます。
ひとつ選んで削除ボタンを押し、
確認メッセージをOKしてみると、
レコードが削除され、DataGridView が再読込されました。
以上です! 次回、UPDATE と INSERT を実装してひととおり終わりにするつもりですー!
2件のコメント
データ保存後に、最終行の※のセルを選択して、削除ボタンをクリックすると
※の1つ前のデータが削除として選択されます。
DataGridView1.CurrentRow.Selected = Trueの箇所で、選択行を判断してい
箇所に何か条件を追加する必要があるようです。
y.yさん細かく検証していただいてありがとうございます。ホントですね! 対処方法を本文に追記しましたのでご参照ください。
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。