トップ回答者
レコードにNull値があるか調べる方法

質問
-
VB2005&ACCESS2000でWinアプリを開発しています。今回もよろしくお願いします。
DataGridViewにデータテーブルの検索結果を表示し、追加・編集を行っているのですが、保存するときに、DataGridViewに入力していないセルがあるかどうか調べるにはどのようにすれば良いのでしょうか?
カレント行のセルは保存するときに、
Dim drv As DataRowView
drv = CType(_11コードBindingSource.Current, DataRowView)If drv(1) Is DBNull.Value Then
MessageBox.Show("コードが入力されていません", "コード登録")
_11コードBindingSource.CancelEdit()という処理を、drv(2)から(9)まで行って、メッセージを表示しています。ですが、ユーザーが複数の行でセルの内容を削除したような場合、カレント行でないセルがNull値になるのでそのまま保存してしまいます。Null値のセルがDataGridViewの中にあるか調べて、メッセージを表示するにはどのような手法があるのでしょうか?教えてください、よろしくお願いします。
回答
-
CellValidatingやRowValidatingでチェックするのが良いと思います。CellValidatingは新規行の場合は使えないので、もし新規行があり得るのであれば、RowValidatingにしぼって、そこでチェックすれば良いでしょう。以下にサンプルがありますが、IsCurrentRowDirtyの場合だけチェックするようにした方がいいように思います。ちょっと今確かめられませんが、DataGridViewが表示される時にも、無条件でRowValidatingが発生した気がします。(未確認)
DataGridView.RowValidating イベント
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.datagridview.rowvalidating(VS.80).aspx
すべての返信
-
CellValidatingやRowValidatingでチェックするのが良いと思います。CellValidatingは新規行の場合は使えないので、もし新規行があり得るのであれば、RowValidatingにしぼって、そこでチェックすれば良いでしょう。以下にサンプルがありますが、IsCurrentRowDirtyの場合だけチェックするようにした方がいいように思います。ちょっと今確かめられませんが、DataGridViewが表示される時にも、無条件でRowValidatingが発生した気がします。(未確認)
DataGridView.RowValidating イベント
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.datagridview.rowvalidating(VS.80).aspx -
trapemiyaさま、返信ありがとうございました。
一応、下のコードでエラー表示できるようになったのですが、一番最後の列を空白にしてエンターキーを押したときにエラー表示されたあと、InvalidOperationExceptionエラーが発生します。セルをエンターキーで横移動するDataGridViewの作成法が公開されていたので、それを使用しています。回避策はあるのでしょうか?
セルに値があるかどうか判定する。 _コードDG1は、DataGridViewを継承したエンターキーでカーソルが横移動するコントロールです。
Private Sub _コードDG1_RowValidating _
(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) _
Handles _コードDG1.RowValidatingIf _コードDG1.IsCurrentRowDirty = True Then
Dim i As Integer = Me._コードDG1.ColumnCount
Dim c As Integer
For c = 0 To i - 1
If _コードDG1(c, e.RowIndex).Value.ToString().Length = 0 Then
_コードDG1.Rows(e.RowIndex).ErrorText = "入力してください"
MessageBox.Show("入力項目が空欄です。入力してください")
e.Cancel = True
Else
_コードDG1.Rows(e.RowIndex).ErrorText = String.EmptyEnd If
Next
End If
End Sub継承コントロールは下記のサイトを参考に、そのままコードをコピーして作りました。
http://www.vbstation.net/tips/inherits_control.htm
ページの一番下の、独自機能を実装という欄のコードの
Public Shadows Function ProcessRightKey(ByVal keyData As Keys) As Boolean
If (keyData And Keys.KeyCode) = Keys.Enter Then
''最終列の場合に次の行の先頭列に移動
If MyBase.CurrentCell.ColumnIndex = MyBase.ColumnCount - 1 _
And MyBase.CurrentCell.RowIndex + 1 <= MyBase.RowCount - 1 Then
MyBase.CurrentCell = MyBase.Rows((MyBase.CurrentCell.RowIndex + 1)).Cells(0)
Return True
End If
End If
Return MyBase.ProcessRightKey(keyData)
End Functionの赤色のところで、「セル値の変更をコミットまたは中止できないため、操作は成功しませんでした。」とエラー表示されてしまいます。本題からズレてしまい、申し訳ありませんが、何か解決策がありましたらご教示いただけませんでしょうか?
-
えむナウさま、返信ありがとうございました。
try/catchでエラー捕捉しようと思ったのですが、なぜか捕らえられません
Private Sub _コードDG1_RowValidating _
(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) _
Handles _コードDG1.RowValidatingTry
If _11DG1.IsCurrentRowDirty = True Then
Dim i As Integer = Me._コードDG1.ColumnCount
Dim c As Integer
For c = 0 To i - 1
If _コードDG1(c, e.RowIndex).Value.ToString().Length = 0 Then
_コードDG1.Rows(e.RowIndex).ErrorText = "入力してください"
MessageBox.Show("入力項目が空欄です。入力してください ")
e.Cancel = True
Else
_コードDG1.Rows(e.RowIndex).ErrorText = String.EmptyEnd If
NextEnd If
Catch ex As Exception
MessageBox.Show(ex.Message, "項目確認")End Try
Try/Catchの位置を色々変えてみたのですが、うまくいきませんでした。e.Cancelを行う前に、セルの位置をエラーが発生した行に戻せばよいのでしょうか?なんだか色々やってるうちにわからなくなってきました。ヒントでも良いのでアドバイスいただけませんでしょうか?
-
trapemiyaさま、えむナウさま、返信ありがとうございました。
アドバイスにありましたとおり、 e.Cancel = True の手前で、セルを進めないようにしたり、エラーをキャッチして色々と試してデバッグした結果、空白のセルがある行から他の行に移動できないのは、入力のときに不便な点があったので、 e.Cancel = Trueを実行せずに、ErrorTextのみを表示するようにして、保存ボタンを押したときに、ErrorTextの表示がある場合は保存処理(更新)を行わないような処理にしました。
保存ボタンをクリックしたら、
Dim dr As DataGridViewRow
For Each dr In Me._コードDG1.Rows
If dr.ErrorText = String.Empty Thenデータの更新処理・・・
というような感じにしました。たくさんアドバイスをくださってありがとうございました。これで行にNull値があるかどうか調べられるようになったのでとてもうれしいです。”RowValidating”というのを知らなかったので、良い勉強になりました。また見かけた際にはよろしくお願いします。この度はありがとうございました。