PDA

Ver la Versión Completa : DBGrid


Puberta
06-12-2007, 01:18:40
Tengo problemas con un DBGrid.

Lo que intento hacer es que mediante un DBGrid, el cual esta relacionado a un Query inserto nuevos registros en una tabla, hasta aquí todo esta bien, pero cuando intenté realizar pruebas me di cuenta que el dbgrid permite agregar cuantos registros deseé.....:eek:

Tengo de dos opciones:

1. Permitir que el usuario solo agregue un registro, pero entonces ¿cómo bloqueo el DBgrid para que solo inserte un registro?.

2. Permitir que el usuario ingrese cuantos registros deseé, pero entonces como es que detectaría que se a presionado la tecla de dirección (Down), porque al hacer esto le tengo que mandar 2 valores que el usuario desconoce y no pueden ser nulos.

Espero me halla dado a entender y que alguien me pueda ayudar.:o

jachguate
06-12-2007, 01:45:19
Tal como lo veo, estas enfocando mal la escopeta.

El asunto no tiene que ver con el dbGrid, sino con el DataSet asociado. Te darás cuenta si ves los eventos del query (y su ayuda): OnNewRecord, BeforeInsert, AfterInsert.

Hasta luego.

;)

Puberta
06-12-2007, 02:42:53
Perdon Jachguate, pero no me sale.

Lo que pasa es que si lo hago en OnNewRecord me pone el mismo valor en cada nuevo registro y no debe ser así, cada registro debe tener sus propios valores.

Intenté en el evento OnKeyPress, es decir que me detectará si presionaba la tecla de dirección(down) me apareciera una ventana con un mensaje X, pero no me queda...la pregunta del millon es ¿Delphi detectá el código ascci de las teclas de dirección?, porque de ser afirmativa la respuesta indica que no escribi el código correcto.

jachguate
06-12-2007, 02:51:19
Perdon Jachguate, pero no me sale.

Lo que pasa es que si lo hago en OnNewRecord me pone el mismo valor en cada nuevo registro y no debe ser así, cada registro debe tener sus propios valores.

Eso es fácil, por ejemplo:


procedure TForm1.Query1NewRecord(parametros);
begin
Query1CAMPO1.AsInteger := random(100);
end;


Lo que quiero decir con esto, es que te pone el mismo valor en cada registro porque vos estas programandolo de ese modo... si queres un valor diferente en cada registro, pues es tu tarea que así suceda... al final de cuentas, vos sos el programador... ¿no?

Hasta luego.

;)

Lepe
06-12-2007, 19:21:47
Hay 2 temas distintos.

Para controlar los valores "por defecto", ya lo ha dicho el compañero jachguate.

Para controlar el número de inserciones:

Podrías utilizar una variable global de la ventana usada a modo de contador.
En el evento AfterPost, incrementas esa variable.
En el evento OnNewRecord, miras el valor de esa variable, y si es mayor a uno, cancelas la edición:

procedure TForm1.DAtasetNewRecord(...);
begin
If (Inserciones > 0) // tu contador numérico
and not (PermitirMasDeUna) // en algún sitio debes controlar la
// permisividad de insertar más de uno o no, aquí lo tienes en cuenta
then
begin
ShowMessage('No se permite más de una inserción');
Dataset.Cancel; // abortamos la creación de este registro
sysutils.Abort; // salimos de este procedimiento.
end;
// si se permite más de una inserción, o es la primera:
// - dar valores a los campos que sean a continuación


end;


Espero haya entendido tu pregunta. Saludos

jachguate
08-12-2007, 00:39:19
En el evento OnNewRecord, miras el valor de esa variable, y si es mayor a uno, cancelas la edición:

En realidad esa verificación, yo la haría en el evento BeforeInsert.

Otra cosa... si el comportamiento por defecto cuando ocurre una excepción es mostrar un mensaje... ¿por qué no simplemente elevar una excepción?


if (FInserciones > 0) then
raise Exception.Create('Error: solamente se le permite insertar un registro!');


Comento también que en el evento AfterPost ya no hay forma de saber si se estaba insertando o editando un registro... a menos que se conserve ese valor en una variable. Lo comento porque el mencionado evento se dispara tanto si se insertaba como si se modificaba un registro.

Hasta luego.

;)

Puberta
09-12-2007, 02:37:21
Tengo el evento onNewRecord, en este hago una consulta a la tabla y traigo el ultimo valor de este, por lo que pongo como clave principal el resultado del query mas 1

QModelosId_Modelo.value := Query.Field[0].value + 1;
QModelosId_Marca.value := DBMarca.Text;

pero el problema es que al poner el dataset en modo de inserción si me manda los valores
pero sólo al primer registro y si el usuario presionaba el tabulador o la tecla de dirección (down) me agregaba más lineas obvimente con los campos vacios, por lo que opte por bloquear el DBGrid....intenté en el evento onKeyDown y si funciona pero me bloquea el dataset y solo me deja agregar un registro.

IF (key in [VK_DOWN, VK_TAB, VK_UP]) then key := 0;

No tengo idea porque cada vez que agrego algo al dataset afecta todo mi código que anteriormente estaba bien, es decir hacia lo que requería que hiciera.

Caral
09-12-2007, 02:53:24
Hola
No entiendo.
Si lo que se quiere es que el usuario coloque unos datos, por ejemplo en un edit y este, esta vacío, por que no estipular un simple mensaje diciendo que este tiene que contener datos?, lo mismo se puede hacer con cualquier otro componente, para que complicarse con la base de datos, datasets u otros?.
No se.
Saludos

Puberta
10-12-2007, 18:46:15
ok. mire tengo un formulario que muestra todas las marcas de los automoviles que hay en la empresa, este formulario también contiene un DBgrid con todos los modelos de esa marca, es decir... marca Chevrolet y el DBgrid contiene los modelos Corvette, Malibu, Astra, Chevy, etc.

Mi intención es que el usuario escriba directamente sobre el DBGrid, si presiona el boton 'Nuevo' entonces ingresa una linea con el ID del modelo y el ID de la marca, el usuario sólo tiene que escribir el modelo pero, si el usuario presionaba el Tabulador o la Tecla de Dirección se agregaba una lina más pero ya con todos los campos vacios.

El problema es que me permite agregar un registro solo una vez porque después me muestra el error 'El dataset no esta en modo Edit o Insert'.

Caral
10-12-2007, 19:00:13
Hola
Bueno no se la razón, pero me parece mas cómodo usar un edit para pasar o actualizar los datos.:rolleyes:
De todos modos, viendo tu explicación, me parece mas correcta la explicación de jachguate , por el uso del dataset o del componente de enlace, puede ser el table o el query, da igual.
Algo asi:
If (Table.State = dsEdit) or (Table.State = dsInsert) then
begin
Por otro lado, si te da error después de actualizar, osea que solo te permite una actualización, es por que o cierras la tabla o la sentencia esta duplicada o no la vuelves a colocar en edición.
Revisa el código, si es posible mejor lo pones por aqui, para verlo.
Saludos

jachguate
11-12-2007, 05:58:17
Hola

La comprobación podes abreviarla así:


if Table1.State in dsEditModes then
begin
..


Hasta luego.

;)

Puberta
11-12-2007, 21:54:25
No lo hago con un edit porque simplemente me pidieron que todo se manejara desde un DBgrid, estoy de acuerdo que todo sería más sencillo, pero no me queda otro remedio.

Es muy tonto, lo que hacia es que cuando editaba o agregaba un registro cambiaba los estados de las columnas (ID_MODELO e ID_MARCA) del DBGrid en modo de solo lectura:

FPMarcas.DBGrid.Fields[0].ReadOnly := True;
FPMarcas.DBGrid.Fields[2].ReadOnly := True;

y cuando guardaba los cambios agregaba la siguiente linea, no sé en que afecte
FPMarcas.DBGrid.ReadOnly.True;

Sinceramente no encontré como corregir todo esto, así que simplemente agregue al evento OnKeyDown

IF (key in [VK_DOWN, VK_TAB, VK_UP, VK_LEFT, VK_RIGHT]) Then key := 0;

para que el usuario no tenga la posibilidad de moverse entre columnas asi como evitar las dos primeras lineas que eran las que que generaban el error.

Alguién me puede decir que hacia mal?