Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Calculated поля, которые зависят от суммы 1-го из, data-полей 
:(
    Опции темы
Delphist
  Дата 12.9.2008, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Возникла довольно неприятная ситуации, сейчас на простом примере постораюсь объяснить:

Есть грид-DBGridEh, с 3-мя колонками:
одна из них связана с полем fkData компонента FIBDataSet, а две других с полями fkCalculated этого же датасета.

Код

|---колонка№1---|---колонка№2---|----колонка№3--| - колонки грида DBGridEh
|-------fkData-----|---fkCalculated---|----fkCalculated--| - привязка с полями FIBDataSet'a
|-------fvtSum-----|-------fvtSum------|------fvtSum------|- Footer DBGridEh'a,в нем отображается сумма значений записей нашего FIBDataSet'a


В обработчике FIBDataSet.OnCalcFields весит код который для каждой записи колонки №2 и №3 делает расчет типа:

Код

  DataSet.FieldByName('Field_2').AsFloat :=  GetSumFirstField * FuncX();
  DataSet.FieldByName('Field_3').AsFloat :=  GetSumFirstField * FuncY();

//GetSumFirstField - возращает сумму значений записией первой колонки (поля)
//FuncX, FuncY произвольные ф-ции


Возник большой вопрос какой должен быть код в GetSumFirstField, 
варианты которые я делал (для упрощения объема кода будут приведены прототипы):

Способ 1:
Код

//работает не всегда коректно например на переоткрытии DataSet'a
function GetSumFirstField: double;
begin
   Result := DBGridEh.GetColumnByFieldName('Field_1').Footer.SumValue;
end;


Способ 2:
Код

{в итоге работает медленно особенно, если БД не локальная, + ко всему возращает неправильный результат (старую сумму) если я
редактирую значение записи первой колонки}
function GetSumFirstField: double;
begin
   Result := ExecFibSql('select sum(field_1) as sum_f1 from MyTable').Query.FieldByName[sum_f1].AsFloat;
end;


Способ 3:
Код

{обмирает почему-то, не коректно возвращает сумму, + bookmark не работает - пробовал сохранить текущ. строку по ID и затем 
восстанавливать ее через Locate, но почему то добавляется лишняя в мой DataSet лишняя пустая строка, так и не понял откуда она 
берется :dash1 }
function GetSumFirstField: double;
begin
var
  context: TContextDS;
  fSource: TField;
  bm: TBookmark
begin

  Result := 0;  
  FastDS(DataSet, context); //блокируем AfterPost := nil; BeforePost := nil; OnCalcFields := nil
  if DataSet is TFIBDataSet then
    TFIBDataSet(DataSet).DisableScrollEvents;
  DataSet.DisableControls;
  bm := DataSet.GetBookmark; //возращает почему-то bm = nil из-за чего позиция текущей записи в finally не востанавливается 
  try
    fSource := DataSet.FieldByName('field_1');
    DataSet.First;
    while not DataSet.Eof do
    begin
        Result := Result + fSource.AsFloat;
      DataSet.Next;
    end;
  finally
    if DataSet.BookmarkValid(bm) then //DataSet.BookmarkValid(bm) = False, из-за bm=nil
    begin
      DataSet.GotoBookmark(bm);
      DataSet.FreeBookmark(bm);
    end;

    if DataSet is TFIBDataSet then
      TFIBDataSet(DataSet).EnableScrollEvents;
    DataSet.EnableControls;
    NormalDS(context); //восстанавливаем AfterPost := oldAfterPost, BeforePost := oldBeforePost, OnCalcFields := oldOnCalcFields
  end;
end;


Подскажите, пожалуйста, какой должен быть кода в GetSumFirstField, чтобы он всегда возвращал правильно сумму?

Это сообщение отредактировал(а) Delphist - 12.9.2008, 10:41


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Delphist
Дата 15.9.2008, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Большая просьба помочь с ответом


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 15.9.2008, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  12.9.2008,  12:36 Найти цитируемый пост)
{в итоге работает медленно особенно, если БД не локальная, + ко всему возращает неправильный результат (старую сумму) если яредактирую значение записи первой колонки}
Код

function GetSumFirstField: double;begin   Result := ExecFibSql('select sum(field_1) as sum_f1 from MyTable').Query.FieldByName[sum_f1].AsFloat;end;


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


Это сообщение отредактировал(а) Frees - 15.9.2008, 09:51


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Frees
Дата 15.9.2008, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  12.9.2008,  12:36 Найти цитируемый пост)
 Способ 1: работает не всегда коректно например на переоткрытии DataSet'a


а в чем проявляется не корректная раббота?

может так будет работать лучше
Код

procedure TForm2.pFIBDataSet1AfterPost(DataSet: TDataSet);
begin
  pFIBDataSet1.RefreshClientFields();
end;

procedure TForm2.pFIBDataSet1AfterOpen(DataSet: TDataSet);
begin
  pFIBDataSet1.EnableCalcFields;
end;

procedure TForm2.pFIBDataSet1BeforeOpen(DataSet: TDataSet);
begin
  pFIBDataSet1.DisableCalcFields;
end;

procedure TForm2.pFIBDataSet1CalcFields(DataSet: TDataSet);
begin
   DataSet.FieldByName('Field_2').AsVariant := DBGridEh.GetColumnByFieldName('Field_1').Footer.SumValue;
end;


Это сообщение отредактировал(а) Frees - 15.9.2008, 10:59


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Delphist
  Дата 16.9.2008, 09:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  15.9.2008,  10:51 Найти цитируемый пост)
работате медленно потому что запрос для каждой записи выполняется, ты его выполняй перед расчетом полей и ложи результат в переменную и при расчете полей использкуй переменную а не вызов  функций

Не очень хороший подход мне, кажется. На мой взгляд, не всегда, удастся определить именно цикл расчета для всех записей. Т.е., конечно, мы можем написать в процедуре типа BeforeFieldsCalc определение суммы, но и этот же BeforeFieldsCalc будет вызываться для каждой записи, а вот как определить, то место или процедуру которая бы вызывалась бы до расчета всех полей. Вот в это проблемно.


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Delphist
  Дата 16.9.2008, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  15.9.2008,  11:56 Найти цитируемый пост)
а в чем проявляется не корректная раббота?
может так будет работать лучше

К сожалению, на сегодняшний день мне приходиться пользоваться компонентами FIBs, это не много урезанный вариант FIBPlus.  В них  нет RefreshClientFields(), DisableCalcFields, EnableCalcFields. 
Вот это:
Код

DisableCalcFields, 
EnableCalcFields.

в принцепе их можно реализовать, на скок я понимаю, через 
Код

 //DisableCalcFields
 oldCF := OnCalcFields; 
 OnCalcFields := nil;

//EnableCalcFields.
OnCalcFields := oldCF;


RefreshClientFields() - не знаю что делает smile, подозреваю что выполняет что-то типа RecalcAllFields - пересчитать все поля

И опять же у меня берет сомнение, что AfterPost, будет всегда срабатывать после AfterOpen smile 

Это сообщение отредактировал(а) Delphist - 16.9.2008, 10:09


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 16.9.2008, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  16.9.2008,  12:07 Найти цитируемый пост)
RefreshClientFields() - не знаю что делает

пересчет вычисляемых полей запускается




--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Delphist
  Дата 16.9.2008, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  16.9.2008,  11:31 Найти цитируемый пост)
пересчет вычисляемых полей запускается

угу уже понял, посмотри, пожалуйста, еще раз мой последний ответ, в особеннности последнее предложение

Это сообщение отредактировал(а) Delphist - 16.9.2008, 10:45


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 16.9.2008, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  16.9.2008,  12:07 Найти цитируемый пост)
И опять же у меня берет сомнение, что AfterPost, будет всегда срабатывать после AfterOpen 

точно будет сперва AfterOpen на закрытом дата сете же пост не сделать


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Delphist
Дата 16.9.2008, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  16.9.2008,  12:00 Найти цитируемый пост)
точно будет сперва AfterOpen на закрытом дата сете же пост не сделать 

не совсем тебя понял. ты согласился с моими выводом или наоборот утверждаешь, что AfterPost будет всегда после AfterOpen'a?


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 16.9.2008, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



 AfterPost будет всегда после AfterOpen'a


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Delphist
  Дата 16.9.2008, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  16.9.2008,  12:32 Найти цитируемый пост)
AfterPost будет всегда после AfterOpen'a 

Ток что проверил, и делаю вывод AfterPost НЕ вызывается после AfterOpen и это правильно как по сути так и по логике.

Это сообщение отредактировал(а) Delphist - 16.9.2008, 13:06


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 16.9.2008, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  16.9.2008,  15:06 Найти цитируемый пост)
Ток что проверил, и делаю вывод AfterPost НЕ вызывается после AfterOpen и это правильно как по сути так и по логике.

AfterPost будет происходить если ты будеш делать post 
но до этого уже отработается AfterOpen

отработать AfterPost нужно что бы если ты вносиш изменения перещитались все поля без переоткрытия


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Delphist
Дата 16.9.2008, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphist Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2145
Регистрация: 3.2.2004
Где: всегда в сети

Репутация: 1
Всего: 3



Цитата(Frees @  16.9.2008,  14:26 Найти цитируемый пост)
AfterPost будет происходить если ты будеш делать post 

Ты предлагаешь искусствено вызывать Post после AfterOpen? Опять же Post можно вызывать ток в том случае если DataSet.State in [dsEdit, dsInsert] а иначе генириться исключение.


--------------------
ProcessInfo 1-ая моя программа (аналог spyxx.exe с гораздо большим функц-ом - внедрение dll в адр. простр. процесса, перехват API-функций, разбор приложения на окна мн.др).
Когда-то давным-давно использовал это...
PM MAIL ICQ   Вверх
Frees
Дата 16.9.2008, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2233
Регистрация: 2.12.2005
Где: Екатеринбург

Репутация: 23
Всего: 54



Цитата(Delphist @  16.9.2008,  16:11 Найти цитируемый пост)
Ты предлагаешь искусствено вызывать Post после AfterOpen? Опять же Post можно вызывать ток в том случае если DataSet.State in [dsEdit, dsInsert] а иначе генириться исключение.

ты меня не понял в AfterPost можно ничего не писать и все будет работать только до того момента пока ты не начнеш редактировать первое поле, а что бы учесть его редактирование на AfterPost и делаем перещет полей


--------------------
Кольцов Виктор Владимирович
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Базы данных и репортинг"
Vit
Петрович

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами


Обязательно указание:

1. Базы данных (Paradox, Oracle и т.п.)

2. Способа доступа (ADO, BDE и т.д.)


  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • Вопросы по SQL и вопросы по базам данных не связанные с Дельфи задавать здесь

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема »


 




[ Время генерации скрипта: 0.0897 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.