Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Расчеты из полей с датой


Автор: crem78 4.8.2008, 14:13
Доброго время суток, господа эксперты. Есть две задачи, вроде решаются просто, но с чего подойти, толком не знаю. Итак, первое: - Есть компонент Table, DBGrid, поле с датой из базы, назовем ее Data1. При нажатии кнопки должна происходить процедура. Берется текущая дата на сегодня, к ней прибавляется неделя или 7 дней, получается результат расчета (число месяц год). Если результат совпадает со строчкой в поле Data1, то строка закрашивается красным цветом. smile 

Вторая задача, такого же типа  только наоборот. Из текущей даты вычитаем 3 месяца (90 дней), полученный результат сверяется с полем Data 2, если совпадает, строка закрашивается зеленым цветом.
 smile 

Автор: Savek 4.8.2008, 14:24
Код

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin

if Column.FieldName='Data1' then
  if Column.Field.AsDateTime=Date+7 then
      DBGrid1.Canvas.Brush.Color:=clRed;

if Column.FieldName='Data2' then
  if Column.Field.AsDateTime=Date-90 then
      DBGrid1.Canvas.Brush.Color:=clGreen;

DBGrid1.DefaultDrawColumnCell(rect,DataCol,column,state);

end;

Автор: pseud 4.8.2008, 15:42
crem78Savek
3 месяца - все-таки никогда не равны 90 (кроме январь_фераль_март);

Код

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  d: TDate;
begin
  if Column.FieldName = 'Data1' then
  begin
    d := Integer(Column.Field.AsDateTime); // чтобы не мешала временная составляющая
    d := d - 7;
    if d = Date then
      DBGrid1.Canvas.Brush.Color := clRed;
  end else
  if Column.FieldName = 'Data2' then
  begin
    d := Integer(Column.Field.AsDateTime);
    IncMonth(d, 3); // именно 3 месяца, а не 90 дней
    if d = Date then
      DBGrid1.Canvas.Brush.Color:=clGreen;
  end;

  DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;


Автор: crem78 4.8.2008, 17:35
Хорошо, а если использовать SQL запросы, какой результат. Думаю, что только он имеет такие широкие возможности. В SQL запросах не селен, помогите решить задачи. smile 

Автор: Poseidon 4.8.2008, 19:15
Используя SQL-запрос ты не закрасишь строку в DBGrid. И вообще, ты не правильно понимаешь суть задачи. Ты получаешь данные в DBGrid и исходя из этих данных должен закрасить одну из строк DBGrid. Получается, что от БД тебе нужно только получить данные. Закрашивание уже происходит на уровне компонента DBGrid, а не на уровне базы. SQL-запросы работают на уровне базы. Вот если тебе надо получить из БД только данные, удовлетворяющие условию "Если результат совпадает...", то тогда можно. Но, как я понимаю, тебе нужно видеть все данные, и только нужные выделять закрашиванием. Тогда через DrawColumnCell, как тебе и подсказали.

Автор: crem78 5.8.2008, 07:30
Цитата(pseud @ 4.8.2008,  15:42)
crem78Savek
3 месяца - все-таки никогда не равны 90 (кроме январь_фераль_март);

Код

   d := Integer(Column.Field.AsDateTime); // чтобы не мешала временная составляющая

Пишет ошибку: Invalid typecast smile 

А по поводу 90 дней или 3 месяцев, так ты прав необходимо 3 месяца. smile

Добавлено @ 07:30
Что про SQL запросы, так понимаю, что он работает на уровне запросов. Если попробовать выдернуть данные из базы, как код запроса будет выглядеть? В последующем передать их допустим в QReport  smile 

Автор: pseud 5.8.2008, 09:24
Цитата(crem78 @  5.8.2008,  07:30 Найти цитируемый пост)
Пишет ошибку: Invalid typecast


Код

d := Int(Column.Field.AsDateTime);


Добавлено через 2 минуты и 15 секунд
Цитата(crem78 @  5.8.2008,  07:30 Найти цитируемый пост)
 Если попробовать выдернуть данные из базы, как код запроса будет выглядеть?

ответ на твой вопрос прост:
Код

select
  *
from 
  dual
 
как говорится "какой вопрос"

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

Добавлено через 3 минуты и 47 секунд
да и что за БД не забудь указать.
а то, если надо выдернуть нечто специфическое, то у каждой БД свои особенности языка SQL.

Автор: crem78 5.8.2008, 11:59
 smile Спасибо за помощь, воспользовался следующим кодом:

Код

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  d: TDate;
begin
  if Column.FieldName = 'Data1' then
  begin
    d := Integer(Column.Field.AsDateTime); // чтобы не мешала временная составляющая
    d := d - 7;
    if d = Date then
      DBGrid1.Canvas.Brush.Color := clRed;
  end else
  if Column.FieldName = 'Data2' then
  begin
    d := Integer(Column.Field.AsDateTime);
    IncMonth(d, 3); // именно 3 месяца, а не 90 дней
    if d = Date then
      DBGrid1.Canvas.Brush.Color:=clGreen;
  end;

  DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;


Теперь вопрос на засыпку, если за место строки в коде:

Код

DBGrid1.Canvas.Brush.Color := clRed;


Прописать отправку найденных строк в Qreport, возможно ли это организовать, если да то как? smile 

Автор: pseud 5.8.2008, 13:48
Цитата(crem78 @  5.8.2008,  11:59 Найти цитируемый пост)
Прописать отправку найденных строк в Qreport


1. точно не в этом методе.
2. лучше сформировать отдельную выборку SQL. метод формирования выборки зависит от используемой СУБД.

Добавлено через 13 минут и 16 секунд
предположим у тебя база Paradox
тогда можешь подключить к отчету приблизительно такой DataSet
Код

  with Query1 do
  begin
    Active := False;
    SQL.Clear;
    SQL.Add('SELECT          ');
    SQL.Add('  *             ');
    SQL.Add('FROM            ');
    SQL.Add('  таблица t     ');
    SQL.Add('WHERE           ');
    SQL.Add('  t.Data1 + 7 < ' + QuotedStr(DateToStr(Date)));
    Active := True;
  end;

Автор: crem78 6.8.2008, 16:16
Цитата(pseud @ 5.8.2008,  13:48)
Цитата(crem78 @  5.8.2008,  11:59 Найти цитируемый пост)
Прописать отправку найденных строк в Qreport


1. точно не в этом методе.
2. лучше сформировать отдельную выборку SQL. метод формирования выборки зависит от используемой СУБД.

Добавлено @ 14:01
предположим у тебя база Paradox
тогда можешь подключить к отчету приблизительно такой DataSet
Код

  with Query1 do
  begin
    Active := False;
    SQL.Clear;
    SQL.Add('SELECT          ');
    SQL.Add('  *             ');
    SQL.Add('FROM            ');
    SQL.Add('  таблица t     ');
    SQL.Add('WHERE           ');
    SQL.Add('  t.Data1 + 7 < ' + QuotedStr(DateToStr(Date)));
    Active := True;
  end;

Пробовал использовать твой код:

Код

with Query1 do
  begin
    Active := False;
    SQL.Clear;
    SQL.Add('SELECT          ');
    SQL.Add('  *             ');
    SQL.Add('FROM            ');
    SQL.Add('"base.DB" Base');
    SQL.Add('WHERE           ');
    SQL.Add('Base.Otsldata + 7 < ' + QuotedStr(DateToStr(Date)));
    Active := True;
  end;


В итоге DBGide не остается не одной строчки.  smile  smile 
Недавно начал использовать  FastReport 4.0, все нравиться. Вопрос до сих пор остается открытый, как организовать задачи для передачи результатов в рапорт, а именно FastReport 4.0?   smile 

Автор: Poseidon 6.8.2008, 23:47
Цитата(crem78 @  6.8.2008,  16:16 Найти цитируемый пост)
В итоге DBGide не остается не одной строчки. 
DBGide - это что? И у тебя в проекте только приведенный код? Query1 у тебя вообще связана с БД? С Query1 что-нибудь связано?

Цитата(crem78 @  6.8.2008,  16:16 Найти цитируемый пост)
как организовать задачи для передачи результатов в рапорт, а именно FastReport 4.0
Ты мне вот раскажи, как ты вообще передаешь данные в отчет? Все-равно какие данные. Как ты это делаешь? Что-то мне подсказывает, что тут вопрос более глобальный, чам просто "подскажите как сделать конкретно вот это". Вообще понимаешь весь смысл создания отчета? Что, откуда и как берется? Покажи хоть как сам пробовал создать отчет.

Автор: crem78 7.8.2008, 15:06
Сначала была задача просто сделать раскраску для строк при определенных условия (кто не помнит, смотри выше). Теперь задача несколько поменялась. Необходимо вывести отбор записей по условиям и передать их в отчет. Прочитав множество материалов про FastReport, узнал множество интересного, а именно про то, что внутри программы имеется скриптовый язык (PascalScript, C++Script, Jscript, BasicScript). Т.е. перед тем, как отчет будет создан, можно задать условия, по которым отчет должен формироваться. В моем случае задача простая, но большими знаниями в разработке программ просто не имею, поэтому прошу помочь мне в моей задаче. Если спросите, что есть же PascalScript он простой, написан 100% на PascalObject, скажу, просто не помню. Использую базу base.DB, компоненты Table, DBGrid. Вроде бы все, что нужно было, создал, но остался последний рывок, это формирование отчетов. Посоветуйте как решить задачу. smile  smile 

Автор: Kbl4AH 7.8.2008, 15:33
2crem78, а зачем тебе вообще DBGrid, если результат запроса нужно вернуть только в отчет? Делай нужную выборку данных при помощи DataSet и сразу в отчет вставляй.

Автор: crem78 7.8.2008, 17:37
Дык, DBGrid мне и не нужен, мне и нужно сразу ставить в отчет выборку. Т.е. в отчете должны быть только отфильтрованные строки, строки по условию. Меня интересует конкретный пример как это реализовать. Спасибо.  smile 

Автор: Akella 7.8.2008, 21:45
Цитата(crem78 @  4.8.2008,  14:13 Найти цитируемый пост)
3 месяца (90 дней)

учти, что 3 месяца <> 90 дней!!!

Автор: morpheyushka 8.8.2008, 11:55
если хочешь делать это дело на уровне SQL-запроса, то тебе поможет чудо функция DATEDIFF ( datepart , startdate , enddate )

Цитата

Syntax
DATEDIFF ( datepart , startdate , enddate ) 

Arguments
datepart

Is the parameter that specifies on which part of the date to calculate the difference. The table lists dateparts and abbreviations recognized by Microsoft® SQL Server™.

Datepart            Abbreviations 

Year                      yy, yyyy 
quarter                  qq, q 
Month                    mm, m 
dayofyear              dy, y 
Day                        dd, d 
Week                    wk, ww 
Hour                      hh 
minute                   mi, n 
second                  ss, s 
millisecond             ms 


startdate

Is the beginning date for the calculation. startdate is an expression that returns a datetime or smalldatetime value, or a character string in a date format. 

Because smalldatetime is accurate only to the minute, when a smalldatetime value is used, seconds and milliseconds are always 0.

If you specify only the last two digits of the year, values less than or equal to the last two digits of the value of the two digit year cutoff configuration option are in the same century as the cutoff year. Values greater than the last two digits of the value of this option are in the century that precedes the cutoff year. For example, if the two digit year cutoff is 2049 (default), 49 is interpreted as 2049 and 2050 is interpreted as 1950. To avoid ambiguity, use four-digit years.

For more information about specifying time values, see Time Formats. For more information about specifying dates, see datetime and smalldatetime. 

enddate

Is the ending date for the calculation. enddate is an expression that returns a datetime or smalldatetime value, or a character string in a date format.

Return Types
integer


И смотри разницу хоть в месяцах, хоть в днях, хоть в неделях - вобщем как хочешь)

ЗЫ Если что то не понятно - пиши, реализуем!

Автор: pseud 8.8.2008, 15:18
morpheyushka
Цитата(crem78 @  7.8.2008,  15:06 Найти цитируемый пост)
Использую базу base.DB


Цитата(morpheyushka @  8.8.2008,  11:55 Найти цитируемый пост)
 by Microsoft® SQL Server™.

ну и при чем здесь жареные гвозди?

Автор: morpheyushka 8.8.2008, 15:36
Цитата(pseud @  8.8.2008,  15:18 Найти цитируемый пост)
ну и при чем здесь жареные гвозди? 

Да я просто из справки цитату сделал...суть же не в этом...человек хочет разницу в датах получить, причем, если я правильно понял, на уровне запроса. Вот я и подсказал ему функцию, которая облегчает в данной ситуации жизнь smile 
А в цитате синтаксис расписан (правда на англ. языке)...чего тут не понятно? smile 

Автор: pseud 8.8.2008, 16:46
Цитата(morpheyushka @  8.8.2008,  15:36 Найти цитируемый пост)
чего тут не понятно?


я не спорю, что в MS SQL твоя чудесная функция заработает.
можно еще накопать кучу функций из Oracle, Informix и пр.
но ни одна из них не заработает.
думаю ты уже догадался почему.

Автор: morpheyushka 8.8.2008, 17:29
Цитата(pseud @  8.8.2008,  16:46 Найти цитируемый пост)
думаю ты уже догадался почему.

да...теперь понял...просто увидел слово SQL и включил бронь по поводу Microsoft SQL Server.
Перечитал заново ветку, и не нашел ни одного слова про тип базы)))


Интересно, а можно съехать на конец рабочей недели smile 

Автор: crem78 16.8.2008, 09:21
Съехать на конец рабочей недели можно, а иногда даже нужно. Как говориться, если долго мучиться, что ни будь получиться. Так оно и вышло. Воспользовался всеми вашими советами и рекомендациями, получилось то, что хотел. Теперь запрос работает правильно, да еще и в отчет передает. Спасибо большое за помощь, очень помогли. Тема закрыта.  smile  smile 

Автор: crem78 16.8.2008, 12:18
В поисках решения, подсказали еще одно решение, может кому тоже поможет. smile 

Все зависит от конкретной СУБД.
Но схема одна:
(продолжаем):

Код

SELECT *
FROM "base.DB" Base
where Otsldata=sysdate+ to_date('7', 'dd);

и 
...
where Syd=sysdate- to_date('3', 'mm');


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)