378 lines
11 KiB
ObjectPascal
378 lines
11 KiB
ObjectPascal
|
|
unit uDataTableUtils;
|
|||
|
|
|
|||
|
|
interface
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
uDACDSDataTable, uDADataTable, uDAInterfaces;
|
|||
|
|
|
|||
|
|
const
|
|||
|
|
ID_NULO = -9000;
|
|||
|
|
ID_TODOS = -9001;
|
|||
|
|
ID_PRIMERO = -9002;
|
|||
|
|
|
|||
|
|
type
|
|||
|
|
TModoDuplicarRegistros = (mdrTodos, mdrActual, mdrSeleccionados);
|
|||
|
|
|
|||
|
|
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
|||
|
|
var ATarget : TDACDSDataTable;
|
|||
|
|
RemoteUpdate: Boolean = True);
|
|||
|
|
|
|||
|
|
procedure DuplicarRegistro(ASource : TDADataTable; ATarget : TDADataTable);
|
|||
|
|
procedure DuplicarRegistros(ASource : TDADataTable; ATarget : TDADataTable;
|
|||
|
|
AModo : TModoDuplicarRegistros);
|
|||
|
|
|
|||
|
|
procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable;
|
|||
|
|
const OnlySelectedRows : Boolean = False);
|
|||
|
|
|
|||
|
|
procedure DeleteAllTable(const ADataTable : TDADataTable);
|
|||
|
|
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
|||
|
|
|
|||
|
|
procedure EnlazarMaestroDetalle(AMasterDataSource : TDADataSource;
|
|||
|
|
ADetail : IDAStronglyTypedDataTable);
|
|||
|
|
|
|||
|
|
implementation
|
|||
|
|
|
|||
|
|
uses
|
|||
|
|
uDAClasses, SysUtils, uDABINAdapter, uROTypes, cxControls,
|
|||
|
|
Dialogs, Variants, uDBSelectionListUtils, uROClasses;
|
|||
|
|
|
|||
|
|
|
|||
|
|
{procedure EliminarNoSeleccionados(const ASource : IDADataset;
|
|||
|
|
var ATarget : TDADataTable);
|
|||
|
|
var
|
|||
|
|
AObj : ISelectedRowList;
|
|||
|
|
i : Integer;
|
|||
|
|
begin
|
|||
|
|
if not Supports(ASource, ISelectedRowList, aObj) then
|
|||
|
|
Exit;
|
|||
|
|
|
|||
|
|
// ATarget.DisableControls;
|
|||
|
|
// ATarget.DisableEventHandlers;
|
|||
|
|
ShowHourglassCursor;
|
|||
|
|
try
|
|||
|
|
ATarget.Open;
|
|||
|
|
ATarget.Last;
|
|||
|
|
while ATarget.RecordCount > AObj.SelectedRows.Count do
|
|||
|
|
begin
|
|||
|
|
if AObj.SelectedRows.IndexOf(ATarget.RecIDValue) < 0 then
|
|||
|
|
ATarget.Delete
|
|||
|
|
else
|
|||
|
|
ATarget.Prior;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
// ATarget.EnableControls;
|
|||
|
|
// ATarget.EnableControls;
|
|||
|
|
HideHourglassCursor;
|
|||
|
|
end;
|
|||
|
|
end;}
|
|||
|
|
|
|||
|
|
|
|||
|
|
procedure DeleteAllTable(const ADataTable : TDADataTable);
|
|||
|
|
begin
|
|||
|
|
ADataTable.ClearRows;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure CloneDataTable(const ASource : TDACDSDataTable;
|
|||
|
|
var ATarget : TDACDSDataTable; RemoteUpdate: Boolean);
|
|||
|
|
var
|
|||
|
|
i : Integer;
|
|||
|
|
begin
|
|||
|
|
with ATarget do
|
|||
|
|
begin
|
|||
|
|
RemoteService := ASource.GetRemoteService;
|
|||
|
|
Adapter := ASource.GetAdapter;
|
|||
|
|
|
|||
|
|
//BusinessRulesID := ASource.BusinessRulesID;
|
|||
|
|
Randomize;
|
|||
|
|
Name := ASource.Name + '_' + IntToStr(Random(MAXINT));
|
|||
|
|
LogicalName := ASource.LogicalName;
|
|||
|
|
|
|||
|
|
Params.AssignParamCollection(ASource.Params);
|
|||
|
|
|
|||
|
|
if Assigned(ASource.LocalSchema) then
|
|||
|
|
LocalSchema := ASource.LocalSchema
|
|||
|
|
else begin
|
|||
|
|
with SchemaCall do
|
|||
|
|
begin
|
|||
|
|
MethodName := ASource.SchemaCall.MethodName;
|
|||
|
|
for i := 0 to ASource.SchemaCall.Params.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
with Params.Add do begin
|
|||
|
|
Name := ASource.SchemaCall.Params[i].Name;
|
|||
|
|
ParamType := ASource.SchemaCall.Params[i].ParamType;
|
|||
|
|
DataType := ASource.SchemaCall.Params[i].DataType;
|
|||
|
|
Value := ASource.SchemaCall.Params[i].Value;
|
|||
|
|
UserClassName := ASource.SchemaCall.Params[i].UserClassName;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
ATarget.Fields.AssignFieldCollection(ASource.Fields); // o tambi<62>n ATarget.LoadSchema;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
with DataUpdateCall do
|
|||
|
|
begin
|
|||
|
|
MethodName := ASource.DataUpdateCall.MethodName;
|
|||
|
|
for i := 0 to ASource.DataUpdateCall.Params.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
with Params.Add do begin
|
|||
|
|
Name := ASource.DataUpdateCall.Params[i].Name;
|
|||
|
|
ParamType := ASource.DataUpdateCall.Params[i].ParamType;
|
|||
|
|
DataType := ASource.DataUpdateCall.Params[i].DataType;
|
|||
|
|
Value := ASource.DataUpdateCall.Params[i].Value;
|
|||
|
|
UserClassName := ASource.DataUpdateCall.Params[i].UserClassName;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
with ScriptCall do
|
|||
|
|
begin
|
|||
|
|
MethodName := ASource.ScriptCall.MethodName;
|
|||
|
|
for i := 0 to ASource.ScriptCall.Params.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
with Params.Add do begin
|
|||
|
|
Name := ASource.ScriptCall.Params[i].Name;
|
|||
|
|
ParamType := ASource.ScriptCall.Params[i].ParamType;
|
|||
|
|
DataType := ASource.ScriptCall.Params[i].DataType;
|
|||
|
|
Value := ASource.ScriptCall.Params[i].Value;
|
|||
|
|
UserClassName := ASource.ScriptCall.Params[i].UserClassName;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
with DataRequestCall do
|
|||
|
|
begin
|
|||
|
|
MethodName := ASource.DataRequestCall.MethodName;
|
|||
|
|
for i := 0 to ASource.DataRequestCall.Params.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
with Params.Add do begin
|
|||
|
|
begin
|
|||
|
|
Name := ASource.DataRequestCall.Params[i].Name;
|
|||
|
|
ParamType := ASource.DataRequestCall.Params[i].ParamType;
|
|||
|
|
DataType := ASource.DataRequestCall.Params[i].DataType;
|
|||
|
|
Value := ASource.DataRequestCall.Params[i].Value;
|
|||
|
|
UserClassName := ASource.DataRequestCall.Params[i].UserClassName;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
with MasterParamsMappings do
|
|||
|
|
for i := 0 to ASource.MasterParamsMappings.Count - 1 do
|
|||
|
|
Add(ASource.MasterParamsMappings.Strings[i]);
|
|||
|
|
|
|||
|
|
with MasterRequestMappings do
|
|||
|
|
for i := 0 to ASource.MasterRequestMappings.Count - 1 do
|
|||
|
|
Add(ASource.MasterRequestMappings.Strings[i]);
|
|||
|
|
|
|||
|
|
MasterMappingMode := ASource.MasterMappingMode;
|
|||
|
|
|
|||
|
|
MasterFields := ASource.MasterFields;
|
|||
|
|
MasterOptions := ASource.MasterOptions;
|
|||
|
|
|
|||
|
|
DetailFields := ASource.DetailFields;
|
|||
|
|
DetailOptions := ASource.DetailOptions;
|
|||
|
|
|
|||
|
|
RemoteUpdatesOptions := ASource.RemoteUpdatesOptions;
|
|||
|
|
StreamingOptions := ASource.StreamingOptions;
|
|||
|
|
RemoteFetchEnabled := ASource.RemoteFetchEnabled;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
if not RemoteUpdate then
|
|||
|
|
begin
|
|||
|
|
ATarget.LogChanges := False;
|
|||
|
|
ATarget.RemoteFetchEnabled := False;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
function DeltaValuesAreDifferent(const aDelta : IDADelta): boolean;
|
|||
|
|
var
|
|||
|
|
i, x : integer;
|
|||
|
|
OldNewAreDifferent: boolean;
|
|||
|
|
begin
|
|||
|
|
OldNewAreDifferent := FALSE;
|
|||
|
|
for i := 0 to (aDelta.Count-1) do
|
|||
|
|
begin
|
|||
|
|
for x := 0 to (aDelta.LoggedFieldCount-1) do
|
|||
|
|
begin
|
|||
|
|
if aDelta.LoggedFieldTypes[x] <> datBlob then
|
|||
|
|
OldNewAreDifferent := (aDelta.Changes[i].OldValues[x] <> aDelta.Changes[i].NewValues[x]);
|
|||
|
|
|
|||
|
|
if OldNewAreDifferent then
|
|||
|
|
Break; // Abandon iteration at the first difference between old and new.
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
if OldNewAreDifferent then
|
|||
|
|
Break; // Abandon iteration at the first difference between old and new.
|
|||
|
|
end;
|
|||
|
|
result := OldNewAreDifferent;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
procedure CopyDataTable(ASource : TDADataTable; ATarget : TDADataTable;
|
|||
|
|
const OnlySelectedRows : Boolean = False);
|
|||
|
|
var
|
|||
|
|
DABin: Binary;
|
|||
|
|
DAAdapter : TDABINAdapter;
|
|||
|
|
AFilter : String;
|
|||
|
|
AFiltered : Boolean;
|
|||
|
|
AObj : ISelectedRecords;
|
|||
|
|
i : Integer;
|
|||
|
|
begin
|
|||
|
|
AFilter := '';
|
|||
|
|
AFiltered := False;
|
|||
|
|
|
|||
|
|
if OnlySelectedRows then
|
|||
|
|
begin
|
|||
|
|
if not Supports(ASource, ISelectedRecords, aObj) then
|
|||
|
|
raise Exception.Create('El origen de datos no soporta la interfaz ISelectedRecords (CopyDataTable)');
|
|||
|
|
|
|||
|
|
if ASource.Filtered then
|
|||
|
|
begin
|
|||
|
|
AFiltered := True;
|
|||
|
|
AFilter := ASource.Filter;
|
|||
|
|
ASource.Filtered := False;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
ASource.Filter := '';
|
|||
|
|
if ASource.Active then
|
|||
|
|
ASource.Close;
|
|||
|
|
|
|||
|
|
for i := 0 to AObj.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
if (i > 0) then
|
|||
|
|
ASource.Filter := ASource.Filter + ' or ';
|
|||
|
|
ASource.Filter := ASource.Filter + '(ID = ' + IntToStr(AObj.Items[i]) + ')';
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
ASource.Filtered := True;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
DABin := Binary.Create;
|
|||
|
|
DAAdapter := TDABINAdapter.Create(nil);
|
|||
|
|
try
|
|||
|
|
ATarget.LogicalName := ASource.LogicalName; // We need to specify new dataset LogicalName
|
|||
|
|
ATarget.RemoteFetchEnabled := False; // "Desconectamos" la tabla destino del servidor
|
|||
|
|
|
|||
|
|
if not ASource.Active then
|
|||
|
|
ASource.Open;
|
|||
|
|
ASource.First;
|
|||
|
|
|
|||
|
|
DAAdapter.Initialize(DABin, aiWrite);
|
|||
|
|
DAAdapter.WriteDataset(DABin, ASource, [woRows]);
|
|||
|
|
DAAdapter.Initialize(DABin, aiReadFromBeginning);
|
|||
|
|
DAAdapter.ReadDataset(DABin, ATarget);
|
|||
|
|
DAAdapter.Finalize;
|
|||
|
|
|
|||
|
|
ATarget.RemoteFetchEnabled := True; // "Conectamos" la tabla del servidor otra vez
|
|||
|
|
|
|||
|
|
// Dejar el filtro de la tabla origen como estaba
|
|||
|
|
if OnlySelectedRows then
|
|||
|
|
begin
|
|||
|
|
ASource.Filtered := False;
|
|||
|
|
ASource.Filter := AFilter;
|
|||
|
|
if AFiltered then
|
|||
|
|
ASource.Filtered := True;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
finally
|
|||
|
|
FreeAndNil(DABin);
|
|||
|
|
FreeAndNil(DAAdapter);
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
procedure DuplicarRegistro(ASource : TDADataTable; ATarget : TDADataTable);
|
|||
|
|
var
|
|||
|
|
i: Integer;
|
|||
|
|
ATargetField: TDAField;
|
|||
|
|
ASourceField: TDAField;
|
|||
|
|
ADetailFields : String;
|
|||
|
|
begin
|
|||
|
|
if not ASource.Active then
|
|||
|
|
ASource.Open;
|
|||
|
|
|
|||
|
|
if not ASource.Active then
|
|||
|
|
ATarget.Open;
|
|||
|
|
|
|||
|
|
// <20>ATarget es una tabla detalle?
|
|||
|
|
if Assigned(ATarget.MasterSource) then
|
|||
|
|
begin
|
|||
|
|
case ATarget.MasterMappingMode of
|
|||
|
|
//mmDataRequest: //Sin hacer;
|
|||
|
|
mmParams: ADetailFields := ATarget.DetailFields;
|
|||
|
|
end;
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
ADetailFields := '';
|
|||
|
|
|
|||
|
|
ATarget.Insert;
|
|||
|
|
{ Hay que desactivar los eventos para que dejan de funcionar
|
|||
|
|
las reglas de negocio y no nos interfieran en la copia
|
|||
|
|
de valores de los campos. }
|
|||
|
|
ATarget.DisableEventHandlers;
|
|||
|
|
try
|
|||
|
|
for i := 0 to ASource.Fields.Count - 1 do
|
|||
|
|
begin
|
|||
|
|
ASourceField := ASource.Fields[i];
|
|||
|
|
ATargetField := ATarget.FindField(ASourceField.Name);
|
|||
|
|
|
|||
|
|
if Assigned(ATargetField) then
|
|||
|
|
begin
|
|||
|
|
// Los campos AutoInc no se rellenan y tampoco los campos que
|
|||
|
|
// formen parte de la relaci<63>n maestro-detalle en el
|
|||
|
|
// caso de que la tabla destino sea una tabla detalle.
|
|||
|
|
if (ATargetField.DataType <> datAutoInc) and
|
|||
|
|
(Pos(ATargetField.Name, ADetailFields) = 0) then
|
|||
|
|
ATargetField.Value := ASourceField.Value;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
finally
|
|||
|
|
ATarget.EnableEventHandlers;
|
|||
|
|
ATarget.Post;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
procedure DuplicarRegistros(ASource : TDADataTable; ATarget : TDADataTable;
|
|||
|
|
AModo : TModoDuplicarRegistros);
|
|||
|
|
begin
|
|||
|
|
if not ASource.Active then
|
|||
|
|
ASource.Open;
|
|||
|
|
|
|||
|
|
if not ATarget.Active then
|
|||
|
|
ATarget.Open;
|
|||
|
|
|
|||
|
|
if AModo = mdrActual then
|
|||
|
|
DuplicarRegistro(ASource, ATarget) //ATarget.CloneSelectedRecord(ASource, True)
|
|||
|
|
else begin
|
|||
|
|
ASource.First;
|
|||
|
|
while not ASource.EOF do
|
|||
|
|
begin
|
|||
|
|
DuplicarRegistro(ASource, ATarget);
|
|||
|
|
ASource.Next;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
|
|||
|
|
procedure EnlazarMaestroDetalle(AMasterDataSource : TDADataSource;
|
|||
|
|
ADetail : IDAStronglyTypedDataTable);
|
|||
|
|
begin
|
|||
|
|
if Assigned(ADetail) then
|
|||
|
|
begin
|
|||
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD> MUY IMPORTANTE !!!!!!!!!!!!!!!!!!
|
|||
|
|
ADetail.DataTable.DisableEventHandlers;
|
|||
|
|
try
|
|||
|
|
ADetail.DataTable.MasterSource := AMasterDataSource;
|
|||
|
|
finally
|
|||
|
|
{ Hay que activar los eventos porque dejan de funcionar
|
|||
|
|
las reglas de negocio al establecer la relaci<EFBFBD>n
|
|||
|
|
maestro-detalle. (Fallo de Data Abstract 3) }
|
|||
|
|
ADetail.DataTable.EnableEventHandlers;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
end;
|
|||
|
|
|
|||
|
|
end.
|