Доброго времени суток, коллеги.
Есть задачка, по идеи банальнейшая. Но что-то не могу найти этого самого банального решения что бы оно было оптимальным.
Задача:
Реализовать календарик, в котором будут подсвечиваться те даты, на которые привязаны различные события (Дни Рождения, События, Праздники). И соответственно при выборе подсвеченной даты отобразить в TDBGrid события которые привязаны к выбранной дате.
Даты событий, хранятся в базе данных. В качестве БД используется MS Access.
Было у меня несколько попыток реализации, были и не работающие корректно и жутко тормозящие. Сейчас нашёл более менее реальное решение, но мне оно не нравится только потому что с ростом данных в базе, скорость отработки на мой взгляд будет падать на глазах.
Мой способ.
В качестве календаря использую MonthCalendar из набора компонент AlthaSkins. (он мне больше импанирует чем стандартный, более приятный юзабилити.)
У календаря есть событие со следующим кодом:
Код:
procedure TfmMainWin.smcCalendarGetCellParams(Sender: TObject;
Date: TDateTime; AFont: TFont; var Background: TColor);
begin
//Подсветим на календаре даты когда будут дни рождения, события, праздники,
if (data.qDatesHB.Active) and (data.qDatesHB.RecordCount > 0) then
begin
data.qDatesHB.First;
while not data.qDatesHB.Eof do
begin
If (DayOf(data.qDatesHB.Fields[0].AsDateTime) = DayOf(Date)) and
(MonthOf(data.qDatesHB.Fields[0].AsDateTime) = MonthOf(Date)) then
begin
Background := clYellow;
Break;
end;
data.qDatesHB.Next;
end;
end;
//Подсветим на календаре даты когда будут напоминания.
if (data.qRemDates.Active) and (data.qRemDates.RecordCount > 0) then
begin
data.qRemDates.First;
while not data.qRemDates.Eof do
begin
If DateOf(data.qRemDates.Fields[0].AsDateTime) = Date then
begin
Background := clYellow;
Break;
end;
data.qRemDates.Next;
end;
end;
end;
При этом
qDatesHB и
qRemDates это TADOQuery с запросами:
Код:
data.qDatesHB.SQL.Text := 'Select DISTINCT Date1 From Subject '+
' Union All '+
' Select DISTINCT DateDo '+
' From Holyday '+
' Union All '+
' Select DISTINCT DateEvent ' +
' From Event ';
data.qRemDates.SQL.Text := ' Select DISTINCT Date1 From Reminder ';
Ну и соответственно при изменении даты в календаре по событию делаем так:
Код:
procedure TfmMainWin.smcCalendarChange(Sender: TObject);
begin
if (Assigned(data)) then
data.OpenEvents(smcCalendar.CalendarDate);
end;
OpenEvents корректирует запрос, задавая нужную дату в условиях Where и таким образом выводит события за выбранную дату.
Весь затык в событии
smcCalendarGetCellParams, слишком не оптимально в цикле прокручивать строки DataSet'а, да ещё получается прокручивать его как минимум столько раз сколько дней в месяца и так каждый раз при переходе на новый месяц.
Вообще конечно работает и не дурно. Почти не заметно большой нагрузки на комп. Но просто не нравится мне такое решение и все тут. Не оптимально оно.
Кто может подкинуть более рациональную идею? Буду очень благодарен. Заранее спасибо
