Page 1 of 1

clientdataset persistent fields property

Posted: Fri Jul 05, 2024 9:08 am
by 16895885
HI
if I connect a Tgrid to a Delphi 12.1 clientdataset, the grid is fed with all the persistent fields of the query
But if I act for example on the visible true/false property in the object inspector of persistent fields, this is not reflected on the Tgrid but I am forced to modify the Tgrid field by field to make what I want invisible or visible
Am I doing something wrong or is this how it works?
field_property.png
example problem
field_property.png (111.9 KiB) Viewed 26670 times

Re: clientdataset persistent fields property

Posted: Fri Jul 05, 2024 9:28 am
by 16895885
HI
I just discovered that to resolve this you need to unlink the clientdataset to the Tgrid with the object inspector, modify the persistent fields and then reconnect the clientdataset to the TGrid
This causes the components to lose some dynamism. Check how it behaves at runtime.
Maybe this could be an interesting fix?
Ciao

Re: clientdataset persistent fields property

Posted: Fri Jul 05, 2024 10:04 am
by Marc
Hello,

Thanks for the follow-up, we'll take a look,

Regards,
Marc Meumann

Re: clientdataset persistent fields property

Posted: Mon Jul 08, 2024 9:39 am
by 16895885
hi
still pertaining to the visible issue of persistent fields, I tried to make some code by adapting one of your examples to manage the expander
visible property at runtime doesn't work, the rest of the code works great
furthermore, changing the display label on the persistent field has no effect on the column title of the grid and this is a big problem, is there some instruction that I haven't found?
Help me please!
Am I doing something wrong?

Code: Select all

/*********************************/
  My_Ctgrid_class := C_TeeGrid_Class.Create;
  // Initialize "Expander"
  My_Ctgrid_class.max_col_footer := 4;

  My_Ctgrid_class.Params_matrix[1].field_name := 'pk_progressivo';
  My_Ctgrid_class.Params_matrix[1].position := 0;
  My_Ctgrid_class.Params_matrix[1].type_function := 'count';

  My_Ctgrid_class.Params_matrix[2].field_name := 'budget';
  My_Ctgrid_class.Params_matrix[2].position := 5;
  My_Ctgrid_class.Params_matrix[2].type_function := 'sum';

  My_Ctgrid_class.Params_matrix[3].field_name := 'budget_utilizzato';
  My_Ctgrid_class.Params_matrix[3].position := 6;
  My_Ctgrid_class.Params_matrix[3].type_function := 'sum';

  My_Ctgrid_class.Params_matrix[4].field_name := 'quota_detraibile';
  My_Ctgrid_class.Params_matrix[4].position := 8;
  My_Ctgrid_class.Params_matrix[4].type_function := 'average';

  TeeGrid1 := My_Ctgrid_class.tgrid_expander(TeeGrid1, Cds_ListView, [b]cds_detail[/b], true, true);
(cds_detail is dataset in attach image)

Code: Select all

/*********************************/
 


type
  TParams = Record
    field_name: string;
    position: smallint;
    type_function: string;
  End;

  C_TeeGrid_Class = class(TObject)

    procedure CBEnabledChange(Sender: TObject);
  private
    { Private declarations }
  protected
  public
    { Public declarations }
    mydataset1_tmp, mydataset2_tmp: TclientDataSet;
    Expander: TExpanderRender;
    function tgrid_expander(mytgrid: tteegrid; mydataset1_in: TclientDataSet;
      mydataset2_in: TclientDataSet; open_expander: boolean;
      footer_calc: boolean): tteegrid;
    procedure GetMyDati(const Sender: TExpanderRender; const ARow: Integer;
      out AData: TObject);
    function read_mydata(const ARecNo: Integer; mydataset1: TclientDataSet;
      mydataset2: TclientDataSet): TclientDataSet;
    function CloneData(const ADataSet: TclientDataSet): TclientDataSet;
    // procedure DetailNewGroup(const Sender, NewGroup: TRowGroup; field_name1 :string; field_name2 : string);
    procedure DetailNewGroup(const Sender, NewGroup: TRowGroup);

    constructor Create;

  var
    max_col_footer: smallint;
    Params_matrix: array [1 .. 10] of TParams;
{ I use the array to manage the totals row of the expander grid
 I pass to the function the fields I want to be used, their position as columns and the type of
 aggregation (this only at text level and then I manage with if se sum count etc)
 }
  end;

