Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.05.06;
Скачать: CL | DM;

Вниз

Сортировка StringGrid по времени   Найти похожие ветки 

 
cardon   (2012-01-05 00:25) [0]

В общем есть StringGrid в котором 3 столбца. Первый из них фиксированный. Остальные начиная с 0 все редактируемые.

1) Время когда необходимо произвести звонок в формате чч:мм:сс
2) Имя Предмета
3) Время оставшееся до звонка в формате чч:мм:сс

Необходимо сделать сортировку по 3 колонке.
К примеру в 3 колонке 8 строк.

1) 0:23:31
2) 34:22:12
3) 2:35:3
4) 12:43:33
5) 23:31:44
6) 0:23:38
7) 3:25:18
8) 0:23:4

Задача расположить их в таком порядке

1) 0:23:4
2) 0:23:31
3) 0:23:38
4) 2:35:3
5) 3:25:18
6) 12:43:33
7) 23:31:44
8) 34:22:12

Так же в 3 колонке может ничего не быть на некоторых полях. Такие строки необходимо поставить в самый конец.

Нагуглил вот такой код. Но сортировка в данном варианте выполняется не правильно и не с 0 строки.

Если применить данный код то сортировка будет выглядеть вот так.

1) 0:23:31
2) 0:23:38
3) 0:23:4
4) 12:43:33
5) 2:35:3
6) 23:31:44
7) 3:25:18
8) 34:22:12



procedure SortStringGrid(var GenStrGrid: TStringGrid; ThatCol: Integer);
const
  // Define the Separator
 TheSeparator = "@";
var
  CountItem, I, J, K, ThePosition: integer;
  MyList: TStringList;
  MyString, TempString: string;
begin
  // Give the number of rows in the StringGrid
 CountItem := GenStrGrid.RowCount;
  //Create the List
 MyList        := TStringList.Create;
  MyList.Sorted := False;
  try
    begin
      for I := 1 to (CountItem - 1) do
        MyList.Add(GenStrGrid.Rows[I].Strings[ThatCol] + TheSeparator +
          GenStrGrid.Rows[I].Text);
      //Sort the List
     Mylist.Sort;

      for K := 1 to Mylist.Count do
      begin
        //Take the String of the line (K – 1)
       MyString := MyList.Strings[(K - 1)];
        //Find the position of the Separator in the String
       ThePosition := Pos(TheSeparator, MyString);
        TempString  := "";
        {Eliminate the Text of the column on which we have sorted the StringGrid}
        TempString := Copy(MyString, (ThePosition + 1), Length(MyString));
        MyList.Strings[(K - 1)] := "";
        MyList.Strings[(K - 1)] := TempString;
      end;

      // Refill the StringGrid
     for J := 1 to (CountItem - 1) do
        GenStrGrid.Rows[J].Text := MyList.Strings[(J - 1)];
    end;
  finally
    //Free the List
   MyList.Free;
  end;
end;


 
Германн ©   (2012-01-05 03:03) [1]


> Но сортировка в данном варианте выполняется не правильно

Она выполняется правильно, ибо сортируются текстовые строки, а не времена.


 
RWolf ©   (2012-01-05 11:01) [2]

Переведи строковые представления времён в какой-нибудь числовой формат (скажем, TDateTime) и выполни сортировку по этим значениям.


 
sniknik ©   (2012-01-05 11:44) [3]

> Если применить данный код то сортировка будет выглядеть вот так.
причем, если хранить время правильно (вроде ODBC каноникал) то будет так, даже со строками...  
1) 00:23:31
2) 00:23:38
3) 00:23:04
5) 02:35:03
7) 03:25:18
4) 12:43:33
6) 23:31:44
8) 34:22:12

хотя правильнее хранить как дататайм, в рекордсете например, тогда и сортировка будет правильная, быстрая, и саму ее писать не придется... хотя, принципы работы нужно будет пересмотреть/заменить.


 
sniknik ©   (2012-01-05 11:46) [4]

> 8) 34:22:12
???
это не время.


 
_Юрий   (2012-01-05 12:02) [5]

как бы я сделал:
1. Каждой строке грида соответствует объект с полем TDateTime
2. При отрисовке грида значения  ячеек берутся с объекта.
3. Объекты все время находятся в TList (или TList<T>, или рекордсете, короче - в контейнере), грид всего навсего отображает этот контейнер. Если контейнер изменился, грид перерисовывается.
4. Отсортировать сам контейнер (по TDateTime), в гриде окажется то, что требуется


 
Германн ©   (2012-01-05 17:12) [6]


> хотя правильнее хранить как дататайм


> sniknik ©   (05.01.12 11:46) [4]
>
> > 8) 34:22:12
> ???
> это не время.
>

Это период времени. Поэтому правильнее хранить количество секунд.


 
cardon   (2012-01-06 19:41) [7]

Почти все получилось сделал вот так

function SortDate(Item1, Item2: Pointer): Integer;
begin
 if PDateTime(Item1)^ < PDateTime(Item2)^ then Result:= -1 else
   if PDateTime(Item1)^ > PDateTime(Item2)^ then Result:= 1 else Result:= 0;
