PDA

Ver la Versión Completa : Consulta con ADOTABLE


nefore
15-06-2013, 20:37:19
Hola, estoy trabajando con una BD de Access 2007 en Delphi 7. Necesito una funcion busca, la cual me devuelva verdadero si encuentra un determinado valor. Los criterios de busqueda son por Codigo, DNI, y por Nombre.
El codigo es el siguiente:

type
Tclasepropietario = class (Tclasepersona)
codigo_titular: Integer;
sexo: string;
fecha_modificacion: TDate;
fecha_desde: TDate;

Procedure grabardatos;
function busqueda (dato:string;opcion:Integer):Boolean;
end;

Implementation

function Tclasepropietario.busqueda(dato: string; opcion: Integer): Boolean;
begin
ADOTable1.Filtered := True;
case opcion of

1: begin
ADOTable1.Filter:= 'CODIGO_TITULAR LIKE '''+'%'+dato+'%''';
if (ADOTable1.RecordCount > 0)
then
begin
Result:=True;
end
else;
begin
Result:=False;
end;
end;
2: begin
ADOTable1.Filter:='DNI LIKE '+dato+'';
if (ADOTable1.RecordCount > 0)
then
begin
Result:=True;
end
else;
begin
Result:=False;
end;
end;
3: begin
ADOTable1.Filter:='APELLIDO_NOMBRES LIKE '''+dato+'*''';
if (ADOTable1.RecordCount > 0)
then
begin
busqueda:=True;
end
else;
begin
busqueda:=False;
end;
end;
end;
end;

En donde dato seria por ejemplo un edit, el cual posee segun lo que vaya a buscar, y opcion seria un "case" que manejo internamente para seleccionar que tipo de busqueda quiero realizar. Pues bien, a todo esto mi problema es que, en el caso del DNI y del CODIGO, en la tabla estan cargados como numeros y aca el parametro dato es string, y cuando por ejemplo realizo un alta de Propietarios necesito saber si el DNI ingresado ya esta cargado o no, pero al momento de llamar a la funcion me salta un error de "No se pudo abrir el filtro" mi duda es ¿existe alguna forma de que la consulta sql me convierta a numero el string "dato" y como seria?

ecfisa
15-06-2013, 23:39:21
Hola nefore, bienvenido a Club Delphi :)

Como a todos los recién llegados te invitamos a que leas nuestra guía de estilo (http://www.clubdelphi.com/foros/guiaestilo.php).

Yo haría:

function Tclasepropietario.Busqueda(const aFieldName, aValue: string): Boolean;
begin
with ADOTable1 do
begin
Filtered := False;
Filter := '(' + aFieldName + ' LIKE ' + QuotedStr('*' + aValue + '*') + ')';
Filtered := True;
Result := RecordCount > 0;
end;
end;


Ejemplo de llamada:

if Busqueda('CODIGO_TITULAR', '0006') then
...


Saludos. :)

nefore
16-06-2013, 02:32:13
Te agradezco la bienvenida, y por tu tiempo para responder. Antes de escribir este post he pegado un vistazo a la guia de estilos, si he rompido alguna norma hazmelo saber.
Te pido disculpas, pero recien estoy empezando en esto, asi que no entiendo muy bien. La constate aFieldName es necesaria que este asi? o sea yo estoy haciendo un alta de propietarios, y quiero usar este busca, para evitar un dni duplicado me explico? (los demas: codigo titular y nombre los usare para realizar una consulta). Segun lo que yo entiendo estas pasando una constante como parametro? y la propiedad(?) Filtered, primero tengo que desactivarla?

He intentando el codigo me pasaste pero, no me deja compilar, me dice incompatible types

ecfisa
16-06-2013, 03:44:47
Hola nefore.
Te agradezco la bienvenida, y por tu tiempo para responder. Antes de escribir este post he pegado un vistazo a la guia de estilos, si he rompido alguna norma hazmelo saber.
No, no has roto ninguna regla, es un recordatorio que siempre se les hace a los que publican su primer mensaje. :)

La constate aFieldName es necesaria que este asi?
El que los parámetros estén declarados como constantes es a fines de optimización, funcionara del mismo modo quitando el calificador. Y el sentido de enviar como argumento el nombre del campo es para evitar la evaluación del índice (opción) dentro de la función.
o sea yo estoy haciendo un alta de propietarios, y quiero usar este busca, para evitar un dni duplicado me explico?
Para ese caso es mas simple usar el método Locate:

begin
if ADOTable1.Locate('DNI', Edit1.Text,[]) then
begin
MessageBox(Handle,'Ya existe un propietario con ese DNI', '', MB_ICONERROR + MB_OK);
Exit;
end;
//... Continuar con el ingreso


He intentando el codigo me pasaste pero, no me deja compilar, me dice incompatible types
Ignoro que tipos estás enviando como argumentos a la función, sería bueno si pusieras la declaración de las variables y la parte del código en que realizas la llamada.
Fijate que los parámetros los declaré de tipo string, partiendo del supuesto que campos tales como APELLIDO_NOMBRES no seran de tipo Integer.

Saludos. :)

nefore
16-06-2013, 07:23:49
Hola nefore.

No, no has roto ninguna regla, es un recordatorio que siempre se les hace a los que publican su primer mensaje. :)


El que los parámetros estén declarados como constantes es a fines de optimización, funcionara del mismo modo quitando el calificador. Y el sentido de enviar como argumento el nombre del campo es para evitar la evaluación del índice (opción) dentro de la función.

Para ese caso es mas simple usar el método Locate:

begin
if ADOTable1.Locate('DNI', Edit1.Text,[]) then
begin
MessageBox(Handle,'Ya existe un propietario con ese DNI', '', MB_ICONERROR + MB_OK);
Exit;
end;
//... Continuar con el ingreso



Ignoro que tipos estás enviando como argumentos a la función, sería bueno si pusieras la declaración de las variables y la parte del código en que realizas la llamada.
Fijate que los parámetros los declaré de tipo string, partiendo del supuesto que campos tales como APELLIDO_NOMBRES no seran de tipo Integer.

Saludos. :)

Oh, vaya! muchas gracias el ADOTable.Locate ha funcionado! Lo malo es que he tenido que pasar el dni como string para que lo tome, dado que lo tenia como campo numerico en la BD, y aca paso un string del edit (segun tengo entendio).
Pues bien, me ha servido de mucho para la validacion, pero el problema es que aun asi necesito un metodo para buscar con ADOTable con un filtro o algo asi, porque por ejemplo cuando realize la consulta y pedir buscar por nombre y apellido (o por parte de este), utilizaria el Filtro y mostraria los resultados en un db grid.
Igualmente desde ya muchas gracias, te agradezco por la ayuda (ya me estaba volviendo loco). Un paso menos. :)

ecfisa
16-06-2013, 10:09:55
Hola.


Pues bien, me ha servido de mucho para la validacion, pero el problema es que aun asi necesito un metodo para buscar con ADOTable con un filtro o algo asi, porque por ejemplo cuando realize la consulta y pedir buscar por nombre y apellido (o por parte de este), utilizaria el Filtro y mostraria los resultados en un db grid.

Si se trata de campos alfanuméricos la función que te puse en el mensaje anterior funciona perfectamente. De tratarse de campos numéricos, tendrás que filtrar por >, <, = ,>=, <=.

Pero creo entender de tu comentario que no has podido implementar la función del mensaje #2 en tu código, por lo cuál te adjunto un demo funcionando para que puedas revisar con tranquilidad el por qué.

Crea una carpeta, descomprimí los fuentes allí y compila. (incluye dbdemos.mdb que trae Delphi)

Saludos. :)

nefore
17-06-2013, 20:55:28
Hola.


Si se trata de campos alfanuméricos la función que te puse en el mensaje anterior funciona perfectamente. De tratarse de campos numéricos, tendrás que filtrar por >, <, = ,>=, <=.

Pero creo entender de tu comentario que no has podido implementar la función del mensaje #2 en tu código, por lo cuál te adjunto un demo funcionando para que puedas revisar con tranquilidad el por qué.

Crea una carpeta, descomprimí los fuentes allí y compila. (incluye dbdemos.mdb que trae Delphi)

Saludos. :)

Hola muchas gracias por tomarte el tiempo para buscar el arhivo que me pasaste, lo he visto y De verdad agradezco tu paciencia y ayuda. Antes que nada, te pido disculpas me he expresado mal, tu codigo, como dices, no tiene ningun problema cuando es string (como nombre y apellido, y dni lo son), el problema es el campo codigo que es integer, probe colocar el AdoTable1 (que es que esta asociado con la tabla propietarios).Filter: 'DNI ='dato; pero me salta un error de "Parametros Incorrectos, fuera del intervalo permitido o en conflicto con otros'.
Me he fijado el archivo que me pasaste, pero justamente realiza la busqueda por name, capital o continent (campos string) y no por los otros campos numericos:

este es el codigo de la busqueda en el cual esta (entre comentarios) el codigo que me pasaste

function Tclasepropietario.busqueda(dato: string; opcion: Integer): Boolean;
var
ban: Boolean;

begin
ban:= False;
ADOTable1.Filtered := True;
case opcion of

1: begin
//ADOTable1.Filter:= Format(' = ',[CODIGO_TITULAR,dato]);
//if (ADOTable1.RecordCount > 0)
//then
//begin
// ban:= True;
//end
//else
//begin
// ban:= False;
//end;
if (ADOTable1.Locate('CODIGO_TITULAR',dato,[])=True)then
ban:=True;
end;
2: begin
if (ADOTable1.Locate('DNI',dato,[])=True)then
ban:=True;
end;
3: begin
ADOTable1.Filter:='APELLIDO_NOMBRES LIKE '''+dato+'*''';
if (ADOTable1.RecordCount > 0)
then
begin
ban:=True;
end
else;
begin
ban:=False;
end;
end;
end;
busqueda:= ban;
end;

He intentado implementar el codigo #2 pero como te mencione, me sigue saltando el error de "Parametros Incorrectos, Fuera del Intervalo permitido o en conflicto con otros". Lo probe con el ADOTABLE.locate (que me mencionaste despues y ha funcionado), pero cuando muestro el ADO en un DB Grid, no me filtra y me muestra solamente esa persona con el dni o con el codigo que haya escrito; solamente apunta a donde se encuentra ese registro (supongo que es por la misma funcion locate, que no es un filtro en realidad, solo busca el valor y se para alli), no es asi con el nombre el cual efectivamente me filtra los resultados.

En el siguiente codigo, ocurre el mismo error:

procedure TForm7.FormActivate(Sender: TObject);
begin
propietario:= Tclasepropietario.Create;
propietario.conectaBD;
propietario.ConectaTabla(1);
ADOTable1.Filtered:= True;
ADOTable1.Filter:='BORRADO LIKE FALSO';
DataSource1.DataSet := ADOTable1;
end;

En donde Form7 es el formulario donde realizo la modificacion de propietarios, lo que intento hacer es: en un DB Grid que esta en dicho formulario, mostrar solo aquellos cuyo campo BORRADO sea FALSO (es decir mostrar aquellos propietarios que estan activos), y a partir de ahi buscar por codigo, dni o "apellido y nombre".
Pero como te digo me salta el error mencionado.

ecfisa
17-06-2013, 22:29:18
Hola.

el problema es el campo codigo que es integer, probe colocar el AdoTable1 (que es que esta asociado con la tabla propietarios).Filter: 'DNI ='dato; pero me salta un error de "Parametros Incorrectos, fuera del intervalo permitido o en conflicto con otros'.

Como te comenté en el mensaje #6:

Si se trata de campos alfanuméricos la función que te puse en el mensaje anterior funciona perfectamente. De tratarse de campos numéricos, tendrás que filtrar por >, <, = ,>=, <=.



En el siguiente codigo, ocurre el mismo error:


procedure TForm7.FormActivate(Sender: TObject);
begin
propietario:= Tclasepropietario.Create;
propietario.conectaBD;
propietario.ConectaTabla(1);
ADOTable1.Filtered:= True;
ADOTable1.Filter:='BORRADO LIKE FALSO';
DataSource1.DataSet := ADOTable1;
end;


En el caso de ser un campo lógico también se tiene que accionar de forma diferente:

procedure TForm1.FilterLogical(const FName: string; const Value: Boolean);
const
COND : array[Boolean] of string =('''False''','''True''');
begin
with ADOTable1 do
begin
Filtered := False;
Filter := Format('%s= %s',[FName, COND[Value]]);
Filtered := True;
end;
end;

// LLamada:
...
begin
FilterLogical('Borrado', True);
...

Creo que debes profundizar un poco mas sobre el tema de los filtros.

En el FTP de Club Delphi se encuentra un libro de descarga gratuita en el que se explica cláramente: La cara oculta de Delphi 4 (http://terawiki.clubdelphi.com/Delphi/Manuales/?download=La_Cara_Oculta_De_Delphi_4_pdf_.zip) (Capítulo 20).

Saludos. :)