--------------------------
procedure C_TeeGrid_Class.CBEnabledChange(Sender: TObject);
begin
  //
end;

// Return a new clone copy of ADataSet data, all rows
function C_TeeGrid_Class.CloneData(const ADataSet: TclientDataSet)
  : TclientDataSet;
var
  tmp: TMemoryStream;
begin
  tmp := TMemoryStream.Create;
  try
    ADataSet.SaveToStream(tmp);
    tmp.position := 0;

    result := TclientDataSet.Create(nil);
    TclientDataSet(result).LoadFromStream(tmp);
  finally
    tmp.Free;
  end;

end;

procedure C_TeeGrid_Class.DetailNewGroup(const Sender, NewGroup: TRowGroup);
var
  tmpTot: TColumnTotals;
  i: smallint;
begin

  // Create a Totals band
  tmpTot := TColumnTotals.Create(NewGroup.Footer); // <--- set to Footer

  // Add some calculations

  for i := 1 to max_col_footer do
  begin
    if Params_matrix[i].type_function = 'count' then
    begin
      tmpTot.Calculation.Add(NewGroup.Columns[Params_matrix[i].position],
        TColumnCalculation.Count);
      tmpTot.Calculation.Add(Params_matrix[i].field_name,
        TColumnCalculation.Count);
    end;
    if Params_matrix[i].type_function = 'sum' then
    begin
      tmpTot.Calculation.Add(NewGroup.Columns[Params_matrix[i].position],
        TColumnCalculation.Sum);
      tmpTot.Calculation.Add(Params_matrix[i].field_name,
        TColumnCalculation.Sum);
    end;
    if Params_matrix[i].type_function = 'min' then
    begin
      tmpTot.Calculation.Add(NewGroup.Columns[Params_matrix[i].position],
        TColumnCalculation.Min);
      tmpTot.Calculation.Add(Params_matrix[i].field_name,
        TColumnCalculation.Min);
    end;
    if Params_matrix[i].type_function = 'max' then
    begin
      tmpTot.Calculation.Add(NewGroup.Columns[Params_matrix[i].position],
        TColumnCalculation.Max);
      tmpTot.Calculation.Add(Params_matrix[i].field_name,
        TColumnCalculation.Max);
    end;
    if Params_matrix[i].type_function = 'average' then
    begin
      tmpTot.Calculation.Add(NewGroup.Columns[Params_matrix[i].position],
        TColumnCalculation.Average);
      tmpTot.Calculation.Add(Params_matrix[i].field_name,
        TColumnCalculation.Average);
    end;
  end;
  // Add a Totals header:
  TTotalsHeader.CreateTotals(NewGroup.Footer, tmpTot);

end;

procedure C_TeeGrid_Class.GetMyDati(const Sender: TExpanderRender;
  const ARow: Integer; out AData: TObject);
begin

  AData := TVirtualDBData.From(read_mydata(ARow + 1, mydataset1_tmp,
    mydataset2_tmp));
end;

function C_TeeGrid_Class.read_mydata(const ARecNo: Integer;
  mydataset1: TclientDataSet; mydataset2: TclientDataSet): TclientDataSet;
// Return the CustomerID for row: ARow
  function key_ricerca: Integer;
  begin
    mydataset1.RecNo := ARecNo;
    result := mydataset1.FieldByName('pk_progressivo').AsInteger;
  end;

