none
レコードにNull値があるか調べる方法 RRS feed

  • 質問

  • 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の中にあるか調べて、メッセージを表示するにはどのような手法があるのでしょうか?教えてください、よろしくお願いします。

    2007年1月8日 14:36

回答

  • CellValidatingやRowValidatingでチェックするのが良いと思います。CellValidatingは新規行の場合は使えないので、もし新規行があり得るのであれば、RowValidatingにしぼって、そこでチェックすれば良いでしょう。以下にサンプルがありますが、IsCurrentRowDirtyの場合だけチェックするようにした方がいいように思います。ちょっと今確かめられませんが、DataGridViewが表示される時にも、無条件でRowValidatingが発生した気がします。(未確認)

    DataGridView.RowValidating イベント 
    http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.datagridview.rowvalidating(VS.80).aspx

    2007年1月8日 16:41
    モデレータ
  • >赤色のところで、「セル値の変更をコミットまたは中止できないため、操作は成功しませんでした。」とエラー表示されてしまいます。

    これは当然ですね。
    今の行の検証に失敗しているから次の行の先頭列に移動しようとすると例外が発生します。
    想定される例外はTry/Catchで捕捉してしかるべき処置(次の行の先頭列に移動させないまま戻るとか)しなければいけません。

    2007年1月9日 7:00
  •  bykyo さんからの引用

    Try/Catchの位置を色々変えてみたのですが、うまくいきませんでした。e.Cancelを行う前に、セルの位置をエラーが発生した行に戻せばよいのでしょうか?

    それでいいと思いますよ。最終行は次の行が無いので、最終行の場合はそのセルに留まるか、1行目(それが最終行の可能性もある)の最初のセルに戻すような感じ(要は巡回する)にしてしまえばいいのではないでしょうか?

    2007年1月10日 0:59
    モデレータ
  • >try/catchでエラー捕捉しようと思ったのですが、なぜか捕らえられません

    あれ、エラーが発生するところをTry/Catchしないといみがありませんよ。
    RowValidatingではエラーが発生していないんですよね。

    カレントセルを移動させるところでTry/Catchしてください。

    2007年1月10日 5:55

すべての返信

  • CellValidatingやRowValidatingでチェックするのが良いと思います。CellValidatingは新規行の場合は使えないので、もし新規行があり得るのであれば、RowValidatingにしぼって、そこでチェックすれば良いでしょう。以下にサンプルがありますが、IsCurrentRowDirtyの場合だけチェックするようにした方がいいように思います。ちょっと今確かめられませんが、DataGridViewが表示される時にも、無条件でRowValidatingが発生した気がします。(未確認)

    DataGridView.RowValidating イベント 
    http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.datagridview.rowvalidating(VS.80).aspx

    2007年1月8日 16:41
    モデレータ
  • RowValidatingですが、DataGridViewが表示される時には発生しませんでした。すみません。気のせいでした。(^^;
    しかし、行が変更されていなくても、行を移る時に発生しますので、やはり、IsCurrentRowDirtyで判断した方が良いと思います。
    2007年1月9日 1:05
    モデレータ
  • trapemiyaさま、返信ありがとうございました。

    一応、下のコードでエラー表示できるようになったのですが、一番最後の列を空白にしてエンターキーを押したときにエラー表示されたあと、InvalidOperationExceptionエラーが発生します。セルをエンターキーで横移動するDataGridViewの作成法が公開されていたので、それを使用しています。回避策はあるのでしょうか?

    セルに値があるかどうか判定する。 _コードDG1は、DataGridViewを継承したエンターキーでカーソルが横移動するコントロールです。

     Private Sub _コードDG1_RowValidating _
        (ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) _
        Handles _コードDG1.RowValidating

            If _コード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.Empty

                    End 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

    の赤色のところで、「セル値の変更をコミットまたは中止できないため、操作は成功しませんでした。」とエラー表示されてしまいます。本題からズレてしまい、申し訳ありませんが、何か解決策がありましたらご教示いただけませんでしょうか?

     

     

    2007年1月9日 4:38
  • >赤色のところで、「セル値の変更をコミットまたは中止できないため、操作は成功しませんでした。」とエラー表示されてしまいます。

    これは当然ですね。
    今の行の検証に失敗しているから次の行の先頭列に移動しようとすると例外が発生します。
    想定される例外はTry/Catchで捕捉してしかるべき処置(次の行の先頭列に移動させないまま戻るとか)しなければいけません。

    2007年1月9日 7:00
  • えむナウさま、返信ありがとうございました。

    try/catchでエラー捕捉しようと思ったのですが、なぜか捕らえられません

      Private Sub _コードDG1_RowValidating _
        (ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) _
        Handles _コードDG1.RowValidating

    Try
                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.Empty

                        End If
                    Next

                End If
            Catch ex As Exception
                MessageBox.Show(ex.Message, "項目確認")

            End Try

    Try/Catchの位置を色々変えてみたのですが、うまくいきませんでした。e.Cancelを行う前に、セルの位置をエラーが発生した行に戻せばよいのでしょうか?なんだか色々やってるうちにわからなくなってきました。ヒントでも良いのでアドバイスいただけませんでしょうか?

    2007年1月9日 14:59
  •  bykyo さんからの引用

    Try/Catchの位置を色々変えてみたのですが、うまくいきませんでした。e.Cancelを行う前に、セルの位置をエラーが発生した行に戻せばよいのでしょうか?

    それでいいと思いますよ。最終行は次の行が無いので、最終行の場合はそのセルに留まるか、1行目(それが最終行の可能性もある)の最初のセルに戻すような感じ(要は巡回する)にしてしまえばいいのではないでしょうか?

    2007年1月10日 0:59
    モデレータ
  • >try/catchでエラー捕捉しようと思ったのですが、なぜか捕らえられません

    あれ、エラーが発生するところをTry/Catchしないといみがありませんよ。
    RowValidatingではエラーが発生していないんですよね。

    カレントセルを移動させるところでTry/Catchしてください。

    2007年1月10日 5:55
  • 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”というのを知らなかったので、良い勉強になりました。また見かけた際にはよろしくお願いします。この度はありがとうございました。

     

     

    2007年1月10日 11:29