2010年7月22日木曜日

.NET 50音検索

50音検索って結構面倒ですね・・・

データテーブルに半角カナで保存されているフィールドを50音検索するサンプルです。

SQLのWhere句に Tool.KanaSearchFilterStringメソッドの戻り値を付ければ
データテーブル以外にもデータベースに対しても50音検索できます。

Public Class Form1


    Private _tbl As DataTable

    Public Sub New()

        ' この呼び出しは、Windows フォーム デザイナで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。

        'テストデータ作成
        Call CreateTestData()
    End Sub

    'テストデータ作成
    Private Sub CreateTestData()

        Dim tbl As New DataTable
        tbl.Columns.Add("Kana", GetType(String))
        tbl.Rows.Add(New Object() {"ア"})
        tbl.Rows.Add(New Object() {"カ"})
        tbl.Rows.Add(New Object() {"サ"})
        tbl.Rows.Add(New Object() {"タ"})
        tbl.Rows.Add(New Object() {"ナ"})
        tbl.Rows.Add(New Object() {"ハ"})
        tbl.Rows.Add(New Object() {"マ"})
        tbl.Rows.Add(New Object() {"ヤ"})
        tbl.Rows.Add(New Object() {"ラ"})
        tbl.Rows.Add(New Object() {"ワ"})

        Me._tbl = tbl
    End Sub

    Private Sub rdoKana_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles rdoKana_All.CheckedChanged _
            , rdoKana_A.CheckedChanged _
            , rdoKana_Ka.CheckedChanged _
            , rdoKana_Sa.CheckedChanged _
            , rdoKana_Ta.CheckedChanged _
            , rdoKana_Na.CheckedChanged _
            , rdoKana_Ha.CheckedChanged _
            , rdoKana_Ma.CheckedChanged _
            , rdoKana_Ya.CheckedChanged _
            , rdoKana_Ra.CheckedChanged _
            , rdoKana_Wa.CheckedChanged _
            , rdoKana_Other.CheckedChanged

        If DirectCast(sender, RadioButton).Checked = False Then
            Return
        End If

        Dim kana As Tool.KanaSearchType
        If rdoKana_A.Checked Then
            kana = Tool.KanaSearchType.A
        ElseIf rdoKana_Ka.Checked Then
            kana = Tool.KanaSearchType.Ka
        ElseIf rdoKana_Sa.Checked Then
            kana = Tool.KanaSearchType.Sa
        ElseIf rdoKana_Ta.Checked Then
            kana = Tool.KanaSearchType.Ta
        ElseIf rdoKana_Na.Checked Then
            kana = Tool.KanaSearchType.Na
        ElseIf rdoKana_Ha.Checked Then
            kana = Tool.KanaSearchType.Ha
        ElseIf rdoKana_Ma.Checked Then
            kana = Tool.KanaSearchType.Ma
        ElseIf rdoKana_Ya.Checked Then
            kana = Tool.KanaSearchType.Ya
        ElseIf rdoKana_Ra.Checked Then
            kana = Tool.KanaSearchType.Ra
        ElseIf rdoKana_Wa.Checked Then
            kana = Tool.KanaSearchType.Wa
        ElseIf rdoKana_Other.Checked Then
            kana = Tool.KanaSearchType.Other
        End If

        Dim sFilter As String = String.Empty
        sFilter = Tool.KanaSearchFilterString("Kana", kana, Tool.KanaSearchDataType.DataTable)
        Dim row() As DataRow = Me._tbl.Select(sFilter)

        Console.WriteLine("【{0}】", kana.ToString)
        For Each r As DataRow In row
            Console.WriteLine(r.Item(0))
        Next
    End Sub

End Class

