あいまい検索

タグの編集
投稿者 初心者  (社会人) 投稿日時 2018/5/23 17:05:32
ComboBoxから選ばれたものを検索列にしたものを作りたいのですが


   Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Dim ConnectionString As String = "<接続文字列>"

        Dim cnn = New SqlConnection(ConnectionString)
        cnn.Open()

        'データアダプタオブジェクトの作成
        Dim Item As String = ComboBox1.SelectedItem
        Dim adapter = New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE Item Like N'%" & TextBox1.Text & "%'", cnn)

        'データセットオブジェクトの作成
        Dim ds = New DataSet()

        '抽出したデータをデータセットに格納
        adapter.Fill(ds)

        'DataGridViewのデータソースにデータセットのテーブルをバインド
        Me.DataGridView1.DataSource = ds.Tables(0)


型 'System.Data.SqlClient.SqlException' のハンドルされていない例外が System.Data.dll で発生しました
追加情報:Invalid column name 'Item'.
とエラーが出ています

どうしたらいいでしょうか?
コードは下記を参考にさせてもらっています
https://hosopro.blogspot.jp/2016/10/sqldataadapterdatagridview.html
投稿者 YuO  (社会人) 投稿日時 2018/5/23 21:42:04
たぶんItemという列がTableテーブルに存在しないのでしょう。
Itemの部分を正しい列の名前に置き換えればよいかと。
投稿者 初心者  (社会人) 投稿日時 2018/5/24 08:03:56
YuOさま

ご指摘ありがとうございます。

〉Itemの部分を正しい列の名前に置き換えればよいかと。
ComboBoxには「ID」などを入れていてItemではなくそのままIDとすれば検索されます。
ですがComboBoxのものを使いたくて、何か間違ってるでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/5/24 12:49:01
> ComboBoxには「ID」などを入れていてItemではなくそのままIDとすれば検索されます。

ComboBox で「入力されているテキスト値」を取得する場合は
 Dim s As String = ComboBox1.Text
です。これは通常、DropDownStyle が DropDown な ComboBox の場合に使います。

ComboBox の DropDownStyle が DropDownList の場合は、
「選択された項目名」を取得するために
 Dim s As String = ComboBox1.GetItemText(ComboBox1.SelectedItem)
のようにします。
http://7ujm.net/VB/ComboBox.html


ComboBox1.Items(n) の中にあるデータが String 型のデータと分かっている場合は、
 Dim s2 As String = CStr(ComboBox1.SelectedItem)
などでも構いませんが、ValueMember プロパティを設定している場合などは、
GetItemText メソッドを通じて取得するようにします。


> ですがComboBoxのものを使いたくて、何か間違ってるでしょうか? 

下記の違いは分かりますよね。
Label1.Text = ComboBox1.GetItemText(ComboBox1.SelectedItem)
Label2.Text = "ComboBox1.GetItemText(ComboBox1.SelectedItem)"
'下記は VB2015 以降限定 
'Label3.Text = $"{ComboBox1.SelectedItem}" 
'Label4.Text = $"{ComboBox1.GetItemText(ComboBox1.SelectedItem)}" 


ということは、下記も別物になるわけで。
Dim adapter1 As New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE Item Like N'%" & TextBox1.Text & "%'", cnn)
Dim adapter2 As New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE ID Like N'%" & TextBox1.Text & "%'", cnn)
Dim adapter3 As New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE " & ComboBox1.GetItemText(ComboBox1.SelectedItem) & " Like N'%" & TextBox1.Text & "%'", cnn)


なお実際は、TextBox1 に "%" や _" が含まれていた場合のエスケープ処理も必要です。
https://sakapon.wordpress.com/2010/06/21/sqlserverlike/
投稿者 初心者  (社会人) 投稿日時 2018/5/24 14:01:07
魔界の仮面弁士さま

>下記の違いは分かりますよね。
>Label1.Text = ComboBox1.GetItemText(ComboBox1.SelectedItem)
>Label2.Text = "ComboBox1.GetItemText(ComboBox1.SelectedItem)"

文字列として扱うかという認識なのですがあってますでしょうか?

Dim adapter As New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE " & ComboBox1.GetItemText(ComboBox1.SelectedItem) & " Like N'%" & TextBox1.Text & "%'", cnn)

と直したら大丈夫でした。

" & ○ & "の"&はどうゆう役割なのでしょうか?

それと

Dim adapter As New SqlDataAdapter("SELECT [ID], [所在], [種類] FROM [Table] WHERE " & ComboBox1.SelectedItem & " Like N'%" & TextBox1.Text & "%'", cnn)

という形でも動くのですがどうなんでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2018/5/24 14:37:20
> 文字列として扱うかという認識なのですがあってますでしょうか?
その通りです。ですから当初の
 "SELECT [ID], [所在], [種類] FROM [Table] WHERE Item Like N'%"…
という表現だと、ComboBox の内容とは無関係に、常に「Item」という名前のフィールドとして処理されるわけですね。


> " & ○ & "の"&はどうゆう役割なのでしょうか?

ご存知のように、「&」は文字列連結のための演算子ですし、
「"」は文字列リテラルを囲む記号です。

Dim s1 As String = "abc"
Dim s2 As String = "xyz"
Dim s3 As String = s1 & s2

上記のうち、変数 s1 、s2 の部分を置き換えると
Dim s3 As String = "abc" & "xyz"
になりますよね。この処理結果は
Dim s3 As String = "abcxyz"
となるわけですが、それと全く同じことです。


先の SQL で言うと、たとえば、
 Dim fieldName As String = "Id"
 Dim searchWord As String = "0"
 Dim sql As String = "WHERE [" & fieldName & "] LIKE N'%" & searchWord & "%' "
というコードがあるとすれば、
 Dim sql As String = "WHERE [" & "Id" & "] LIKE N'%" & "0" & "%' "
という形に展開されるので、結果として
 Dim sql As String = "WHERE [Id] LIKE N'%0%' "
という文字列が得られることになるわけです。


なお、VB2015 以降の場合は、& 演算子で繋いでいくよりも、
 Dim fieldName As String = "Id"
 Dim searchWord As String = "0"
 Dim sql As String = $"WHERE [{fieldName}] LIKE N'%{searchWord}%' "
の構文を使った方が読みやすいかもしれません。


> という形でも動くのですがどうなんでしょうか?
間違いではないのですが、SelectedItem プロパティの戻り値は Object 型なので、
そのコードだと「Option Strict On」でコンパイルした時にエラーとなりますね。

また、ComboBox の DisplayMember プロパティを利用している場合には、
GetItemText メソッドを通じて取得するようにしないと、正しい文字列表現になりません。

それと、ComboBox でまだ何も選択されていない場合には、
ComBox1.SelectedIndex は -1 を返し、
ComBox1.SelectedItem は Nothing を返すことにも注意しましょう。
投稿者 初心者  (社会人) 投稿日時 2018/5/24 15:05:29
>魔界の仮面弁士さま

とりあえず動くものができました。
ありがとうございます!

それと大変勉強になりました。
エスケープ処理などやることはまだあるので学んで加えていこうと思います。