Is it possible to get the Field-Value from TTMSFNCDataGridDatabaseAdapter in the TTMSFNCDataGrid.OnGetCellLayout
This would be really handy for defining formatting conditions externally based on database values instead of displayed values.
Is it possible to get the Field-Value from TTMSFNCDataGridDatabaseAdapter in the TTMSFNCDataGrid.OnGetCellLayout
This would be really handy for defining formatting conditions externally based on database values instead of displayed values.
Hi, you can use the following code to achieve the behavior your looking for. The code is based on the BioLife.xml (TClientDataSet)
procedure TForm1.TMSFNCDataGrid1GetCellLayout(Sender: TObject;
ACell: TTMSFNCDataGridCell);
var
o: Integer;
begin
if not Assigned(TMSFNCDataGridDatabaseAdapter1) or not TMSFNCDataGridDatabaseAdapter1.CheckDataSet then
Exit;
o := TMSFNCDataGridDatabaseAdapter1.DataLink.ActiveRecord;
try
if TMSFNCDataGridDatabaseAdapter1.SetActiveRecord(ACell.Row) then
begin
if TMSFNCDataGridDatabaseAdapter1.ColumnAtField['Category'].Field.AsString = 'Shark' then
ACell.Layout.Font.Color := gcRed;
end;
finally
TMSFNCDataGridDatabaseAdapter1.DataLink.ActiveRecord := o;
end;
end;
This works great if you are using the field values within the dataset, However, if I need to check the qty from inventory and if qty are not there make that row red, I try to use the following code but it has a performance issue.
procedure TBOMForm.WOITEMSDATAGRIDGetCellLayout(Sender: TObject;
ACell: TTMSFNCDataGridCell);
var
ar, c, r: Integer;
TOTON : DOUBLE;
begin
if ACELL.row < WOITEMSDATAGRID.FixedRowCOUNT then
begin
Acell.Layout.TextAlign := TTMSFNCGraphicsTextAlign.gtaCenter;
Acell.layout.Font.Style := [tfontstyle.fsUnderline,tfontstyle.fsBold];
Acell.layout.Font.Size := 15;
end
else
begin
Acell.layout.Font.Style := [tfontstyle.fsBold];
Acell.layout.Font.Size := 11;
end;
R := 0;
if not Assigned(WOITEMSDATAGridDatabaseAdapter) or not WOITEMSDATAGridDatabaseAdapter.CheckDataSet then
Exit;
r := WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord;
try
if WOITEMSDATAGridDatabaseAdapter.SetActiveRecord(ACell.Row) then
begin
if (WOITEMSDATAGridDatabaseAdapter.ColumnAtField['TYPE'].Field.AsString = 'Raw Good') THEN
BEGIN //FDQUERY4 IS USING A STORED PROCEDURE TO GET QTY ON HAND
FDQUERY4.Close;
FDQUERY4.ParamByName('LG').AsString := 'Vicksburg';
FDQUERY4.ParamByName('PID').AsInteger := WOITEMSDATAGridDatabaseAdapter.ColumnAtField['PARTID'].Field.AsInteger;
FDQUERY4.Open;
if fdquery4.RecordCount > 0 then
TOTON := FDQUERY4.FieldByName('QTYONHAND').AsFloat
else
TOTON := 0;
FDQUERY4.Close;
IF (WOITEMSDATAGridDatabaseAdapter.ColumnAtField['QTYTARGET'].Field.ASFLOAT > TOTON) then
ACELL.Layout.Fill.Color := tAlphaColorRec.Red
ELSE
ACELL.Layout.Fill.Color := tAlphaColorRec.lightgreen;
END
else
exit;
end;
finally
WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord := r;
end;
.
Thanks still learning Datagrid
Garnett
The performance issue comes from fetching the columns (ColumnAtField), you might want to determine the column once after the dataset is set active, and then use that column to retrieve the field. Or use the fields from the dataset directly.
procedure TBOMForm.CheckInvClick(Sender: TObject);
VAR
TOTON,TOT : DOUBLE;
CNT : INTEGER;
flg : boolean;
begin
CNT := 0;
flg := False;
FDTbl9D.FIRST;
while NOT FDTbl9D.Eof do
BEGIN
CNT := CNT + 1;
if FDTbl9D.FieldByName('TYPE').AsSTRING = 'Raw Good' then
BEGIN
FDQUERY4.Close;
FDQUERY4.ParamByName('LG').AsString := FDTBL9BA.FieldByName('LOCATIONGROUP').AsString;
FDQUERY4.ParamByName('PID').AsINTEGER := FDTbl9D.FieldByName('PARTID').AsINTEGER;
FDQUERY4.Open;
if fdquery4.RecordCount > 0 then
TOTON := FDQUERY4.FieldByName('QTYONHAND').AsFloat
else
TOTON := 0;
FDQUERY4.Close;
WOITEMSDATAGrid.BeginUpdate;
TOT := FDTbl9D.FieldByName('QTYTARGET').AsFloat;
if (TOTON >= TOT) AND (FDTbl9BA.FieldByName('STATUS').AsSTRING = 'Entered') then
WOITEMSDATAGrid.Layouts[6,cnt].Fill.Color := tAlphaColorRec.Lightgreen
ELSE
begin
if (TOTON < TOT) AND (FDTbl9BA.FieldByName('STATUS').AsSTRING = 'Entered') then
begin
WOITEMSDATAGrid.Layouts[6,cnt].Fill.Color := tAlphaColorRec.Rosybrown;
flg := True;
end;
end;
WOITEMSDATAGrid.EndUpdate;
END;
FDTbl9D.Next;
END;
FDTbl9D.FIRST;
if flg then
CreateWOTraveler.Enabled := False
else
CreateWOTraveler.Enabled := True;
end;
This is the way I set the row column[6] fill color base on inventory qty and did work in fncgrid but it will not set the color here and I cannot seem to get it to work in the
layout procedure WOITEMSDATAGRIDGetCellLayout
thanks
Garnett
Your previous code, coloring the cells dynamically was the correct approach. You mentioned that you had performance issues, most likely this is due to the retrieval of columns each time a cell layout is dynamically built up. You would need to change the code to:
procedure TForm7.FormCreate(Sender: TObject);
begin
//after activate adapter / dataset
FTypeColumn := WOITEMSDATAGridDatabaseAdapter.ColumnAtField['TYPE'];
FPartIDColumn := WOITEMSDATAGridDatabaseAdapter.ColumnAtField['PARTID'];
FQtyTargetColumn := WOITEMSDATAGridDatabaseAdapter.ColumnAtField['QTYTARGET'];
end;
procedure TBOMForm.WOITEMSDATAGRIDGetCellLayout(Sender: TObject;
ACell: TTMSFNCDataGridCell);
var
ar, c, r: Integer;
TOTON : DOUBLE;
begin
if ACELL.row < WOITEMSDATAGRID.FixedRowCOUNT then
begin
Acell.Layout.TextAlign := TTMSFNCGraphicsTextAlign.gtaCenter;
Acell.layout.Font.Style := [tfontstyle.fsUnderline,tfontstyle.fsBold];
Acell.layout.Font.Size := 15;
end
else
begin
Acell.layout.Font.Style := [tfontstyle.fsBold];
Acell.layout.Font.Size := 11;
end;
R := 0;
if not Assigned(WOITEMSDATAGridDatabaseAdapter) or not WOITEMSDATAGridDatabaseAdapter.CheckDataSet then
Exit;
if not Assigned(FTypeColumn) or not Assigned(FPartIDColumn) or not Assigned(FQtyTargetColumn) then
Exit;
r := WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord;
try
if WOITEMSDATAGridDatabaseAdapter.SetActiveRecord(ACell.Row) then
begin
if (FTypeColumn.Field.AsString = 'Raw Good') THEN
BEGIN //FDQUERY4 IS USING A STORED PROCEDURE TO GET QTY ON HAND
FDQUERY4.Close;
FDQUERY4.ParamByName('LG').AsString := 'Vicksburg';
FDQUERY4.ParamByName('PID').AsInteger := FPartIDColumn.Field.AsInteger;
FDQUERY4.Open;
if fdquery4.RecordCount > 0 then
TOTON := FDQUERY4.FieldByName('QTYONHAND').AsFloat
else
TOTON := 0;
FDQUERY4.Close;
IF (FQtyTargetColumn.Field.ASFLOAT > TOTON) then
ACELL.Layout.Fill.Color := tAlphaColorRec.Red
ELSE
ACELL.Layout.Fill.Color := tAlphaColorRec.lightgreen;
END
else
exit;
end;
finally
WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord := r;
end;
end;
ColumnAtField loops through the columns which can be done once, after the dataset is activated.
Still having an issue with performance, however I decided to pickup inventory qty on hand value with a fdtable calculated field which as part of the dataset: code below works
procedure TBOMForm.WOITEMSDATAGRIDGetCellLayout(Sender: TObject;
ACell: TTMSFNCDataGridCell);
var
r: Integer;
begin
if ACell.row < WOITEMSDATAGRID.FixedRowCOUNT then
begin
ACell.Layout.TextAlign := TTMSFNCGraphicsTextAlign.gtaCenter;
ACell.Layout.Font.Style := [tfontstyle.fsUnderline, tfontstyle.fsBold];
ACell.Layout.Font.Size := 15;
endelsebeginAcell.Layout.Font.Style := [tfontstyle.fsBold];
ACell.Layout.Font.Size := 11;
end;
if not Assigned(WOITEMSDATAGridDatabaseAdapter) or not WOITEMSDATAGridDatabaseAdapter.CheckDataSet then
Exit;
r := WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord;
try
if WOITEMSDATAGridDatabaseAdapter.SetActiveRecord(ACell.row) then
begin
if WOITEMSDATAGridDatabaseAdapter.ColumnAtField['TYPE'].Field.AsString = 'Raw Good'
then
if WOITEMSDATAGridDatabaseAdapter.ColumnAtField['QTYTARGET']
.Field.AsFloat > WOITEMSDATAGridDatabaseAdapter.ColumnAtField['TOTON']
.Field.AsFloat THEN
ACell.Layout.FILL.Color := tAlphaColorRec.Yellowgreen
ELSE
ACell.Layout.FILL.Color := tAlphaColorRec.green;
end;
finally
WOITEMSDATAGridDatabaseAdapter.DataLink.ActiveRecord := r;
end;
Thanks Pieter
Garnett
Hi,
Does this provide better results in terms of performance?
PS: I edited and formatted the code snippets for readability
Yes, average time before 20-40 seconds to 3 to 5 seconds.
P.S. The other issue with filtering datagrid using firedac fdtable tables. Is there a flag(s) or setting within the datagrid or datagriddatabaseadapter that would not allow filtering or could it be that master/detail datagrids has an issue with filtering?
Thanks
Garnett