Public Class Tool

    ''' <summary>
    ''' 50音検索の検索文字
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum KanaSearchType
        A = 1
        Ka = 2
        Sa = 3
        Ta = 4
        Na = 5
        Ha = 6
        Ma = 7
        Ya = 8
        Ra = 9
        Wa = 10
        Other = 11
    End Enum

    ''' <summary>
    ''' 50音検索するデータ種
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum KanaSearchDataType
        Oracle = 1
        SQLServer = 2
        Access = 3
        DataTable = 4
    End Enum

    ''' <summary>
    ''' 50音検索を行うフィルター文字列を作成します。
    ''' </summary>
    ''' <param name="sFieldNm">50音検索を行うフィールド名</param>
    ''' <param name="kana">検索するカナ</param>
    ''' <param name="dataType">検索するデータ種</param>
    ''' <returns></returns>
    ''' <remarks>
    ''' </remarks>
    Public Shared Function KanaSearchFilterString(ByVal sFieldNm As String, ByVal kana As KanaSearchType, ByVal dataType As KanaSearchDataType) As String

        'Oracle SubStr
        'DataTable SubString
        'SQLServer SubString
        'Access Mid
        Dim funcNm As String
        Select Case dataType
            Case KanaSearchDataType.Oracle
                funcNm = "Substr"
            Case KanaSearchDataType.Access
                funcNm = "Mid"
            Case Else
                funcNm = "SubString"
        End Select


        Dim sFilter As String = String.Empty
        If kana = KanaSearchType.A Then
            sFilter = "{0}({1},1,1) in ('ア','イ','ウ','エ','オ','ァ','ィ','ゥ','ェ','ォ')"
        ElseIf kana = KanaSearchType.Ka Then
            sFilter = "{0}({1},1,1) in ('カ','キ','ク','ケ','コ')"
        ElseIf kana = KanaSearchType.Sa Then
            sFilter = "{0}({1},1,1) in ('サ','シ','ス','セ','ソ')"
        ElseIf kana = KanaSearchType.Ta Then
            sFilter = "{0}({1},1,1) in ('タ','チ','ツ','テ','ト')"
        ElseIf kana = KanaSearchType.Na Then
            sFilter = "{0}({1},1,1) in ('ナ','ニ','ヌ','ネ','ノ')"
        ElseIf kana = KanaSearchType.Ha Then
            sFilter = "{0}({1},1,1) in ('ハ','ヒ','フ','ヘ','ホ')"
        ElseIf kana = KanaSearchType.Ma Then
            sFilter = "{0}({1},1,1) in ('マ','ミ','ム','メ','モ')"
        ElseIf kana = KanaSearchType.Ya Then
            sFilter = "{0}({1},1,1) in ('ヤ','ユ','ヨ','ャ','ュ','ョ')"
        ElseIf kana = KanaSearchType.Ra Then
            sFilter = "{0}({1},1,1) in ('ラ','リ','ル','レ','ロ')"
        ElseIf kana = KanaSearchType.Wa Then
            sFilter = "{0}({1},1,1) in ('ワ','ヲ','ン')"
        ElseIf kana = KanaSearchType.Other Then
            sFilter = "{1} IS NULL OR {0}({1},1,1) not in ('ア','イ','ウ','エ','オ','ァ','ィ','ゥ','ェ','ォ'" & _
                                                        ",'カ','キ','ク','ケ','コ'" & _
                                                        ",'サ','シ','ス','セ','ソ'" & _
                                                        ",'タ','チ','ツ','テ','ト'" & _
                                                        ",'ナ','ニ','ヌ','ネ','ノ'" & _
                                                        ",'ハ','ヒ','フ','ヘ','ホ'" & _
                                                        ",'マ','ミ','ム','メ','モ'" & _
                                                        ",'ヤ','ユ','ヨ','ャ','ュ','ョ'" & _
                                                        ",'ラ','リ','ル','レ','ロ'" & _
                                                        ",'ワ','ヲ','ン')"
        End If


        If Not String.IsNullOrEmpty(sFilter) Then
            sFilter = String.Format(sFilter, funcNm, sFieldNm)
        End If
        Return sFilter
    End Function
End Class

0 件のコメント: