Всем привет, опять же, пишу статью про ADO, а также по просьбе читателя моего блога, который попросил рассказать, как в БД можно работать с вычисляемыми полями (чтобы значение вычисляемого поля сразу менялось, при вводе нового значения), на примере БД — MS Access. Я расскажу 2 способа работы с вычисляемые полями, а на примере покажу только один способ. Ну, первый способ состоит в том, что все поля, в том числе и вычисляемое, мы создаем сразу в БД - MS Access, причем тип данных, поля, в котором будет менять значение — указываем Вычисляемое поле.
Что касается второго способа, то вычисляемое поле, мы создадим в нашем проекте, через компоненты TAdoQuery или TAdoTable.
Ну и сразу скажу, что есть, не очень правильный 3 метод, при котором можно использовать TTimer.
Давайте начнем с нашей БД.
У меня в БД имеет следующую структуру:
Итак, БД в MS Access у нас создана, теперь переходим к самому проекту в Delphi, на форме у меня следующие компоненты:
- TDataSource
- TDBGrid
- TADOConnection
- TADOQuery
- TButton
Теперь, делаем подключение к нашей БД, как это делать, мы рассматривали в статье, так что заострять внимание на этом, я не буду. Далее, нам необходимо все наши компоненты связать между собой, ну вот и приступим. Выделяем компонент TADOQuery и в свойстве Connection указываем — TADOConenction. Далее, выделяем компонент TDataSource и в свойстве DataSet указываем TADOQuery. Затем, выделяем компонент TDBGrid и в свойстве DataSource указываем TDataSource.
Все, теперь добавим все наши поля. Для этого, нам необходимо активировать наш запрос и подключение. В свойстве компонента TADOConenction — Connected устанавливаем True, а в свойстве компонента TADOQuery - SQL, напишем следующий запрос
SELECT * FROM Test
Имя, нашей таблицы — Test. Ну и далее, активируем наш запрос, в свойстве Active, компонента TADOQuery устанавливаем в True.
Далее нажимаем, двойным щелчком мыши по компоненту TADOQuery и появляется окно:
В данном окне, нажимаем правой кнопкой мыши, и из контекстного меню, выбираем пункт Add all fields. В список добавиться все наши поля таблицы.
Ну, а теперь создадим наше Вычисляемое поле. Для этого, в данном окне, нажимаем правой кнопкой мыши и из контекстного меню выбираем пункт New Field, после чего появиться окно, где необходимо заполнить поля, как показано на рисунке:
Указываем имя нашего вычисляемого поля, устанавливаем указатель на Calculated и указываем тип данных — Integer, можно и с плавающей точкой, какой Вам удобно.
Ну, а дальше, выделяем компонент TADOQuery и на событие OnCalcFields напишем следующий код:
procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
ADOQuery1Sum.AsInteger:=ADOQuery1Values.AsInteger*ADOQuery1Count.AsInteger;
end;
Не забываем, что свойство AutoCalcFields, компонента TADOQuery должно быть установлено в True
Как видите, ничего сложного нету. Как я говорил раньше, можно сразу же в БД создать вычисляемое поле, а можно в проекте. Теперь при изменении значения в любой из ячеек, значение нашего вычисляемого поля автоматические будет меняться.
Исходник можно скачать тут
Мне повезло что я нашёл сервис, который успешно создает недорогие сайты и радует своей стабильностью.
Похожие записи
Метки: Access, Ado, ADoconnection, AdoQuery, MS Access, sql, БД, Вычисляемые поля
Спасибо Андрей53!!! Классный пример. А я как только не пробовал, не получалось. Оказывается просто как и все гениальное. У тебя на сайте информации по базам данных, хватит на добротный учебник. И я думаю, если бы удалось издать, он бы пользовался популярностью, по крайней мере среди начинающих (как минимум). Спасибо что помогаешь разбираться и не оставляешь вопросы без внимания.
Пробовал повторить
procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
ADOQuery1Sum.AsInteger:=
ADOQuery1Values.AsInteger*ADOQuery1Count.AsInteger;
end;
вылетали ошибки, хотя в исходнике все также прописано и работает.
Попробовал прописать столбцы через fields
begin
AdoQuery1.Fields.FieldByName(‘Ост’).asInteger:=
AdoQuery1.Fields.FieldByName(‘Приход’).asInteger-AdoQuery1.Fields.FieldByName(‘Расход’).asInteger;
end;
Заработало.
Может он именно на русские названия ругался,
или то что вместо обычного Grida я использую DBGridEh?
Нет, то что вместо стандартного грида используешь DBGRidEh не в этом проблема, а ошибка хоть какая вылетала?
Вот
[error] unit1.pas(36)Illegal character in input file ‘О'($CE)
[error] unit1.pas(36)Illegal character in input file ‘П'($CF)
[error] unit1.pas(36)Illegal character in input file ‘Р'($DO)
‘О’- я так понял, первая буква слова Остаток, а ‘П’и’Р’ по ходу Приход и Расход.
так ты решил проблему?
Ну да. Через Fields и все получилось
Сегодня решил по экспериментировать. Добавил к примеру кнопку, на событии онклик прописал ADOQuery1.Insert; Но при нажатии, строка почему то не добавляется.
Еще иногда выскакивает ошибка, ADOQuery1:DataSet not in edit or insert mode
в моем исходнике добавлял?
Не, у себя…
Может разница в версиях Delphi? Я Delphi7 осваиваю.
В твоем примере все работает, только после того как в добавленную строку вбиваю данные, выскакивает ошибка что должен использоваться обновляемый запрос. Не могу понять, что за запрос такой.
Все нашел блин, — причина как обычно моя невнимательность…
внимательней будь, просто так без кода и без проетка тяжелова-то найти обшибку, ты выкладывай код чуть что
что написать на кнопку найти, у меня выводить ошибку, помогите!!!
какой код у Вас на кнопке найти, как поиск осуществляете? запросами, фильтрацией? функцией?
Большое спасибо за статью! Единственное, не получается привязать вычисление двух полей DBGrid к кнопке. Т.е. по нажатию баттона, два поля с числовыми значениями складываются, а результат должен отображаться в третьей колонке. Не могли бы вы подсказать, как реализовать эту функцию?
так все же в данной статье написано
Делаю по такому же принципу, как описано для события OnCalcFields, но не получается, выдается ошибка. Если меняешь значения для одного из полей и рассчитываешь, то работает, для всей таблицы со значениями не работает. В чем может быть проблема?
можете скинуть или показать исходник?
Здравствуйте большое спасибо за статью.
Помогите пожалуйста я еще плохо разбираюсь с базами данных и не могу понять куда сохраняется сумма складываемая из двух полей?
В базе Access поле которое создали через Delphi 7 нету соответственно и значений тоже нету. Открываю прогу значения есть.
Можно ли сделать чтобы в Access записывались вычисляемые значения ?
да, можно, их надо просто сохранить, ADOQuery.Post
Здраствуйте, помогите, пожалуйста,
у меня база по учету выдачи книг читателям. Мне необходимо сделать, чтобы автоматически в DBGrid ложились данные (в DBGrid должно быть количество строк равное количеству дней в месяце,за который мы хотим получить отчет) в первый столбец должно ложится число читателей, пришедших за день в библиотеку, во-второй столбец, число школьников, в-третий, число студентов и т.д. и так 30 строк, если, например, за апрель месяц. Мне не понятно, как нужно указать день, за который нужно подсчитать(((
Не совсем понял, но в Delphi можно определить количество дней в месяце, в зависимости от этого количества Вы сможете создать таблицу в БД с нужным количество строк!
Еще один способ, при котором в DBGrid (DBGridEh) организовывается колонка, где отображается рассчитанное значение или, вообще, любая другая строка.
В списке колонок DBGrid создается еще одна, которая не связывается ни с каким полем таблицы БД.
В процедуре обработки события OnDrawColumnCell гриды происходит обработка данных, получение и вывод результата:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
D : string;
R : TRect;
begin
if Column.Index = 6 then begin //индекс дополнительной колонки
//операторы вычислений или любые другие
R := Rect;
InflateRect(R, 0, -2);
DrawText(DBGrid1.Canvas.Handle, PChar(D), -1, R, DT_Center);
end;
end;
Недостаток в том, что отображенный результат не может быть использован в других местах программы. Но и ситуаций, когда этого не нужно вполне предостаточно.
А можно как-нибудь фильтровать по вычисляемому полю? Пробовал, не получилось!
{
int n;
n=2500;
ADOTable1->Filtered=false;
ADOTable1->Filter= «(Отработано=’ «+IntToStr(n)+» ‘)»;
ADOTable1->Filtered=true;
DBChart1->RefreshData();}
Поле «отработано» — вычисляемое!
Заранее спасибо!