Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2012.05.06;
Скачать: [xml.tar.bz2];

Вниз

Сортировка 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.004 c
2-1325855150
Anthony
2012-01-06 17:05
2012.05.06
Иконка для приложения


2-1325802985
Дмитрий
2012-01-06 02:36
2012.05.06
Scheduler


2-1326020364
Gu
2012-01-08 14:59
2012.05.06
dllmain vs init-final


2-1325795317
Gu
2012-01-06 00:28
2012.05.06
stdcall


2-1325978911
Gu
2012-01-08 03:28
2012.05.06
Exception dll





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский