0% encontró este documento útil (0 votos)
23 vistas10 páginas

DLL 2 - Ayuda para Crear Eventos - Delphi Snippet - RowObject Comunidad ...

Este documento presenta tres clases (TDatasetObject, TRowObject, TFieldObject) que facilitan la manipulación de datos en eventos de Delphi para a3ERP. La clase TDatasetObject encapsula conjuntos de datos (registros). TRowObject encapsula cada registro y sus campos. TFieldObject proporciona métodos para manipular los valores de los campos. El código provisto permite acceder y modificar registros/campos de forma más sencilla que usar matrices de variantes directamente.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
23 vistas10 páginas

DLL 2 - Ayuda para Crear Eventos - Delphi Snippet - RowObject Comunidad ...

Este documento presenta tres clases (TDatasetObject, TRowObject, TFieldObject) que facilitan la manipulación de datos en eventos de Delphi para a3ERP. La clase TDatasetObject encapsula conjuntos de datos (registros). TRowObject encapsula cada registro y sus campos. TFieldObject proporciona métodos para manipular los valores de los campos. El código provisto permite acceder y modificar registros/campos de forma más sencilla que usar matrices de variantes directamente.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 10

23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

Ayuda para crear eventos: Delphi snippet –


RowObject

ENE 26
Publicado por El monstruo de Caerbannog
Como si me tratase del doctor Frankenstein
(http://www.youtube.com/watch?v=muTcYb1lCbU) perseguido por
mi creación, decido abandonar mi retiro para afrontar a la bestia a
la que un día aciago, jugando a ser programador, di
vida: RowObject.pas

Sí, varias han sido las llamadas que hemos recibido últimamente de
desarrolladores que se quejaban de fallos en un código que, en
ciertos casos, hemos proporcionado como ejemplo de cómo manipular de manera fácil unas
matrices de variants en delphi usadas en algunos eventos de a3ERP. Para evitar tener que aplicar la
medicina de la escupidera de bronce a alguno (se evita leyendo algunos artículos de este blog),
publicaré aquí la versión más reciente de dicha unidad.

Bien, el fragmento de código que publico a continuación contiene tres clases principalmente que nos
evitarán tener que trabajar con las engorrosas matrices de matrices de variants (las matrices
unidimensionales son muy fáciles de manipular, con un caramelo basta).

TDatasetObject

Esta clase encapsula lo que en el artículo en el que se describían los tipos usados en los eventos
a3ERP (http://comunidadnexus.com/2009/03/26/yo-y-nexus-la-consumacion/) denominé “Conjunto
de datos”. Se encarga de, dado un variant que contiene un “Conjunto de datos”, o sea una lista de
“Registros”, crear una lista de objetos (TRowObject) para cada uno de los registros. Permite, de esta
manera, un acceso indexado a los registros. Adicionalmente permite devolver los cambios que se
hayan producido en los registros al variant original.

TRowObject

Esta otra encapsula lo que en el enlace del punto anterior se denominó “Registro”. Su
responsabilidad es mantener la lista de campos definidos en el registro encapsulado así como
proveer de algunas facilidades para localizarlos, ya sea por índice o nombre. Además es capaz de
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 1/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

devolver los cambios que se produjeran en los campos mantenidos al variant.

TFieldObject

La última de las tres clases simplemente permite algunas facilidades extra para manipular los
valores de cada uno de los campos, al estilo de los TField, del tipo denominado “Registro”, ya
encapsulado por la clase anterior.

El código: RowObject.pas

Que menos que decir que se entrega como está, con sus bugs y demás atrocidades que se puedan
encontrar. La mayor versión de Delphi con la que se ha compilado es la 2006. La última vez que lo
intenté, compiló. Con versiones superiores es muy posible que de problemas por el soporte
UNICODE.
001 unit RowObject;
002
003 interface
004
005 uses
006 SysUtils, Classes, Contnrs;
007
008 type
009 ERowObjectException = class(Exception);
010 EInvalidFieldnameException = class(ERowObjectException);
011 EInvalidGetFieldsParameter = class(ERowObjectException);
012
013 TDatasetObject = class;
014
015 TRowObject = class;
016 TFieldObject = class
017 private
018 FIndex: Integer;
019 FValue,
020 FOldValue: Variant;
021 FRow: TRowObject;
022 FModified: Boolean;
023 FFieldname: string;
024 protected
025 procedure SetAsBoolean(const AValue: Boolean);
026 procedure SetAsCurrency(const AValue: Currency);
027 procedure SetAsFloat(const AValue: Double);
028 procedure SetAsInteger(const AValue: Integer);
029 procedure SetAsString(const AValue: string);
030 function GetAsCurrency: Currency;
031 function GetAsInteger: Integer;
032 function GetAsString : string;
033 function GetAsBoolean: Boolean;
034 function GetAsFloat: Double;
035 procedure SetValue(const Value: Variant);
036 procedure ApplyTo(var Line: Variant);
037 public
038 constructor Create(const AIndex: Integer; ARow: TRowObject);
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 2/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

039 property AsCurrency: Currency read GetAsCurrency write SetAsCurrency;


040 property AsInteger: Integer read GetAsInteger write SetAsInteger;
041 property AsString : string read GetAsString write SetAsString;
042 property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean;
043 property AsFloat: Double read GetAsFloat write SetAsFloat;
044 property Modified: Boolean read FModified;
045 property Value: Variant read FValue write SetValue;
046 property OldValue: Variant read FOldValue;
047 function IsEmpty: Boolean; overload;
048 class function IsEmpty(AValue: Variant): Boolean; overload;
049 class function VarAreEqual(const Var1, Var2: Variant): Boolean;
050 procedure CancelChange;
051 property Fieldname: string read FFieldname;
052 property Index: Integer read FIndex;
053 property Row: TRowObject read FRow;
054 end;
055
056 TRowObject = class
057 private
058 FData: Variant;
059 FDataset: TDatasetObject;
060 FFields: TObjectList;
061 FFieldNameIndex: TStrings;
062 protected
063 function GetBufferFieldCount: Integer;
064 function GetBufferFieldName(const Index: Integer): string;
065 function GetBufferFieldValue(const Index: Integer): Variant;
066 procedure BuildFields;
067 procedure CheckIndex(const AIndex: Integer);
068 function GetModified: Boolean;
069 function GetFields(const FieldNameOrIndex: Variant): TFieldObject;
070 function GetFieldCount: Integer;
071 public
072 constructor Create(const Line: Variant; ADatasetObject: TDatasetObject = nil); overload;
073 destructor Destroy; override;
074 procedure ApplyTo(var Line: Variant);
075 procedure CancelChanges;
076 property Modified: Boolean read GetModified;
077 function FindField(const AFieldname: string): TFieldObject;
078 function FieldByName(const AFieldname: string): TFieldObject;
079 property Fields[const FieldNameOrIndex: Variant]: TFieldObject read GetFields; default;
080 property FieldCount: Integer read GetFieldCount;
081 property Dataset: TDatasetObject read FDataset;
082 end;
083
084 TDatasetObject = class
085 private
086 FRows: TObjectList;
087 function GetModified: Boolean;
088 protected
089 function GetCount: Integer;
090 function GetRows(const Index: Integer): TRowObject;
091 public
092 constructor Create; overload;
093 constructor Create(const Lines: Variant); overload;
094 destructor Destroy; override;
095 procedure AddRow(ARow: TRowObject);
096 function RemoveRow(ARow: TRowObject): TRowObject;
097 procedure ApplyTo(var Lines: Variant);
098 // todo: funciones de busqueda, modificado, etc...
099 procedure Sort(Compare: TListSortCompare);
100 property Count: Integer read GetCount;
101 property Rows[const Index: Integer]: TRowObject read GetRows; default;
102 property Modified: Boolean read GetModified;
103 end;
104
105 implementation
106
107 uses
108 Variants;

comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 3/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

109
110 { TRowObject }
111
112 constructor TRowObject.Create(const Line: Variant; ADatasetObject: TDatasetObject = nil);
113 begin
114 inherited Create;
115 FData := Line;
116 FFields := TObjectList.Create(True);
117 FFieldNameIndex := TStringList.Create;
118 TStringList(FFieldNameIndex).Sorted := True;
119 FDataset := ADatasetObject;
120 BuildFields;
121 end;
122
123 procedure TRowObject.BuildFields;
124 var
125 Idx, Max: Integer;
126 Field: TFieldObject;
127 begin
128 FFields.Clear;
129 FFieldNameIndex.Clear;
130 Max := GetBufferFieldCount - 1;
131 for Idx := 0 to Max do begin
132 Field := TFieldObject.Create(Idx, Self);
133 FFields.Add(Field);
134 FFieldNameIndex.AddObject(Field.Fieldname, Field);
135 end;
136 end;
137
138 destructor TRowObject.Destroy;
139 begin
140 FFieldNameIndex.Free;
141 FFields.Free;
142 inherited;
143 end;
144
145 function TRowObject.GetBufferFieldCount: Integer;
146 begin
147 Result := FData[0];
148 end;
149
150 procedure TRowObject.CheckIndex(const AIndex: Integer);
151 begin
152 if (AIndex > GetFieldCount) then
153 raise ERangeError.CreateFmt('Índice [%d] fuera de rango [%d, %d]', [AIndex, 0, GetFieldCount - 1]);
154 end;
155
156 function TRowObject.GetBufferFieldValue(const Index: Integer): Variant;
157 begin
158 CheckIndex(Index);
159 Result := FData[Index + 1][1];
160 end;
161
162 function TRowObject.GetBufferFieldName(const Index: Integer): string;
163 begin
164 CheckIndex(Index);
165 Result := FData[Index + 1][0];
166 end;
167
168 procedure TRowObject.ApplyTo(var Line: Variant);
169 var
170 Idx: Integer;
171 begin
172 for Idx := 0 to FieldCount - 1 do
173 Fields[Idx].ApplyTo(Line);
174 end;
175
176 procedure TRowObject.CancelChanges;
177 var
178 Idx: Integer;
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 4/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

179 begin
180 for Idx := 0 to FieldCount - 1 do
181 Fields[Idx].CancelChange;
182 end;
183
184 function TRowObject.GetModified: Boolean;
185 var
186 Idx: Integer;
187 begin
188 for Idx := 0 to FieldCount - 1 do begin
189 Result := Fields[Idx].Modified;
190 if Result then Exit;
191 end;
192 Result := False;
193 end;
194
195 function TRowObject.FieldByName(const AFieldname: string): TFieldObject;
196 begin
197 Result := FindField(AFieldname);
198 if not Assigned(Result) then
199 raise EInvalidFieldnameException.CreateFmt('No se encontró campo [%s]', [AFieldname]);
200 end;
201
202 function TRowObject.FindField(const AFieldname: string): TFieldObject;
203 var
204 Idx: Integer;
205 begin
206 Idx := FFieldNameIndex.IndexOf(UpperCase(AFieldname));
207 if Idx = -1 then
208 Result := nil
209 else
210 Result := TFieldObject(FFieldNameIndex.Objects[Idx]);
211 end;
212
213 function TRowObject.GetFieldCount: Integer;
214 begin
215 Result := FFields.Count;
216 end;
217
218 function TRowObject.GetFields(const FieldNameOrIndex: Variant): TFieldObject;
219 begin
220 if VarIsOrdinal(FieldNameOrIndex) then
221 Result := TFieldObject(FFields[FieldNameOrIndex])
222 else if VarIsStr(FieldNameOrIndex) then
223 Result := FieldByName(FieldNameOrIndex)
224 else
225 raise EInvalidGetFieldsParameter.Create('Parametro FieldNameOrIndex de tipo incorrecto');
226 end;
227
228 { TDatasetObject }
229
230 constructor TDatasetObject.Create(const Lines: Variant);
231 var
232 Idx, Max: Integer;
233 begin
234 Create;
235 Max := Lines[0];
236 for Idx := 1 to Max do
237 AddRow(TRowObject.Create(Lines[Idx], Self));
238 end;
239
240 constructor TDatasetObject.Create;
241 begin
242 inherited Create;
243 FRows := TObjectList.Create;
244 end;
245
246 destructor TDatasetObject.Destroy;
247 begin
248 FreeAndNil(FRows);
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 5/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

249 inherited;
250 end;
251
252 procedure TDatasetObject.AddRow(ARow: TRowObject);
253 begin
254 FRows.Add(ARow);
255 end;
256
257 procedure TDatasetObject.ApplyTo(var Lines: Variant);
258 var
259 Idx: Integer;
260 Aux: Variant;
261 begin
262 for Idx := 1 to Count do begin
263 Aux := Lines[Idx];
264 Rows[Idx - 1].ApplyTo(Aux);
265 VarArrayPut(Lines, Aux, [Idx]);
266 end;
267 end;
268
269 function TDatasetObject.GetCount: Integer;
270 begin
271 Result := FRows.Count;
272 end;
273
274 function TDatasetObject.GetModified: Boolean;
275 var
276 Idx: Integer;
277 begin
278 for Idx := 0 to Count - 1 do begin
279 Result := Rows[Idx].Modified;
280 if Result then Exit;
281 end;
282 Result := False;
283 end;
284
285 function TDatasetObject.GetRows(const Index: Integer): TRowObject;
286 begin
287 Result := TRowObject(FRows[Index]);
288 end;
289
290 function TDatasetObject.RemoveRow(ARow: TRowObject): TRowObject;
291 begin
292 FRows.Remove(ARow);
293 Result := ARow;
294 end;
295
296 procedure TDatasetObject.Sort(Compare: TListSortCompare);
297 begin
298 FRows.Sort(Compare);
299 end;
300
301 { TFieldObject }
302
303 procedure TFieldObject.CancelChange;
304 begin
305 if not FModified then Exit;
306 FValue := FOldValue;
307 end;
308
309 constructor TFieldObject.Create(const AIndex: Integer; ARow: TRowObject);
310 begin
311 inherited Create;
312 FValue := ARow.GetBufferFieldValue(AIndex);
313 FFieldname := ARow.GetBufferFieldName(AIndex);
314 FOldValue := FValue;;
315 FIndex := AIndex;
316 FRow := ARow;
317 end;
318
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 6/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

319 procedure TFieldObject.ApplyTo(var Line: Variant);


320 var
321 Aux: Variant;
322 begin
323 Aux := Line[Index + 1];
324 if VarAreEqual(Value, Aux[1]) then Exit;
325 VarArrayPut(Aux, Value, [1]);
326 VarArrayPut(Line, Aux, [Index + 1]);
327 FOldValue := FValue;
328 end;
329
330 procedure TFieldObject.SetAsBoolean(const AValue: Boolean);
331 begin
332 Value := AValue;
333 end;
334
335 procedure TFieldObject.SetAsCurrency(const AValue: Currency);
336 begin
337 Value := AValue;
338 end;
339
340 procedure TFieldObject.SetAsFloat(const aValue: Double);
341 begin
342 Value := AValue;
343 end;
344
345 procedure TFieldObject.SetAsInteger(const AValue: Integer);
346 begin
347 Value := AValue;
348 end;
349
350 procedure TFieldObject.SetAsString(const AValue: string);
351 begin
352 Value := AValue;
353 end;
354
355 procedure TFieldObject.SetValue(const Value: Variant);
356 begin
357 if (VarAreEqual(FValue, Value)) then Exit;
358 FValue := Value;
359 FModified := not VarAreEqual(FValue, OldValue);
360 end;
361
362 class function TFieldObject.VarAreEqual(const Var1, Var2: Variant): Boolean;
363 begin
364 try
365 Result := VarSameValue(Var1, Var2);
366 except
367 Result := False;
368 end;
369 end;
370
371 function TFieldObject.GetAsBoolean: Boolean;
372 begin
373 if IsEmpty then
374 Result := False
375 else
376 Result := Value;
377 end;
378
379 function TFieldObject.GetAsFloat: Double;
380 begin
381 if IsEmpty then
382 Result := 0
383 else
384 Result := Value;
385 end;
386
387 function TFieldObject.GetAsInteger: Integer;
388 begin
comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 7/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

389 if IsEmpty then


390 Result := 0
391 else
392 Result := Value;
393 end;
394
395 function TFieldObject.GetAsString: string;
396 begin
397 if IsEmpty then
398 Result := ''
399 else
400 Result := Value;
401 end;
402
403 class function TFieldObject.IsEmpty(AValue: Variant): Boolean;
404 begin
405 Result := VarIsNull(AValue) or (VarIsStr(AValue) and (AValue = ''));
406 end;
407
408 function TFieldObject.IsEmpty: Boolean;
409 begin
410 Result := TFieldObject.IsEmpty(Value);
411 end;
412
413 function TFieldObject.GetAsCurrency: Currency;
414 begin
415 if IsEmpty then
416 Result := 0
417 else
418 Result := Value;
419 end;
420
421 end.

Como podemos ver, explícitamente hemos creado un TDatasetObject pero manipulado un


TRowObject y un TFieldObject.

TRowObject

En caso de que estuviéramos implementando algún evento de documentos en versión 7, o alguno de


líneas de documento (por ejemplo), podemos simplificar el manipulado del registro que nos llega
con esta clase de la siguiente manera:
01 procedure ANTESDEGUARDARLINEA(Documento: String; Cabecera: Variant; Linea: Variant): Variant; stdcall;
02 var
03 Row: TRowObject;
04 begin
05 Result := Null;
06 if Documento <> 'FV' then Exit; // Sólo en facturas de venta
07 Row := TRowObject.Create(Linea);
08 try
09 if Row.FieldByName('CODART').AsString = '0' then
10 SumarPuntosCliente(Row.FieldByName('UNIDADES').AsFloat);
11 finally
12 Row.Free;
13 end;
14 end;

comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 8/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

Mejoras posibles

Hay muchas. Por ejemplo soportar versiones de Delphi UNICODE trabajando contra a3ERP con
cadenas AnsiString, que no haga falta indicar el destino en los método ApplyTo (y por lo tanto
queden como Apply sin más). Que el TRowObject permita construir registros al vuelo, sin necesidad
de darle un variant origen, para así facilitar el devolver campos a modificar en los métodos
“AntesDeGuardarLinea”, etc…

Os animo a que uséis este código y compartáis con nosotros las


mejoras que introduzcáis. Para ello podéis enviarlas como comentarios
a este artículo y así podremos discutirlas entre todos e incorporarlas.
Hacedlo o no lo hagáis, pero sabed que una escupidera os vigila…

ADVERTISEMENT

Acerca de El monstruo de Caerbannog

Temible guardián de la gruta que esconde un temible y obscuro secreto...


View all posts by El monstruo de Caerbannog »
Publicado el enero 26, 2012 en Desarrolladores, Distribuidores, Programación, Versión 8, Versión 9
y etiquetado en código, delphi, dll terceros. Guarda el enlace permanente. Dejar un comentario.

comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 9/10
23/09/12 Ayuda para crear eventos: Delphi snippet – RowObject « Comunidad a3ERP

Dejar un comentario

Blog de WordPress.com. Tema: Mystique por digitalnature.

comunidadnexus.com/2012/01/26/delphi-snippet-rowobject/ 10/10

También podría gustarte