Listviewのソートについて

解決


shellken  2007-06-28 02:53:25  No: 99112

Form1にListview1を貼り付けます。
以下を実行すると、数字のプラスマイナスを考えて、並べ替えが出来ませんが数字のプラスマイナスをも考慮したソートが出来るようにするにはどうしたらいいでしょうか?

'******************************************************************
Public Class LVSort

    'IComparerインターフェイス
    Implements IComparer

    Private mOrder As SortOrder = SortOrder.Ascending  'ソート順(昇順・降順)
    Private mKey As Integer = 0                        'ソート列

    'ソート順(昇順・降順)プロパティ
    Public Property Order() As SortOrder
        Get
            Return mOrder
        End Get
        Set(ByVal Value As SortOrder)
            mOrder = Value
        End Set
    End Property

    'ソート列プロパティ
    Public Property Key() As Integer
        Get
            Return mKey
        End Get
        Set(ByVal Value As Integer)
            mKey = Value
        End Set
    End Property

    '比較結果を返す
    Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
        Dim intRet As Integer

        Try
            '比較用リストアイテム格納変数
            Dim sx As ListViewItem = CType(x, ListViewItem)
            Dim sy As ListViewItem = CType(y, ListViewItem)

            '文字列を比較し、値を格納
            intRet = CompareString(sx.SubItems(mKey).Text, sy.SubItems(mKey).Text)

            '降順のときは結果を逆転
            If mOrder = SortOrder.Descending Then
                intRet = -intRet
            End If

        Catch ex As Exception

            Debug.WriteLine(ex.Message.ToString)

        End Try

        '結果を返す
        Return intRet

    End Function

    '文字列内の数値として認識できる部位を検査し、比較した値を返す
    Private Function CompareString(ByVal str1 As String, ByVal str2 As String) As Integer
        Dim chrNum() As Char = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
        Dim i As Integer
        Dim intPos As Integer
        Dim intLength As Integer
        Dim intNext1 As Integer
        Dim intNext2 As Integer
        Dim intRet As Integer
        Dim idx As Integer
        Dim idx1 As Integer
        Dim idx2 As Integer
        Dim lngNum1 As Long = -1
        Dim lngNum2 As Long = -1

        'はじめの文字列から数値として認識できる部分を探す
        idx1 = str1.IndexOfAny(chrNum)

        '見つかった場合
        If idx1 <> -1 Then
            '位置を格納
            intPos = idx1

            '長さの初期値
            intLength = 1

            '見つかった位置から文字列の終わりまで検査
            For i = idx1 + 1 To str1.Length - 1
                '数値として認識できるか検査
                idx = str1.Substring(i, 1).IndexOfAny(chrNum)

                '数値として認識できない場合は抜ける
                If idx = -1 Then Exit For

                '長さを格納
                intLength += 1
            Next

            '数値をLong値として格納
            lngNum1 = CType(str1.Substring(intPos, intLength), Long)

            '文字列の途中で終了した場合
            If intPos + intLength <> str1.Length Then
                'ループを抜けたポイントを格納
                intNext1 = intPos + intLength
            End If

        End If

        '次の文字列から数値として認識できる部分を探す
        idx2 = str2.IndexOfAny(chrNum)

        '見つかった場合
        If idx2 <> -1 Then
            '位置を格納
            intPos = idx2

            '長さの初期値
            intLength = 1

            '見つかった位置から文字列の終わりまで検査
            For i = idx2 + 1 To str2.Length - 1
                '数値として認識できるか検査
                idx = str2.Substring(i, 1).IndexOfAny(chrNum)

                '数値として認識できない場合は抜ける
                If idx = -1 Then Exit For

                '長さを格納
                intLength += 1
            Next

            '数値をLong値として格納
            lngNum2 = CType(str2.Substring(intPos, intLength), Long)

            '文字列の途中で終了した場合
            If intPos + intLength <> str2.Length Then
                'ループを抜けたポイントを格納
                intNext2 = intPos + intLength
            End If

        End If

        '数値が認識されなかったか、
        'または同じ位置ではない場合
        If idx1 = -1 Or idx2 = -1 Or (idx1 <> idx2) Then
            '単純比較を行なう
            intRet = String.Compare(str1, str2)
        Else

            '文字列の先頭が数値として認識されたか、
            'または数値より前の文字列が同じ場合
            If (idx1 = 0 And idx2 = 0) Or _
                (str1.Substring(0, str1.Length - (str1.Length - idx1)) = _
                str2.Substring(0, str2.Length - (str2.Length - idx2))) Then

                '数値として認識でき、ひとつめが大きい場合
                If lngNum1 <> -1 And lngNum2 <> -1 And lngNum1 > lngNum2 Then
                    '入れ替える値を格納
                    intRet = 1
                ElseIf lngNum1 <> -1 And lngNum2 <> -1 And lngNum1 < lngNum2 Then
                    '数値として認識でき、ひとつめが小さい場合は
                    '入れ替えない値を格納
                    intRet = -1
                ElseIf intNext1 <> 0 And intNext2 <> 0 Then
                    '文字列の最後まで調べていない場合は再帰
                    intRet = CompareString(str1.Substring(intNext1), str2.Substring(intNext2))
                Else
                    '入れ替えない値を格納
                    intRet = -1
                End If
            Else
                '数値より前の文字列が違う場合は単純比較
                intRet = String.Compare(str1, str2)
            End If
        End If

        '値を返す
        Return intRet

    End Function

