DataGridViewで三角関数を入力したいです。

タグの編集
投稿者 ひでと  (社会人) 投稿日時 2011/4/25 15:59:25
XP、Visual Studio 2005 を使用しております。
DataGridViewのセルに入力するとき三角関数を式として入力して、答えをそのセルにそのまま入力したいのです。

VBScripを使って計算式を計算する方法をネットで知り、
    Public Function Culk(ByVal expression As String) As String
        Try
            Dim exp As String = expression
            Dim t As Type = Type.GetTypeFromProgID("MSScriptControl.ScriptControl")
            Dim obj As Object = Activator.CreateInstance(t)
            t.InvokeMember("Language", Reflection.BindingFlags.SetProperty, Nothing, obj, New Object() {"vbscript"})
            Dim Result As Double = CDbl(t.InvokeMember("Eval", Reflection.BindingFlags.InvokeMethod, Nothing, obj, New Object() {exp}))
            Return Result
        Catch ex As Exception

        End Try
        Return expression
    End Function
として 文字列を計算する方法は分ったのですが、
DataGridViewのどのようなイベントを用いたら、入力後に計算できるのでしょうか?

以前 CurrentCellDirtyStateChangedイベントで編集時に計算する方法を教えていただきましたが、
このイベントだと、1文字1文字毎にイベントが発生?するようで、また編集中のセルが取得できない?ように思います。よろしくお願いいたします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/4/25 17:02:45
> Public Function Culk(ByVal expression As String) As String
Culk …… Calc ではなく? (calculate)

> Dim Result As Double = CDbl(t.InvokeMember("Eval", Reflection.BindingFlags.InvokeMethod, Nothing, obj, New Object() {exp}))
> Return Result
戻り値の型は String で、Return する値は Double なのですか?

> 入力後に計算できるのでしょうか?
表示だけの問題なら、CellPainting イベントで「計算結果」を描画してみるという手もあります。
(計算処理に時間を要する場合は、計算結果をキャッシュしておく必要がありそうですが)


> また編集中のセルが取得できない?ように思います。
DataGridView 上に表示される TextBox のイベントを使ってみては如何でしょう。
http://dobon.net/vb/dotnet/datagridview/editingcontrol.html
http://dobon.net/vb/dotnet/datagridview/textboxevent.html
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewtextboxeditingcontrol%28VS.80%29.aspx

# 未確認ですが…編集終了の検知に使えそうなところでいうと、TextBox の
# Validating、Validated、VisibleChanged、Leave イベントあたり?
投稿者 ひでと  (社会人) 投稿日時 2011/4/25 17:50:53
魔界の仮面弁士様 ありがとうございます。
>Culk …… Calc ではなく? (calculate)
えーー、英語苦手で適当にしてます。恥。

>戻り値の型は String で、Return する値は Double なのですか?
Stringに直しておきます。恥恥。

>DataGridView 上に表示される TextBox のイベントを使ってみては如何でしょう。
>http://dobon.net/vb/dotnet/datagridview/editingcontrol.html
>http://dobon.net/vb/dotnet/datagridview/textboxevent.html
>http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridviewtextboxeditingcontrol%28VS.80%29.aspx

># 未確認ですが…編集終了の検知に使えそうなところでいうと、TextBox の
># Validating、Validated、VisibleChanged、Leave イベントあたり? 

DataGridViewでTextBoxが使われているのまでは、ネットで調べたのですが、
EditingControlShowingというイベント?を使い入力時のチェックをしている例がありました。

その例では TextBoxのKeyPressイベントで処理していたのですが、
教えていただいた Validating、Validated、VisibleChanged、Leave についても調べてみます。

気になるのが、
DataGridViewのCurrentCellDirtyStateChangedイベントに処理をいれているのですが

    Private Sub DataGridView1_CurrentCellDirtyStateChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DataGridView1.CurrentCellDirtyStateChanged
        Me.DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
                計算()
    End Sub

このような処理は併用できないのかな?という点を調べてみます。ありがとうございました。
投稿者 ひでと  (社会人) 投稿日時 2011/4/26 10:12:38
試してみたのですが、解決しません。もう少しご助力を・・・。

試してみたのは以下のようです。
    Private Sub dataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dataGridView1.EditingControlShowing
        '表示されているコントロールがDataGridViewTextBoxEditingControlか調べる
        If TypeOf e.Control Is DataGridViewTextBoxEditingControl Then
            Dim dgv As DataGridView = CType(sender, DataGridView)

            '編集のために表示されているコントロールを取得
            Dim tb As DataGridViewTextBoxEditingControl = _
                CType(e.Control, DataGridViewTextBoxEditingControl)

            'イベントハンドラを削除
            RemoveHandler tb.Leave, AddressOf dataGridViewTextBox_Leave

            'KeyPressイベントハンドラを追加
            AddHandler tb.Leave, AddressOf dataGridViewTextBox_Leave
        End If
    End Sub
    'DataGridViewに表示されているテキストボックスのKeyPressイベントハンドラ
    Private Sub dataGridViewTextBox_KeyPress(ByVal sender As Object, _
            ByVal e As KeyPressEventArgs)
        If e.KeyChar = vbCr Then
            sender.Text = Calk(sender.text)
        End If
    End Sub

    Private Sub dataGridViewTextBox_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
        sender.text = Calk(sender.text)
    End Sub

    Private Sub dataGridViewTextBox_Validated(ByVal sender As Object, ByVal e As System.EventArgs)
        sender.text = Calk(sender.text)
    End Sub
    Private Sub dataGridViewTextBox_Leave(ByVal sender As Object, ByVal e As System.EventArgs)
        sender.text = Calk(sender.text)
    End Sub

として dataGridView_EditingControlShowingのRemoveHandler 、AddHandler を
KeyPress、Validating、Validated、Leaveと変更しながら実験してみました。

KeyPressの場合 If e.KeyChar = vbCr Then ではEnterキーが取得できないようで、
sender.Text = Calk(sender.text)は実行できませんでした。
他のTextBoxではうまくできていたのに・・・?

他の場合は sender.textは 計算した結果 ("1+1"で実験  "2")になりましたが、イベントが終わると
dataGridViewのセルでは "1+1"のままになってしまいます。

さらなるアドバイスをお願いいたします。
投稿者 ひでと  (社会人) 投稿日時 2011/4/26 17:11:36
お騒がせしました。
TextBoxの処理がよくなかったようです。

    Private Sub dataGridViewTextBox_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
        Dim sen As System.Windows.Forms.DataGridViewTextBoxEditingControl = sender
        sen.EditingControlDataGridView.CurrentCell.Value = Calk(sender.text)
  End Sub

としたら計算できました。

解決とさせていただきますが、これじゃダメという場合は教えてください。
ありがとうございました。