Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сортировка данных в колонках ListView  (Прочитано 11453 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Shouldercannon
Помогающий

ru
Offline Offline

« : 11-03-2011 10:18 » 

Так делается сортировка для двух колонок;
Код:
procedure TForm1.ListView1ColumnClick(Sender: TObject;
  Column: TListColumn);
begin
  if FSortKey = Column.Index + 1 then FSortKey := -FSortKey else FSortKey := Column.Index + 1;
  if ListView1.SortType <> stText then ListView1.SortType := stText else ListView1.AlphaSort;
end;

procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem;
  Data: Integer; var Compare: Integer);
var
  N1, N2: Integer;
begin
  if Abs(FSortKey) = 1 then Compare := AnsiCompareText(Item1.Caption, Item2.Caption)
  else
  begin
N1 := StrToInt(Item1.SubItems[Abs(FSortKey) - 2]);
N2 := StrToInt(Item2.SubItems[Abs(FSortKey) - 2]);

if N1 = N2 then Compare := 0 else if N1 < N2 then Compare := -1 else Compare := 1;
  end;
  Compare := Compare * (FSortKey div Abs(FSortKey));
end;
Но это только для двух колонок, а если их три, четыре или более?
FSortKey - номер колонки.
Код:
  if Abs(FSortKey) = 1 then
begin
end
  else
  if Abs(FSortKey) = 2 then
begin
end
  else
  if Abs(FSortKey) = 3 then
begin
end;
Как тут сделать сортировку не знаю.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 11-03-2011 10:35 » 

Shouldercannon, а чего ты хочешь? сортировать 3 конкретные колонки или сортировать любое количество выбранных пользователем колонок?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Shouldercannon
Помогающий

ru
Offline Offline

« Ответ #2 : 11-03-2011 18:43 » 

Сортировать любое количество выбранных пользователем колонок.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 11-03-2011 19:41 » 

Shouldercannon, есть ли соответствующие встроенные средства в ListView, я не знаю - уже 8 лет не работал с Delphi.

Если же делать вручную, то нужно придумывать алгоритм и соответствующую ему структуру данных.

Например, собрать все колонки в список в порядке сортировки.
Затем в обрабатывать строчки ListView алгоритмом сортировки, вызывая в качестве функции сравнения нижеописанную.

Функция сравнения принимает в качестве аргументов две сравниваемые строчки ListView и упорядоченный список колонок сортировки.
В цикле по колонкам сортировки:
Извлечь из первой и второй строк значения текущей колонки и сравнить их.
Если сравнение даёт "больше" или "меньше", закончить цикл.
Если сравнение даёт "равно", продолжать цикл, пока не закончится список колонок.
Функция должна вернуть результат последнего сравнения.

Естественно, это для случая, когда все колонки сортируются в одном порядке. Если же сортировки по колонкам разнонаправленные, то нужно инвертировать результат сравнения для колонок, сортируемых в обратном порядке.
« Последнее редактирование: 11-03-2011 19:43 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Shouldercannon
Помогающий

ru
Offline Offline

« Ответ #4 : 12-03-2011 18:25 » 

Код:
  ...

  FSortKey: Integer;     //  Теперь в самом деле используется как номер колонки
  FBackSort: Boolean;  //   Направление сортировки
 
  ...

procedure TForm1.ListView1ColumnClick(Sender: TObject;
  Column: TListColumn);
begin
  if (FSortKey = Column.Index) then // Если это та же самая колонка - меняем направление сортировки
    FBackSort := not FBackSort
  else                                             // иначе - прямая сортировка
    FBackSort := False;

  FSortKey := Column.Index;
  ListView1.AlphaSort;
end;

procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem;
  Data: Integer; var Compare: Integer);
var
 N1, N2, SubItemInd: Integer;
begin
  if (FSortKey > 0) then  // Сортируем по субайтемсам
  begin
    SubItemInd := FSortKey -1;

    // StrToInt не годится, потому как вызовет ошибку если строчка пустая
    // либо не приводится к числу. Поэтому StrToIntDef

    N1 := StrToIntDef(Item1.SubItems[SubItemInd],0);
    N2 := StrToIntDef(Item2.SubItems[SubItemInd],0);

    if FBackSort then        // Обратная сортировка
      Compare := N2 - N1
    else                     // Прямая сортировка
      Compare := N1 - N2;
  end
  else                    // Сортируем по капшену айтемса
  begin
    if FBackSort then     // Обратная сортировка
      Compare := AnsiCompareText(Item2.Caption,Item1.Caption)
    else                  // Прямая сортировка
      Compare := AnsiCompareText(Item1.Caption,Item2.Caption);
  end;
end;
Сортировка перестаёт работать если в колонках есть что-то на подобии: 00:12:05 или русские буквы (один символ), или латиские буквы (один символ), или данные типа 1/2.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 13-03-2011 05:10 » new

Shouldercannon, а что тут вообще написано? Какие-то дикие условия, что если это первая колонка, то сравниваем строки, иначе числа. Естественно, строки, которые содержат не числа, в числа не преобразуются. А в чём заключается твой вопрос?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines