I'm getting data using a query in Delphi, and would like to add a calculated field to the query before it runs. The calculated field is using values in code as well as the query so I can't just calculate it in SQL.
I know I can attach an OnCalcFields
Event to actually make the calculation, but the problem is after adding the calculated field there are no other fields in the query...
I did some digging and found that all of the field defs are created but the actual fields are only created
if DefaultFields then
CreateFields
Default Fields is specified
procedure TDataSet.DoInternalOpen;
begin
FDefaultFields := FieldCount = 0;
...
end;
Which would indicate that if you add fields you only get the fields you added.
I would like all the fields in the query AS WELL AS the ones I Add.
Is this possible or do I have to add all the fields I'm using as well?
Create a calculated field in a queryIn the Navigation Pane, right-click the query that you want to change, and then click Design View on the shortcut menu. Click the Field cell in the column where you want to create the calculated field. To manually create your expression, type your expression.
Go to the menu Edit -> Local Field -> Create. Give the field some name and descrption. Choose the properties that you need and enter the Calculation Formula using the short name from step 2 (e.g. COST * 1.10 to add 10% to the COST field).
To add a field, drag the field from a data source in the upper pane of the query design window down to the Field row of the design grid, in the bottom pane of the query design window. When you add a field this way, Access automatically fills in the Table row of the design grid to reflect the data source of the field.
If you have know your to be calculated fields names at runtime, you can use something like that.
var
initing:boolean;
procedure TSampleForm.dsSampleAfterOpen(
DataSet: TDataSet);
var
i:integer;
dmp:tfield;
begin
if not initing then
try
initing:=true;
dataset.active:=false;
dataset.FieldDefs.Update;
for i:=0 to dataset.FieldDefs.Count-1 do
begin
dmp:=DataSet.FieldDefs.Items[i].FieldClass.Create(self);
dmp.FieldName:=DataSet.FieldDefs.Items[i].DisplayName;
dmp.DataSet:=dataset;
if (dmp.fieldname='txtState') or (dmp.FieldName='txtOldState') then
begin
dmp.Calculated:=true;
dmp.DisplayWidth:=255;
dmp.size:=255;
end;
end;
dataset.active:=true;
finally
initing:=false;
end;
end;
procedure TSampleForm.dsSampleAfterClose(
DataSet: TDataSet);
var
i:integer;
dmp:TField;
begin
if not initing then
begin
for i:=DataSet.FieldCount-1 downto 0 do
begin
dmp:=pointer(DataSet.Fields.Fields[i]);
DataSet.Fields.Fields[i].DataSet:=nil;
freeandnil(dmp);
end;
DataSet.FieldDefs.Clear;
end;
end;
procedure TSampleForm.dsSampleCalcFields(
DataSet: TDataSet);
var
tmpdurum,tmpOldDurum:integer;
begin
if not initing then
begin
tmpDurum := dataset.FieldByName( 'state' ).AsInteger;
tmpOldDurum:= dataset.FieldByName( 'oldstate' ).AsInteger;
dataset.FieldByName( 'txtState' ).AsString := State2Text(tmpDurum);
dataset.FieldByName( 'txtOldState' ).AsString := State2Text(tmpOldDurum);
end;
end;
procedure TSampleForm.btnOpenClick(Sender: TObject);
begin
if dsSample.Active then
dsSample.Close;
dsSample.SQL.text:='select id,state,oldstate,"" as txtState,"" as txtOldState from states where active=1';
dsSample.Open;
end;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With