Форум: "Начинающим";
Текущий архив: 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