Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 |

 

  Вопрос: кто знает (расширенная сорировка)? Добавлено: 26.10.06 17:10  

Автор вопроса:  Marki
Кто может помочь с ответом на вопрос:
-----
имеется объект DataGridView с несколькими столбцами.
В него заливаются данные, полученные путем запроса SQL с указанием сортировки по нескольким столбцам.
В результате изменения данных необходима их пересортировка для сохранения порядка отображения.
Каим образом отсортировать по нескольким столбцам одновременно?
сортировка требуется по ТРЕМ столбцам.
-----
например, есть столбец "город", "улица", "фамилия".
условно говоря при переезде человека с адреса на адрес или с города в город его положение в списке изменялось. Ну или если человек, например, сменил фамилию )))

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 1
Автор ответа:
 AKE



Вопросов: 0
Ответов: 7
 Профиль | | #1 Добавлено: 26.10.06 23:09

Создай в таблице(таблицах) дополнительное поле (например SORT_ORDER)заполни его как тебе нужно и сортируй по нему! В Select-e это поле можно не указывать, или сделать ширину колонки=0... Вообще то непонятно, при смене фамилии -нужно менять положение или нет!?

Ответить

Номер ответа: 2
Автор ответа:
 Marki



Вопросов: 42
Ответов: 94
 Профиль | | #2 Добавлено: 26.10.06 23:21
Создай в таблице(таблицах) дополнительное поле (например SORT_ORDER)заполни его как тебе нужно

еще раз, но БОЛЬШИМИ БУКВАМИ:

СОРТИРОВАТЬ =Н А Д О= ПО НЕСКОЛЬКИМ СТОЛБЦАМ. ЕЩЕ РАЗ: =ПО Н Е С К О Л Ь К И М=
создание дополнительного столбца приводит к необходимости его заполнения перед сортировкой.
Специально для Вас =персональный= вопрос:
КАКИМ ОБРАЗОМ МНЕ ЗАПОЛНИТЬ НОВЫЙ СТОЛБЕЦ, ЕСЛИ ЗАПОЛНИТЬ ЕГО НАДО ТАК ЧТОБЫ СОРТИРОВКА ПРОИЗВОДИЛАСЬ С УЧЕТОМ ДАННЫХ, РАСПОЛОЖЕННЫХ В ТРЕХ СТОЛБЦАХ.

Всем - сорри за капс. Надеюсь в дальнейшем на ответы по существу.

Ответить

Номер ответа: 3
Автор ответа:
 AKE



Вопросов: 0
Ответов: 7
 Профиль | | #3 Добавлено: 27.10.06 00:25
Не обижайтесь, но действительно непонятно, что должно произойти (или не произойти)при изменении фамилии или адреса. Если человек должен остаться в той же позиции где и был, то дополнительный столбец и будет являться уникальным, никогда не изменяемым идентификатором личности, присвоенным ей автоинкрементацией (генератором, триггером или др. в зависимости от СУБД)при внесении нового человека в БД.
Ответ на "специальный" вопрос: Новый столбец заполняется при INSERте новой записи автоматически согласно "...порядка отображения" известного(надеюсь) пока только Вам.

Ответить

Номер ответа: 4
Автор ответа:
 Marki



Вопросов: 42
Ответов: 94
 Профиль | | #4 Добавлено: 27.10.06 00:44
еще раз постараюсь пояснить задачу на придуманном примере:
1) столбец 1 - город
2) столбец 2 - улица
3) столбец 3 - ФИО
4) столбцы, не участвующие в сортировке

Требуется группировка по городам (например по возрастанию), внутри каждого города - по улице, и уже внутри каждой улицы - по ФИО.
Человек может переезжать в другой город с сохранением своих ФИО и например на такую же улицу - но он уже должен "переместиться" в группу другого города, там его улица должна попасть в соответствии с порядком сортировки на требуемое место и соответственно его ФИО - так же внутри "группы улицы" (если такая уже есть и там кто-то записан) должны быть отсортированы.

Т.е. ЛЮБОЕ изменение данных в трех первых столбцах требует сортировки сначала по первому столбцу, затем НЕ нарушая эту сортировку - по следующему и т.д.

Если совсем оказалось неясно - АНАЛОГОМ является сортировка в Excel:
при выборе сортировки предлагается:
СНАЧАЛА СОРТИРУЕМ ПО СТОЛБЦУ ИКС, ЗАТЕМ ПО СТОЛБЦУ ИГРЕК И ЗАТЕМ ПО СТОЛБЦУ ЗЭТ.

Ответить

Номер ответа: 5
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #5 Добавлено: 27.10.06 00:53
А что тебе мешает после изменения данных выполнить новый запрос к БД и вернуть уже отсортированный по твоим полям набор записей?
Или у тебя обязательным условием является сортировака средствами исключительно DataGridView?

Ответить

Номер ответа: 6
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #6 Добавлено: 27.10.06 01:03
И еще... насколько я знаю, этот контрол имеет замечательный метод - DataGridView.Sort(IComparer) И все,что тебе надо сделать - это написать класс,реализующий интерфейс IComparer и передать его в качестве аргумента методу Sort контрола DataGridView.. и будет тебе щастье!!!
Таким образом ты можешь отсортировать хоть по 23-м столбцам.. потому что реализию сортировки ты будешь писать сам в этом классе...

Ответить

Номер ответа: 7
Автор ответа:
 Marki



Вопросов: 42
Ответов: 94
 Профиль | | #7 Добавлено: 27.10.06 01:08
сделать хочется действительно именно без запроса к базе... т.к. возможна ситуация что данные вносятся именно в список, без записи в саму базу.

В отношении IComparer - гм... метод есть, посмотрел в помощи до обращения сюда, но не уловил его сути (((

Ответить

Номер ответа: 8
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #8 Добавлено: 27.10.06 01:17
Суть проста.. Дело в том, что DataGridView не имеет ни малейшего представления о том, что за данные находятся в твоих столбцах, как ты хочешь их сортировать и в каком порядке. Критериев сортировки может быть туча.. Для этого и создается этот класс. В нем пищшешь реализацию единственного метода Comparer,который будет и будет сравнивать строки в твоем наборе данных.. вот собственно и все...

Ответить

Номер ответа: 9
Автор ответа:
 Marki



Вопросов: 42
Ответов: 94
 Профиль | | #9 Добавлено: 27.10.06 01:37
В нем пищшешь реализацию единственного метода Comparer,который будет и будет сравнивать строки в твоем наборе данных.. вот собственно и все...


вот это "все" я как раз пока и не догнал, в результате чего стал искать другие пути решения той же задачи.

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 27.10.06 02:23
Нууу, блин.. дружище.. а ты не пробовал набрать в гугле DataGridView.Sort(IComparer)? Нет?
К твоему удивлению вывалиться туева хуча ссылок с деталями реализации этого класса..
Вот одна из них..
http://msdn2.microsoft.com/en-us/library/wstxtkxs.aspx

Ответить

Номер ответа: 11
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #11 Добавлено: 27.10.06 05:03
Помойму глупо сортировать программно если можно запросом вынуть данные.

Воопервых оно быстрее будет, без ошибок... а главное легче реализовывается...

Ответить

Номер ответа: 12
Автор ответа:
 Marki



Вопросов: 42
Ответов: 94
 Профиль | | #12 Добавлено: 27.10.06 09:20
2 EROS - спасибо, ссылку посмотрю.

2 HACKER - сложно раговаривать с самим собой. Это я про себя и так, на всякий случай.
т.к. возможна ситуация что данные вносятся именно в список, без записи в саму базу

Ответить

Номер ответа: 13
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #13 Добавлено: 27.10.06 18:14
Воопервых оно быстрее будет, без ошибок... а главное легче реализовывается...


HACKER, ну не скажи... на счет быстрее вопрос спорный.. поскольку обращение к БД принято считать очень ресурсоемким процессом, и дергать БД лишний раз не есть хороший тон в программировании.. Легче-да.. тут я с тобой согласен, хотя и реализация этого метода сложной не назовешь. Этот способ сортировки не имеет ничего общего с известными тебе способами сортировки методами "пузырька" и ему подобным. Его задача сравнить в этой ф-ии 2 строки X & Y и вернуть один из 3 результатов.. -1,0,1 - вот и все! Вся реализация займет 7-10 строчек кода. Никаких перестановок в массиве и прочих прелестей сортировки VB6. Зато гибкость и управляемость кода налицо.

Ответить

Номер ответа: 14
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #14 Добавлено: 27.10.06 21:32
Вот что то от нефига делать, решил протестировать этот метод сортировки..

''' <summary>
''' Test DataGridView.Sort(IComparer)
''' </summary>
''' <remarks>
''' Add to form:
''' - DataGridView (Name = DataGridView1)
''' - Button       (Name = btnSort)
''' </remarks>
Public Class Form1


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

        '// Заполняем DataGridView тестовыми данными
        Dim arrayFamily() As String = New String() {"Иванов", _
                                                    "Петров", _
                                                    "Сидоров", _
                                                    "Козлов", _
                                                    "Смирнов", _
                                                    "Васильев"}

        Dim arrayFirstName() As String = New String() {"Иван", _
                                                       "Николай", _
                                                       "Михаил", _
                                                       "Пётр", _
                                                       "Василий", _
                                                       "Вячеслав"}

        Dim arrayLastName() As String = New String() {"Александрович", _
                                                      "Владимирович", _
                                                      "Федорович", _
                                                      "Семенович"}

        With DataGridView1.Columns
            .Add("columnNumber", "№ п/п";)
            .Add("columnFamily", "Фамилия";)
            .Add("columnFirstName", "Имя";)
            .Add("columnLastName", "Отчество";)
        End With

        Dim Rnd As New Random

        For Counter As Int32 = 1 To 1000 '// Rows count

            '// Первое поле (№ строки) для контроля сортировки
            ;DataGridView1.Rows.Add(New String() {Counter.ToString, _
                                             arrayFamily(Rnd.Next(0, arrayFamily.Length)), _
                                             arrayFirstName(Rnd.Next(0, arrayFirstName.Length)), _
                                             arrayLastName(Rnd.Next(0, arrayLastName.Length))})

        Next

    End Sub

    Private Sub btnSort_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles btnSort.Click

        Dim stopWatch As New Stopwatch
        stopWatch.Start()

        '// Сортируем данные по 3 полям
        ;DataGridView1.Sort(New RowComparer)

        stopWatch.Stop()

        '// Show result
        MessageBox.Show(String.Format("Sorting result is {0} ms", stopWatch.Elapsed.TotalMilliseconds), _
                        "Test DataGridView.Sort(IComparer)", _
                        MessageBoxButtons.OK, _
                        MessageBoxIcon.Information)

    End Sub

    ''' <summary>
    ''' Приватный класс для сортировки строк DataGridView
    ''' Реализуем интерфейс System.Collections.IComparer
    ''' </summary>
    ''' <remarks>Регистр не учитываем (IgnoreCase = True)</remarks>
    Private Class RowComparer
        Implements Collections.IComparer

        Public Function Compare(ByVal x As Object, _
                                ByVal y As Object) As Integer _
                                Implements System.Collections.IComparer.Compare

            Dim rowX As DataGridViewRow = TryCast(x, DataGridViewRow)
            Dim rowY As DataGridViewRow = TryCast(y, DataGridViewRow)
            Dim compareResult As Int32

            '// Проверяем входные данные
            If rowX Is Nothing OrElse _
               rowY Is Nothing Then Throw New ArgumentNullException("X or Y Is Nothing...";)

            '// Сравниваем 2 фамилиии
            compareResult = String.Compare( _
                                    rowX.Cells(1).Value, _
                                    rowY.Cells(1).Value, _
                                    True) '// Игнорируем регистр

            '// Если они равны, то сравниваем имена
            If compareResult = 0 Then _
                compareResult = String.Compare( _
                                        rowX.Cells(2).Value, _
                                        rowY.Cells(2).Value, _
                                        True)

            '// Если снова одинаковые, то сравниваем отчества
            If compareResult = 0 Then _
                compareResult = String.Compare( _
                                        rowX.Cells(3).Value, _
                                        rowY.Cells(3).Value, _
                                        True)

            '// Возвращаем результат вызова
            Return compareResult

        End Function

    End Class

End Class


Результат на моей машине 16,0479 ms
Сортировка по 3 полям для 1000 строк.. по- моему вполне приемлемо. На БД не тестил, но думаю, что на небольших объемах данных результат не сильно будет отличаться...

Ответить

Номер ответа: 15
Автор ответа:
 HACKER


 

Разработчик Offline Client

Вопросов: 236
Ответов: 8362
 Профиль | | #15 Добавлено: 28.10.06 01:58
Гы :) действительно х.з. с быстродействием, не тестил (хотя думаю уж точно не медленее)... но по поводу реализации...

Путь какой-то грид будет привязан как рекордсет... тогда вся сортировка седется к sql запросу:

DB.Execute ("SELECT * FRON table ORDER BY [Поле] ASC ";)...

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам