Возникла довольно неприятная ситуации, сейчас на простом примере постораюсь объяснить:
Есть грид-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, чтобы он всегда возвращал правильно сумму? |