End Class

'*********************************************************************
Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows フォーム デザイナで生成されたコード "

    Public Sub New()
        MyBase.New()
        InitializeComponent()
    End Sub

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private components As System.ComponentModel.IContainer

    Friend WithEvents ListView1 As System.Windows.Forms.ListView
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.ListView1 = New System.Windows.Forms.ListView
        Me.SuspendLayout()
        '
        'ListView1
        '
        Me.ListView1.Font = New System.Drawing.Font("MS ゴシック", 9.75!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(128, Byte))
        Me.ListView1.HideSelection = False
        Me.ListView1.Location = New System.Drawing.Point(12, 12)
        Me.ListView1.Name = "ListView1"
        Me.ListView1.Size = New System.Drawing.Size(404, 196)
        Me.ListView1.TabIndex = 1
        Me.ListView1.UseCompatibleStateImageBehavior = False
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 12)
        Me.ClientSize = New System.Drawing.Size(426, 223)
        Me.Controls.Add(Me.ListView1)
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle
        Me.MaximizeBox = False
        Me.Name = "Form1"
        Me.Text = "リストビューのソート"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'リストビューの初期設定
        ListView1.View = View.Details                        '詳細表示
        ListView1.HeaderStyle = ColumnHeaderStyle.Clickable  'カラムヘッダのクリック可能

        'リストビューの詳細表示用のヘッダ作成
        ListView1.Columns.Add("アイテム", 100, HorizontalAlignment.Left)
        ListView1.Columns.Add("サブ1", 100, HorizontalAlignment.Left)
        ListView1.Columns.Add("サブ2", 100, HorizontalAlignment.Right)

        ListView1.Items.Add("あああああ")
        ListView1.Items(0).SubItems.Add("fffff")
        ListView1.Items(0).SubItems.Add("33333")
        ListView1.Items.Add("いいいいい")
        ListView1.Items(1).SubItems.Add("ddddd")
        ListView1.Items(1).SubItems.Add("44444")
        ListView1.Items.Add("ううううう")
        ListView1.Items(2).SubItems.Add("aaaaa")
        ListView1.Items(2).SubItems.Add("-66666")
        ListView1.Items.Add("えええええ")
        ListView1.Items(3).SubItems.Add("eeeee")
        ListView1.Items(3).SubItems.Add("88888")
        ListView1.Items.Add("おおおおお")
        ListView1.Items(4).SubItems.Add("bbbbb")
        ListView1.Items(4).SubItems.Add("-77777")
        ListView1.Items.Add("かかかかか")
        ListView1.Items(5).SubItems.Add("hhhhh")
        ListView1.Items(5).SubItems.Add("55555")
        ListView1.Items.Add("ききききき")
        ListView1.Items(6).SubItems.Add("ggggg")
        ListView1.Items(6).SubItems.Add("-11111")
        ListView1.Items.Add("くくくくく")
        ListView1.Items(7).SubItems.Add("ccccc")
        ListView1.Items(7).SubItems.Add("22222")

    End Sub

    'カラムヘッダのクリック
    Private Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
        Static blnOrderFlg As Boolean
        Dim ccLVSort As LVSort = New LVSort

        With ccLVSort
            If blnOrderFlg Then
                '昇順
                .Order = SortOrder.Ascending
            Else
                '降順
                .Order = SortOrder.Descending
            End If

            'クリックされた列によりソートキーを指定
            .Key = e.Column
        End With

        'ListViewItemSorterプロパティへ、ソートの比較演算子を表すカスタムクラスを指定
        ListView1.ListViewItemSorter = ccLVSort

        'フラグ変数を反転
        blnOrderFlg = Not blnOrderFlg

    End Sub

   
End Class
'*********************************************************************


大吉末吉  2007-06-28 06:32:30  No: 99113

あれ?これってVB.NETですよね?
ここは「VB2-VB6専用」の掲示板ですよ。
VB.NETはお隣の「VB.NET掲示板(.NET専用)」をご利用ください。

> 数字のプラスマイナスをも考慮したソート

>             '文字列を比較し、値を格納
>             intRet = CompareString(sx.SubItems(mKey).Text, sy.SubItems(mKey).Text)

文字列のままではなく、一度数値に直してから比較するとか・・・


通り  2007-06-28 18:05:38  No: 99114

移動先
http://madia.world.coocan.jp/cgi-bin/vbnet/wwwlng.cgi?print+200706/07060036.txt


通り2  2007-07-11 23:00:27  No: 99115

とりあえず解決


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加