end;

procedure SortStringGrid(var GenStrGrid: TStringGrid; ThatCol: Integer);
var
  CountItem, i, J: integer;
  MyList: TList;
 pTime: PDateTime;
begin

 CountItem := GenStrGrid.RowCount;
 MyList        := TList.Create;

  try
    begin
      for J := 0 to (CountItem - 1) do  begin

      if GenStrGrid.Rows[J+1].Strings[ThatCol]<>"" then
       begin
         new(pTime); pTime^:= StrToTime(GenStrGrid.Rows[J+1].Strings[ThatCol]); MyList.Add(pTime);
         end;
          end;

     Mylist.Sort(SortDate);

     for i:= 0 to MyList.Count - 1 do begin
         GenStrGrid.Rows[i+1].ValueFromIndex[ThatCol]:= TimeToStr(PDateTime(MyList.Items[i])^);
        Dispose(MyList.Items[i]);
      end;
        end;
  finally
    //Free the List
   MyList.Free;
  end;
end;


Почти все хорошо кроме
1) Сортировка происходит не с 0 поля а с 1.
2) Непонятно откуда береться знак = перед временем в 3 столбце
3) При сортировке сортируется только 3 столбец. А мне необходимо чтобы с сортировкой 3 столбца перемещались и первые 2.


 
RWolf ©   (2012-01-06 21:38) [8]


> не с 0 поля а с 1

видимо, оттого, что Rows в этом коде считаются с 1 по GenStrGrid.RowCount.


> знак =

ну, а чего же ожидать, присваивая свойство ValueFromIndex.


> чтобы с сортировкой 3 столбца перемещались и первые 2.

тогда надо перемещать не только ThatCol, а и другие столбцы.


 
cardon   (2012-01-07 01:55) [9]

Спасибо очень помогли. Сделал все сортирует хорошо.
Но есть несколько проблем.
Вот код малоли кому понадобиться

function SortDate(Item1, Item2: Pointer): Integer;
begin
 if PMyItem(Item1)^.Time2 < PMyItem(Item2)^.Time2 then Result:= -1 else
   if PMyItem(Item1)^.Time2 > PMyItem(Item2)^.Time2 then Result:= 1 else Result:= 0;
end;

procedure SortStringGrid(var GenStrGrid: TStringGrid);
var
 L: TList;
 i,d,s: Integer;
 pTime: PMyItem;
begin
 s:=GenStrGrid.RowCount;

 L:= TList.Create; try

     for d:= 0 to s - 1 do begin
       new(pTime);
       pTime^.PredName:= GenStrGrid.Cells[1,d];

       if GenStrGrid.Cells[0,d]<>"" then
       pTime^.Time1:= StrToTime(GenStrGrid.Cells[0,d]) else
       pTime^.Time1:= StrToTime("23:59:59");

       if GenStrGrid.Cells[2,d]<>"" then
       pTime^.Time2:= StrToTime(GenStrGrid.Cells[2,d]) else
       pTime^.Time2:= StrToTime("23:59:59");
       L.Add(pTime);
   end;

   L.Sort(SortDate);

   for i:= 0 to L.Count - 1 do begin
     GenStrGrid.Rows[i].Strings[0]:= TimeToStr(PMyItem(L.Items[i])^.Time1);
     GenStrGrid.Rows[i].Strings[1]:= PMyItem(L.Items[i])^.PredName;
     GenStrGrid.Rows[i].Strings[2]:= TimeToStr(PMyItem(L.Items[i])^.Time2);
     Dispose(L.Items[i]);
   end;
 finally
   L.Free;
 end;
end;


1) В колонке 0 и 2 может время не стоять напротив предмета. Я это решил с помощью добавления времени им 23:59:59 но как понимаете это не выход из положения. Хотелось бы чтобы они просто добавлялись в самый конец StringGrid"a с теми же пустыми строками.
2) Если 2 и более предмета в одно и тоже время то они постоянно скачут по StringGrid"у между собой т.к. сортировка происходит каждую секунду хотелось бы чтобы этого не было. Чтобы на своих местах стояли постоянно а не скакали между собой.


 
RWolf ©   (2012-01-07 15:21) [10]


> чтобы они просто добавлялись в самый конец StringGrid"a
> с теми же пустыми строками.


> Чтобы на своих местах стояли постоянно


и то, и другое решается изменением функции SortDate так, чтобы она выдавала нужный порядок сортировки: пустые в конец, одинаковые ( в т.ч. одинаковые пустые) — по какому-то другому критерию.



Страницы: 1 вся ветка

Текущий архив: 2012.05.06;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.007 c
2-1325802985
Дмитрий
2012-01-06 02:36
2012.05.06
Scheduler


15-1324526689
И. Павел
2011-12-22 08:04
2012.05.06
Сайт, сделанный на ucoz.ru


2-1326069317
Gu
2012-01-09 04:35
2012.05.06
x64 str


2-1326047881
3asys
2012-01-08 22:38
2012.05.06
ADO Connection


15-1325661876
Свифт
2012-01-04 11:24
2012.05.06
раздача инета по wi-fi