VB.NET DataGridViewのヘッダをダブルクリックしたとき

VB.NET で開発中のアプリで DataGridView を使用しています。

んで、CellDoubleClick イベントを使用して、レコードの編集用ファンクションを呼んでいました。

しかしヘッダをクリックしてソートした場合もこれが発生してしまい、地味に困っておりました。

ヘッダをクリックした場合にはこのファンクション呼びたくないなーとおもって方法を色々探していたところ、CellDoubleClick の引数 e を使って

e.RowIndex < 0

の場合を除外する条件分岐で、あっさり解決しましたとさ。

posted by へっぽ at 20:00 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET ImeMode=Katakanaが反映されない

vb.net で開発したアプリケーションで、あるテキストボックスのImeModeをKatakanaに設定しているのに、なぜか反映されず、ImeModeがデフォルト状態となってしまう・・・ 。

どうやら初回起動時にフォーカスされるテキストボックスは、ImeModeが正しく反映されない「ことがある」ようで。

実際、似たようなことをしている他のフォームではImeModeが正しく反映されていた。

今回は、Loadイベントパンドラにて
@一旦ボタンにフォーカスを当てて
A所望のテキストボックスにフォーカスを当て直す
ことで回避。

Microsoftに本件のサポートページがありました。
https://support.microsoft.com/ja-jp/kb/945146

posted by へっぽ at 20:26 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET 突然の『ORA-6413: 接続がオープンしていません。』

ほんの10分前まで正常に動いていたモジュールが、突然

『Oracle.DataAccess.Client.OracleException ORA-6413: 接続がオープンしていません。』

というエラーを出すようになってしまった。

Oracle接続部分なんて毛ほども触っていないのに・・・何故だ。

原因は、exeが格納されているフォルダに「半角カッコ()」が含まれていたこと。

フォルダ名から()を除去してやると正常に稼働するようになった。

なかなか原因を推測しづらいエラーメッセージ┐( ̄ヘ ̄)┌。

posted by へっぽ at 05:51 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET OracleストアドプロシージャのSELECT結果を取得するA

OracleのストアドプロシージャでSELECTした結果をVB.NETで取得する方法。
Aストアドプロシージャがカーソルを使っているパターン

下記のようなストアドプロシージャがある場合

 PROCEDURE SAMPLE_PROCEDURE2(
   INPUT1 IN NUMBER,
   O_CURSOR_FOR_SAMPLE OUT REF_CURSOR
 ) AS
   BEGIN
     OPEN O_CURSOR_FOR_SAMPLE FOR
       SELECT
         ID,
         NAME,
         DEPARTMENT
       FROM
         EMPLOYEE
       WHERE
         ID = INPUT1;

   END SAMPLE_PROCEDURE;




それを取得するためのVB.NETコードは以下のようになる。
(DataTableで返す)

 Dim connection As OracleConnection = New OracleConnection()
 Dim command As OracleCommand = New OracleCommand()
 DIm adapter As OracleDataAdapter = New OracleDataAdapter()

 'Oracleへのコネクションをオープンする
 connection = New OracleConnection()
 connection.ConnectionString = "XXX"
 connection.Open()
 command.Connection = connection

 'ストアドプロシージャをセットする
 command.CommandType = CommandType.StoredProcedure
 command.CommandText = "PROCEDURE_NAME"

 'ストプロのパラメータをセットする
 Dim inPara1 As New OracleParameter("INPUT1", OracleDbType.Decimal, ParameterDirection.Input)
 inPara1.Value = 1
 Dim outPara1 As New OracleParameter("out_CURSOR", OracleDbType.RefCursor, ParameterDirection.Output)
 command.Parameters.Add(inPara1)
 command.Parameters.Add(outPara1)
 
 'ストアド実行
 adapter = New OracleDataAdapter(command)
 Dim ds As New DataSet()
 adapter.Fill(ds)

 command.Parameters.Clear() '後で使うためにクリアする

 Return ds.Tables(0)

 connection.Close()
 connection.Dispose()
 adapter.Dispose()



posted by へっぽ at 12:34 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET OracleストアドプロシージャのSELECT結果を取得する@

OracleのストアドプロシージャでSELECTした結果をVB.NETで取得する方法。
@ストアドプロシージャがカーソルを使っていないパターン

下記のようなストアドプロシージャがある場合

 PROCEDURE SAMPLE_PROCEDURE1(
    INPUT1 IN NUMBER,
    OUTPUT1 OUT NVARCHAR2
  ) AS
  BEGIN
    BEGIN
      SELECT
        NAME
      INTO
        OUTPUT1
      FROM
        EMPLOYEES
      WHERE
        ID = INPUT1;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        OUTPUT1 := '';
    END;
  END SAMPLE_PROCEDURE1;




それを取得するためのVB.NETコードは以下のようになる。
(Stringで返す)

 Dim connection As OracleConnection = New OracleConnection()
 Dim command As OracleCommand = New OracleCommand()

 'Oracleへのコネクションをオープンする
 connection = New OracleConnection()
 connection.ConnectionString = "XXX"
 connection.Open()
 command.Connection = connection

 'ストアドプロシージャをセットする
 command.CommandType = CommandType.StoredProcedure
 command.CommandText = "SAMPLE_PROCEDURE1"
 
 'ストアドプロシージャのパラメータをセットする
 Dim inPara1 As New OracleParameter("INPUT1", OracleDbType.Decimal, ParameterDirection.Input)
 inPara1.Value = 1
 Dim outPara1 As New OracleParameter("OUTPUT1", OracleDbType.NVarchar2, ParameterDirection.Output)
 outPara1.Size = 45 '出力パラメータのサイズ指定
 command.Parameters.Add(inPara1)
 command.Parameters.Add(outPara1)
 
 'ストアド実行
 command.ExecuteNonQuery()
 
 command.Parameters.Clear() '後で使うためにクリアする

 Return outPara1.Value.ToString()

 connection.Close()
 connection.Dispose()





posted by へっぽ at 10:16 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataGridView の ComboBoxColumn にフォーカスが当たったらすぐにリストを表示する

DataGridView の ComboBoxColumn は、フォーカスが当たってもリストがすぐには表示されず、3回ほどクリックしないとリストが出てこない。
フォーカスが当たったら即座にリストを表示する必要があったので、やり方をメモ。
DataGridView の CellEnter イベントを補足することによって実現する。
フォーカスが当たったセルの種類(必要なら名前も)で判断し、該当したら F4 キーを送信するというやり方。


Private Sub SampleDataGridView_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles SampleDataGridView.CellEnter
  Dim dgv As DataGridView = CType(sender, DataGridView)
  Dim columnIndex As Integer = e.ColumnIndex
  
  'コンボボックスは即座にリストを表示する
  If dgv.Columns(columnIndex).Name = column1.Name AndAlso _
   TypeOf dgv.Columns(columnIndex) Is DataGridViewComboBoxColumn Then
   SendKeys.Send("{F4}")
   
  End If
  
End Sub



posted by へっぽ at 19:06 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataGridView の所定のカラムだけ、IMEを操作する

DataGridView で、特定のカラムだけ IMEをOff(Disable)にする必要が出てきたのでやり方をメモ。
DataGridView の CellEnter イベントを補足することによって実現する。
フォーカスが当たったセルのカラム名で判断し、該当したら ImeMode を変更するというやり方。


Private Sub SampleDataGridView_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles SampleDataGridView.CellEnter
  Dim dgv As DataGridView = CType(sender, DataGridView)
  Dim columnIndex As Integer = e.ColumnIndex
  
  Dim columnName As String = dgv.Columns(columnIndex).Name
  
  '特定のカラムはIMEをDisableにする
  Select Case columnName
    Case column1.Name, column2.Name
      SampleDataGridView.ImeMode = Windows.Forms.ImeMode.Disable
      
    Case Else
      SampleDataGridView.ImeMode = Windows.Forms.ImeMode.On
    
  End Select
  
End Sub



posted by へっぽ at 23:24 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataGridView のカーソル遷移で、ReadOnly = True のセルをスキップする

DataGridView のカーソルは基本的にタブキーで遷移させることができ、左から右に動く。
そのときに、ReadOnly = True のセルだけスキップする(フォーカスを当てない)処理が必要になったので、サンプルコードをメモ。
DataGridView の CellEnter イベントを補足することによって実現する。
単純に、ReadOnly = True のセルにフォーカスが当たったら Tab キーを送る、というやり方。

※下記の方法だと、マウスクリックした場合でもフォーカスが当たらなくなってしまうが、仕様ということで。


Private Sub SampleDataGridView_CellEnter(sender As Object, e As DataGridViewCellEventArgs) Handles SampleDataGridView.CellEnter
  Dim dgv As DataGridView = CType(sender, DataGridView)
  Dim columnIndex As Integer = e.ColumnIndex
  
  'ReadOnlyのカラムはフォーカスせず次のカラムへ飛ばす
  If dgv.Columns(columnIndex).ReadOnly = True Then
    SendKeys.Send("{Tab}")
    
  End If
  
End Sub


posted by へっぽ at 17:48 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataGridViewCheckBoxColumn の変化をすぐに反映させる

DataGridView を使っていて、
DataGridViewCheckBoxColumn のチェック状態と、それと同じ行にある DataGridViewComboBoxColumn の選択値に相関を持たせるという機能実装が必要に。
チェックボックスの付け外しをしたら、すぐに相関チェックが走るようにしたい。

単純に CellValueChanged だと一度フォーカスを外さないと反映されず、リアルタイム(?)の取りたい場合は CurrentCellDirtyStateChanged を使用する必要があるらしい。

下は、チェックボックス(myCheckBox)のチェックが外れたとき、同じ行のコンボボックス(myComboBox)が何か選択されていたら、メッセージ「hogehoge」を表示してチェックボックスのチェックを再度強制的にセットする、というサンプル。
DataGridView の CommitEnd と EndEdit がポイントだった。


  Private Sub SampleDataGridView_CurrentCellDirtyStateChanged(sender As Object, e As EventArgs) Handles SampleDataGridView.CurrentCellDirtyStateChanged
    If SampleDataGridView.CurrentCell.OwningColumn.Name = myCheckBox.Name AndAlso SampleDataGridView.IsCurrentCellDirty Then
      SampleDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit)

      Dim comboBoxStr As String = SampleDataGridView.CurrentRow.Cells(myComboBox.Name).FormattedValue
      If SampleDataGridView.CurrentCell.Value = False AndAlso comboBoxStr <> "" Then
        MsgBox("hogehoge")
        SampleDataGridView.CurrentCell.Value = True
        SampleDataGridView.EndEdit()

      End If

    End If

  End Sub



posted by へっぽ at 16:33 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET ValueMemberとDisplayMemberの取得

コンボボックスに設定した
・ValueMember
・DisplayMember
を取得するときにいつも迷うのでメモ。

ComboBoxでそれぞれの値を取得するには(ComboBox型の変数をcbとして)
・ValueMember・・・cb.SelectedValue
・DisplayMember・・・cb.Text

DataGridViewComboBoxColumnでそれぞれの値を取得するには(DataGridViewComboBoxColumn型の変数をdgvc、行を示す変数をi、列を示す変数をjとして)
・ValueMember・・・dgvc.Rows(i).Cells(j).Value
・DisplayMember・・・dgvc.Rows(i).Cells(j).FormattedValue

posted by へっぽ at 12:01 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET Excelプロセスが残り続ける

Excelのプロセスが残り続ける問題に悩まされた。
非っっ常に多くのサイトにお世話になりながらも、ドハマりした挙句何とかかんとか解決したので、必要事項を自分なりに整理してみた。
(全て世間的には当たり前のことのようだが・・・)

@暗黙参照は作らない
必ず、一度全て変数にして作る!

  Dim xlApp As Excel.Application = Nothing
  Dim xlBooks As Excel.Workbooks = Nothing
  Dim xlBook As Excel.Workbook = Nothing
  Dim xlSheets As Excel.Sheets = Nothing
  Dim xlSheet As Excel.Worksheet = Nothing
  Dim xlRange As Excel.Range = Nothing

  xlApp = CreateObject("Excel.Application")
  xlBooks = xlApp.Workbooks
  xlBook = xlBooks.Open(fileName)
  xlSheets = xlBook.Worksheets
  xlSheet = xlSheets(1) '1シート目を読む
  xlRange = xlSheet.Range("A1")
  :



A最後の参照開放は順序が重要!
親子関係は上から順に、
Application→Workbooks→Workbook→Sheets→Worksheet→Range
となっているので、開放はこのに行う。
その際、WorkbookはCloseし、ApplicationはQuitする。

  xlBook.Close(False)
  xlApp.Quit()
  If xlRange IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlRange)
  If xlSheet IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlSheet)
  If xlSheets IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlSheets)
  If xlBook IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBook)
  If xlBooks IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBooks)
  If xlApp IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)



BFor文で参照している場合は毎回開放!
※これをやらなくても大丈夫としているサイトもあったが、自分の環境だとプロセスは残り続けたので(With句を使っていないから?)。

  Do
    xlRange = xlSheet.Range("A" & rowIndex + 1)
    Dim str = xlRange.Text.ToString
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlRange)

    :

    rowIndex += 1
  Next



お世話になった方々
http://d.hatena.ne.jp/chago/20130121/1358742211
http://homepage1.nifty.com/rucio/main/technique/teq_15.htm
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=31076&forum=7
http://www.asahi-net.or.jp/~ef2o-inue/vbnet/sub13_03_040.html
posted by へっぽ at 16:40 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataGridViewのコンボボックスに対する項目設定(DataSourceを使用)

コンボボックスに項目を設定するやり方の一つに、DataSourceプロパティを設定するというものがある。

例)
Dim dt As DataTable
・・・
ComboBox1.DataSource = dt

DataGridViewComboBoxColumnにもこのプロパティがあり、これを使うとDataGridViewの全ての行に共通の項目を一括設定することができる。

例)
Dim dgvc As DataGridViewComboBoxColumn
・・・
dgvc.DataSource = dt

時には全ての行ではなく、個々の行に別々の項目をセットしたいことがある。
そのようなときは、DataGridViewComboBoxCellのプロパティをセットすることで実現できる。

例)
Dim dgvcell As DataGridViewComboBoxCell
・・・
dgvcell = dgvc.Rows(0).Cells(0)
dgvcell.DataSource = dt

posted by へっぽ at 05:52 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET ツールボックスに何も出てこない

とあるフォームにTextBoxを追加したいと思ったが、「ツールボックス」欄に何も出てこない・・・

原因は、部品を追加したいフォーム「コード」を表示してしまっており、「フォームデザイナー画面」を表示していなかったため。

この状態だと、「ツールボックス」欄には 『このグループには使用可能なコントロールがありません。』 とだけ出てしまう。

フォームのデザイン画面を開くと、ちゃんとツールの一覧が表示される。

posted by へっぽ at 18:02 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET 属性 'DesignerGeneratedAttribute' を複数回適用することはできません。

VB.NETで下記のようなエラーが突然現れた。

「属性 'DesignerGeneratedAttribute' を複数回適用することはできません。」

ほかにも

「○○ は、この class で △△として既に宣言されています。」

が多数…。

原因は、フォームをコピーして別のフォームを作成したのだが、コピー後のフォームのクラス名が、コピー元の名前のままだったため。

コピー後のフォームのクラス名を修正したところ、解消した。

posted by へっぽ at 01:08 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET KeyDownイベントが拾えない

フォームでKeyDownイベントを拾うFunctionを記述しているのに、まったく反応しない。
KeyPressやPreviewKeyDownを設定してもダメ。
デバッガを設定してもかすりもしない。何故??

原因は、フォームのプロパティ KeyPreview が False になっていたため。
これを True にすると、KeyDown等々のイベントが捕捉できるようになる。
フォームをコピーして使いまわしていると、いろいろ設定値が変わっているものです・・・。

posted by へっぽ at 22:46 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET コンボボックスで検索候補表示機能を実装する

VB.NETアプリのコンボボックスで、入力した文字が含まれる候補のみを表示する機能を実装。
所謂サジェスト検索的なものに近いか。

@あらかじめ、コンボボックスのリストとなる要素をDataTableで作成しておく。
(DataTableには"ITEM"というカラムがあるものとする)

A次に、それらの要素DataTableのDataViewを作成し、コンボボックスのテキストが変化するたびに、DataViewをフィルタリングし、要素を絞っていく。

B最後に、Aで絞った要素を、コンボボックスのデータソースとして追加し、リスト表示する。

というやり方を採った。


Private Sub ComboBox1_TextUpdate(sender As Object, e As EventArgs) Handles ComboBox1.TextUpdate
    '入力された文字列で検索条件をつくる
    Dim w As String = "ITEM LIKE '%" & ComboBox1.Text & "%'"
    Dim dv = New DataView(comboDt) 'comboDtはコンボボックスの全件リスト
    dv.RowFilter = w

    '候補を絞った結果を格納する
    Dim comboDt2 = New DataTable
    comboDt2.Columns.Add("ITEM", Type.GetType("System.String"))
    For Each drv As DataRowView In dv
     comboDt2.ImportRow(drv.Row)
    Next

    'コンボボックスに候補を絞った結果をセット
    ComboBox1.DataSource = comboDt2

    '候補を表示
    ComboBox1.DroppedDown = True

End Sub



正しいやり方かはわからないが、概ねこんな感じ。
また、上記のままだと、テキスト入力するたびにカーソルが文字列の頭に戻ってしまうので、逐一それを調整する作業も必要になる。



posted by へっぽ at 00:46 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET Multiline=False でも改行コードLFは入る

フォームのテキストボックスのMultilineプロパティをFalseにしていたのに、
改行コードが混入するという事態が発生。

混入していた改行コードは「LF」。
テキストボックスのMultiline=Falseは、「CRLF」ないし「CR」は防いでくれるが、「LF」は通過してしまうらしい。
しかもその場合、画面上は改行が表示されない(改行されてないように見える)

テキストエディタからコピペしたときぐらいしか発生しないだろうと思っていたら、一つ手段を発見。Excelからコピペしたときも発生し得る。

Excelの一つのセルに改行を含む文字列が書かれている場合、そのセルを編集モードにしてコピーしたときには、その改行コードはCRLFとなる。
しかしセルとしてコピーした場合、ペースト先ではその改行コードはLFとなる様子。
今回のも恐らくこの手順で発生したのではなかろうか・・・

posted by へっぽ at 16:09 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET DataTableに追加した項目を表形式で一括表示

対して目新しい方法ではないが、DataTableの項目を一覧化したいことがあったので、方法をメモ。
DataTableの中のDataRowを1つずつ取り出し、さらにその中のItemArrayを1つずつ取り出して、各々ToStringしてコンソール出力する。


Dim dataTable As DataTable = New DataTable()
:(dataTableに値が入っているものとする>)
Console.WriteLine("dataTableの中身を表示")
For Each r As DataRow In dataTable.Rows
  For Each i As Object In r.ItemArray
    Console.Write(i.ToString & " | ")
  Next
 Console.WriteLine("")
Next



posted by へっぽ at 23:59 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET AutoScrollPositionを設定してもスクロールバーの位置がズレる

VB.NETで、とあるフォームにスクロールバーを設置。
スクロールバーを動かした後、他のウインドウを前面にして、再びフォームを前面にすると、スクロールバーの位置が(0,0)に戻っているという現象が発生。

Form1_Deactivate メソッドで Me.AutoScrollPosition.X と Me.AutoScrollPosition.Y を取得しておき、
Form1_Activated メソッドでその値をセットするコードを実装していたのだが上手くいかない。
スクロールバーが(0, 0)の位置に戻ってしまう。

■修正前

Private scrollX
Private scrollY

Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
  Me.AutoScrollPosition = New Point(scrollX, scrollY)

End Sub

Private Sub Form1_Deactivate(sender As Object, e As EventArgs) Handles MyBase.Deactivate
  scrollX = Me.AutoScrollPosition.X
  scrollY = Me.AutoScrollPosition.Y

End Sub



調べてみたら、
AutoScrollPosition.XとAutoScrollPosition.Xで得られる値は負
AutoScrollPosition = New Point(X, Y)で設定する値は正
ということらしい。

■修正後

Private scrollX
Private scrollY

Private Sub Form1_Activated(sender As Object, e As EventArgs) Handles MyBase.Activated
  Me.AutoScrollPosition = New Point(-scrollX, -scrollY)

End Sub

Private Sub Form1_Deactivate(sender As Object, e As EventArgs) Handles MyBase.Deactivate
  scrollX = Me.AutoScrollPosition.X
  scrollY = Me.AutoScrollPosition.Y

End Sub



これで何とかスクロール位置を維持できた。



posted by へっぽ at 01:00 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする

VB.NET Oracleのストアドプロシージャを呼ぶと『ORA-06502: PL/SQL: 数値または値のエラーが発生しました』

VB.NETからOracleのストアドプロシージャを呼んだところ、
『ORA-06502: PL/SQL: 数値または値のエラーが発生しました』
が発生。

以下、問題のコード。

■Oracleストアドプロシージャ

  PROCEDURE GETUSERNAME(
    I_ID IN NVARCHAR2,
    I_PW IN NVARCHAR2,
    O_NAME OUT NVARCHAR2
  ) AS
    BEGIN
      SELECT
        NAME
     INTO
        O_NAME
      FROM
        USER
      WHERE
        ID = I_ID
        AND
        PW = I_PW;
    END GETUSERNAME;



■VB.NET

  'ストアドプロシージャの呼び出し
  Dim cmd As New OracleCommand
  cmd.Connection = conn
  cmd.CommandType = CommandType.StoredProcedure
  cmd.CommandText = "GETUSERNAME"
  cmd.Parameters.Add(New OracleParameter("I_ID", OracleDbType.NVarchar2, ParameterDirection.Input))
  cmd.Parameters.Add(New OracleParameter("I_PW", OracleDbType.NVarchar2, ParameterDirection.Input))
  cmd.Parameters.Add(New OracleParameter("O_NAME", OracleDbType.NVarchar2, ParameterDirection.Output))
  cmd.Parameters("I_ID").Value = "ID"
  cmd.Parameters("I_PW").Value = "PASSWORD"
  cmd.ExecuteNonQuery()
  MsgBox(cmd.Parameters("O_NAME").Value.ToString())



これでVBを実行すると、cmd.ExecuteNonQuery() のところで冒頭のエラーが発生。

このエラーで検索しても、「ストアドプロシージャで数値のNULLチェックをきちんとすれば〜」的なことが書いてある。
とはいえ、プロシージャにはそんなチェックが必要そうなところは見当たらない。

で、行き当たったのが以下のブログ(ありがとうございます!)
http://modeverv.hateblo.jp/entry/20081226/1230262620

VARCHARのOUTPUTはサイズ指定が必要…?
試しに以下のように変更。


■VB.NET(新)

  'ストアドプロシージャの呼び出し
  Dim cmd As New OracleCommand
  cmd.Connection = conn
  cmd.CommandType = CommandType.StoredProcedure
  cmd.CommandText = "GETUSERNAME"
  cmd.Parameters.Add(New OracleParameter("I_ID", OracleDbType.NVarchar2, ParameterDirection.Input))
  cmd.Parameters.Add(New OracleParameter("I_PW", OracleDbType.NVarchar2, ParameterDirection.Input))
  Dim p As OracleParameter = New OracleParameter("O_NAME", OracleDbType.NVarchar2)
  p.Direction = ParameterDirection.Output
  p.Size = 200
  cmd.Parameters.Add(p)

  cmd.Parameters("I_ID").Value = "ID"
  cmd.Parameters("I_PW").Value = "PASSWORD"
  cmd.ExecuteNonQuery()
  MsgBox(cmd.Parameters("O_NAME").Value.ToString())



…解決。
OracleのエラーメッセージもVBの仕様も分かりにくく、ハマりました…


posted by へっぽ at 00:20 | TrackBack(0) | VB.NET | このブログの読者になる | 更新情報をチェックする