// Execute OrdersTable query for a given CustomerID
  procedure FiltroDati(const key_ricerca: Integer);
  begin
    mydataset2.active := False;
    mydataset2.ParamByName('pk_progressivo').AsInteger := key_ricerca;
    mydataset2.active := True;
  end;

begin
  FiltroDati(key_ricerca);
  result := CloneData(mydataset2);
end;

function C_TeeGrid_Class.tgrid_expander(mytgrid: tteegrid;
  mydataset1_in: TclientDataSet; mydataset2_in: TclientDataSet;
  open_expander: boolean; footer_calc: boolean): tteegrid;
begin
  mydataset1_tmp := mydataset1_in;
  mydataset2_tmp := mydataset2_in;

  // Create "Expander"
  Expander := mytgrid.grid.Current.NewExpander;

  // Setup event
  Expander.OnGetData := GetMyDati;

  // We don't know in advance if a row can be expanded or not, so set Always
  // Expander.AlwaysExpand := True;

  // Set to first Column
  mytgrid.Columns[0].Render := Expander;

  // Optional:
  if footer_calc = True then
    mytgrid.grid.Current.OnNewDetail := DetailNewGroup;

  if not open_expander then
  Begin
    mytgrid.grid.Current.ShowHideAllDetail(0, False);
    Open := False;
  End
  else
  Begin
    mytgrid.grid.Current.ShowHideAllDetail(0, True);
    Open := True;
  End;

  result := mytgrid;
end;

constructor C_TeeGrid_Class.Create;
begin
  //
end;

end.

Re: clientdataset persistent fields property

Posted: Mon Jul 08, 2024 3:33 pm
by Marc
Hello,

We'll run some checks for suggestions.

Regards,
Marc Meumann

Re: clientdataset persistent fields property

Posted: Mon Jul 08, 2024 5:05 pm
by Marc
Hello,

The refreshing of the grid content should be done by modifying the source, as you observed in your earlier post. In addition to that your could modify the columns (hiding them) in relation to any particular fields that you may not wish to include at any time.

eg.

Code: Select all

  TeeGrid1.Columns.Items[3].Visible := not TeeGrid1.Columns.Items[3].Visible;
  TeeGrid1.Columns.Items[3].Header.Text := 'my col header text';
The best example, I think, that covers the use of expander is this one:

https://github.com/Steema/TeeGrid-VCL-F ... il_FireDAC

It is likely that you've seen it already. It includes methods to show/hide the expander and to implement it by code. Have you seen that code?

I'm sure this answer doesn't go into the detail you're looking for so please let us know what it's missing, I haven't been able to pick out all of the details from your code sample.

With thanks.
Regards,
Marc

Re: clientdataset persistent fields property

Posted: Tue Jul 09, 2024 8:43 am
by 16895885
Hi Marc
Thank you for your always prompt response

I used all the code you provided and improved it
I also solved the problems I reported to you and which I will try to explain better here
If anything you could create a small demo or a note for those who use your wonderful component whose wide possibilities I appreciate every day
The underlying issue is managing the runtime dataset that powers the expander
during the clone phase via the SaveToStream / LoadFromStream cycle the resulting dataset loses all the properties set in the original clientdataset
Example
ClientDataSet: My_dataset_input_for_clone
Persistent field: field_1, field_2,
Sets the object inspector properties
1) Field_1.visible = False
2) Field_1.displaylabel = 'field_1'
3) Field_1.displaywith = 30
4) Field_2.visible = True
5) Field_2.displaylabel = 'My_name_for_label_header' (modify from field_2)
6) Field_2.displaywith = 10 (change from 30)

the result is that
1 = true
5 = field_2
6=30
in practice it loses these properties
the solution is that when I exit the loadfromstream code I make the settings I need but this is inconvenient, very inconvenient.

Sorry for my english
Ciao
Raffaele

Re: clientdataset persistent fields property

Posted: Mon Jul 15, 2024 8:13 am
by Marc
Hello Raffaele,

We're taking a look to see what improvements can be made. Thanks for the detailed information.

Regards,
Marc