Si utilizamos este componente en local, el conjunto de datos lo extraeremos
de un fichero local. Este fichero debera ser creado por otro TclientDataSet,
por lo tanto tendremos que crear el conjunto de datos. Para crear un conjunto
de datos en memoria debemos definir los campos e índices que deseemos
y aplicar el método CreateDataSet.
With ClientDataSet1.FieldDefs do Begin Clear; Add('Nombre',ftstring,30,true); Add('apellido 1º', ftstring 10, true); Add('apellido 2º',ftstring 10,true); ... End; With ClientDataSet1.indexdefs do Begin Clear; Add('xnombre,'nombre',[ixCaseInsensitive]); Add... End; ClientDataSet1.createdataset; |
Para cargar y salvar los datos puede utilizar los métodos LoadFromFile y SaveToFile, o bien utilizar la propiedad FileName del componente para no tener que utilizar los dos métodos. Vamos a realizar un ejemplo que nos permitira crear tablas anidadas. Al crear este tipo de tablas, todos los datos se almacenan en el mismo fichero. Las tablas anidadas funcionan a mayor velocidad que las relaciones master/detail. Para realizar el ejemplo seguimos los siguientes pasos:
Insertamos un componente TclientDataSet, modificamos la propiedad FieldsDefs y definimos los campos:
. Nombre ftstring 20
ftrequired
. Apellido1 ftstring
15 ftrequired
. Apellido2 ftstring
15
...
. Telefono ftDataSet
Para definir los campos de la detalle, seleccionamos la definición del campo Teléfono y editamos la propiedad ChildDefs donde definimos los campos:
. Telefono ftinteger
. Especif. Ftstring
20
Añadimos dos indices por medio de la propiedad indexdefs (por nombre y apellido).
Para almacenar la estructura pulsamos con el botón derecho del
ratón sobre el componente y ejecutamos el comando CreateDataSet.
Mediante el editor de campos añadimos los campos y para que los
datos aparezcan ordenados por nombre asignamos a la propiedad indexfieldnames
el campo nombre. Para la visualización de datos pordemos utilizar
un dbgrid. Si queremos que los datos aparezcan en dos dbgrid utilizaremos
otro clientdataset utilizando la propieda DataSetField de dicho componente
con el TclientDataset anterior. Si deseamos eliminar un dato de la tabla
detalle antes de eliminar el maestro realizaremos lo siguiente:
Clientdataset2.first; While not ClientDataSet2.eof do ClientDataset2.delete; |
Al utilizar el componente TclientDataset hay un nuevo campo, los campos
calculados internos. Para ello entrar en new field, en este componente
podemos ver dos nuevas opciones InternalCalc y Aggregate. El tipo Intercalc
se calcula durante la respuesta al evento OnCalcFields. La diferencia de
este tipo de campos a los conocidos campos calculados es que el valor de
los campos calculados internos se almacenan también junto al conjunto
de datos. La principal consecuencia de esta politica de almacenamiento
es que se pueden definir indices basados en este campo. Asi que tenemos
algo parecido a índices por expressiones para los conjuntos de datos
clientes. Si tenemos campos calculados normales e internos, el evento oncalcfields
se ejecutara dos veces, una vez para cada campo. Para diferenciarlos utilizaremos
la propiedad State del conjunto de datos. En un caso valdrá dsCalcFields
y en el otro dsInternalCalc. Partiendo del caso anterior, realizaremos
un ejemplo que tendrá dos opciones de menú: Fichero y Editar.
Dentro de la opción de fichero podremos elegir: Salvar cambios o
salir. Y en Editar elegimos deshacer registro actual o deshacer todos los
cambios. El código sería:
unit Unit3; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Mask, DBCtrls, ExtCtrls, Grids, DBGrids, Menus, Db; type TForm3 = class(TForm) MainMenu1: TMainMenu; File1: TMenuItem; Salvarcambios1: TMenuItem; Salir1: TMenuItem; Editar1: TMenuItem; deshacerregistroactual1: TMenuItem; deshacertodosloscambios1: TMenuItem; DBNavigator1: TDBNavigator; DBEdit1: TDBEdit; DBEdit2: TDBEdit; DBEdit3: TDBEdit; DBEdit4: TDBEdit; DBEdit5: TDBEdit; DBGrid1: TDBGrid; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; procedure DBGrid1Enter(Sender: TObject); procedure DBGrid1Exit(Sender: TObject); procedure Salir1Click(Sender: TObject); procedure Salvarcambios1Click(Sender: TObject); procedure deshacerregistroactual1Click(Sender: TObject); procedure deshacertodosloscambios1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form3: TForm3; implementation uses Unit2; {$R *.DFM} procedure TForm3.DBGrid1Enter(Sender: TObject); begin DBNavigator1.datasource:=datamodule2.Datasource2; end; procedure TForm3.DBGrid1Exit(Sender: TObject); begin DBNavigator1.datasource:=datamodule2.datasource1; end; procedure TForm3.Salir1Click(Sender: TObject); begin close; end; procedure TForm3.Salvarcambios1Click(Sender: TObject); begin if Datamodule2.ClientDataSet1.state in [dsedit,dsInsert] then datamodule2.clientdataset1.post; if Datamodule2.clientdataset2.state in [dsEdit,dsInsert] then Datamodule2.ClientDataSet2.Post; with datamodule2.clientdataset1 do begin mergechangelog; savetofile('clientes'); end; label1.caption:='REGISTROS SALVADOS'; label1.caption:=inttostr(datamodule2.clientdataset1.aggregates.find('totalrecords').value) //'registros salvados'; end; procedure TForm3.deshacerregistroactual1Click(Sender: TObject); begin datamodule2.ClientDataSet1.revertrecord; end; procedure TForm3.deshacertodosloscambios1Click(Sender: TObject); begin datamodule2.ClientDataSet1.cancelupdates; end; end. |
Vamos a realizar otro ejemplo utilizando el TclientDataset para ver una relación maestro detalle utilizando un solo dbgrid.
. Insertamos los dos TDatasource y dos Ttable
para establecer la relación maestro/detalle entre las dos tablas.
. Insertamos el TclientDataSet pulsar el
boton derecho del raton y elegir la opción "Assign Local Data" y
elegir la tabla principal. Entramos en el editor de campos del TclientDataset
y asignamos los campos.
Si deseamos visualizar los datos en otro dbgrid utilizaremos otro TclientDataset. Modificamos la propiedad DataSetField y lo unimos con el primer TclientDataSet.
NOTA: Los ejemplos se encuentran en el CD en:
.
\ejemplos\anidadas
.
\ejemplos\TClientDataSet
.
\ejemplos\masterdetail