PDA

Ver la Versión Completa : Desproteger DBGrid en ejecución


aguml
20-02-2017, 15:49:15
Hola amigos, estoy trasteando un poco con las bases de datos y me encuentro con el siguiente problema. Tengo un DBGrid el cual de inicio se selecciona toda la fila, no tiene habilitada la opcion de seleccionar varias filas, no se puede editar el valor de las celdas y tiene la propiedad de ReadOnly a true. Quiero revertir todo eso para poder hacerlo al ingresar una contraseña y de momento estoy con esta prueba:
void __fastcall TForm2::ButtonDesbloquearClick(TObject *Sender)
{
AnsiString pass = "1234567890";
AnsiString cadena = InputBox("Desbloqueo de lista","Introduce la contraseña:","");
if(pass == cadena)
{
DBGrid1->Options = TDBGridOptions(DBGrid1->Options) >> dgRowSelect >> dgEditing;
DBGrid1->ReadOnly = false;
DBNavigator1->Enabled = true;
}else{
ShowMessage("Contraseña incorrecta. No se ha desbloqueado la lista.");
}
}
Me encuentro con que se deshabilita la opcion dgRowSelect pero parece que la opcion dgEditing no porque no me deja editar nada. ¿Pueden ayudarme?

ecfisa
20-02-2017, 16:14:57
Hola.


...
{
DBGrid1->ReadOnly = false;
DBGrid1->Options = DBGrid1->Options +
TDBGridOptions() >> dgRowSelect << dgEditing << dgMultiSelect ;
// O también:
// DBGrid1->Options = TDBGridOptions(DBGrid1->Options) >> dgRowSelect
// << dgEditing << dgMultiSelect ;
}


Saludos :)

aguml
20-02-2017, 16:44:21
Gracias lo pruebo cuando llegue y te digo que tal. Por cierto no quiero que se pueda hacer multiseleccion nunca así que lo que haces al final supongo que puedo quitarlo.
Otro problema que tenia es que uso en el evento onclick del dbgrid:
EditNombre->Text=DBGrid1->DataSource->DataSet->FieldValue["Nombre"];
Una vez que podía editar si creo un nuevo registro con el botón + del DBNavigator aparecía la línea y si la selecciono me sale un error donde dice que no se puede convertir una variable de tipo null a string. Lo he "solucionado" usando un try catch pero me gustaría hacerlo correctamente y no se como seria. ¿podrías ayudarme con eso también?

ecfisa
20-02-2017, 17:09:18
Por cierto no quiero que se pueda hacer multiseleccion nunca así que lo que haces al final supongo que puedo quitarlo.
Si, así es.


... si creo un nuevo registro con el botón + del DBNavigator aparecía la línea y si la selecciono me sale un error donde dice que no se puede convertir una variable de tipo null a string. Lo he "solucionado" usando un try catch pero me gustaría hacerlo correctamente y no se como seria. ¿podrías ayudarme con eso también?
Agrega el mismo código al evento BeforeAction:

void __fastcall TForm1::DBNavigator1BeforeAction(TObject *Sender,
TNavigateBtn Button)
{
if ( Button == nbInsert ) // ¿ inserta ?
{
DBGrid1->ReadOnly = false;
DBGrid1->Options = TDBGridOptions(DBGrid1->Options) >> dgRowSelect
<< dgEditing;
}
}


Saludos :)

aguml
20-02-2017, 18:18:34
Creo que no me he explicado bien, el DBNavigator por defecto esta deshabilitado y al desbloquear todo también habilito a este. Si le doy al + pero no escribo nada y cambio de columna en la misma fila y luego vuelvo a la celda de columna Nombre de esa fila, en ese momento es cuando me tira la excepción.

ecfisa
20-02-2017, 18:45:08
Hola.
Creo que no me he explicado bien, el DBNavigator por defecto esta deshabilitado y al desbloquear todo también habilito a este. Si le doy al + pero no escribo nada y cambio de columna en la misma fila y luego vuelvo a la celda de columna Nombre de esa fila, en ese momento es cuando me tira la excepción.
Reproduje la situación que comentas arriba y no obtengo error.

Tal vez descubriríamos algo si nos publicas los eventos y código donde desactivas y donde activas las acciones.

Saludos :)

aguml
20-02-2017, 22:01:07
Te pongo el enlace para poder descargar el proyecto: https://mega.nz/#!Uo0y2ZbT!WT7qUG6OQrnVD_GoxhTZP0YSd6YnfOoLYEFu6bTkt4E
Es solo una prueba para experimentar con sqlite y zeosdb ya que no se casi nada de ellos y queria ver su uso un poco haciendo una especie de base de datos de clientes donde se van insertando las consumisiones.

ecfisa
21-02-2017, 13:19:21
Hola.

No pude compilar y/o ejecutar tu código por que me faltan componentes, pero cuando usas la propiedad vectorial FieldValues en el evento OnCellClick deberías revisar que el valor del campo actual no sea nulo:


void __fastcall TForm2::DBGrid1CellClick( TColumn *Column )
{
TDBGrid *GR = static_cast<TDBGrid*>( DBGrid1 );
TDataSet *DS = static_cast<TDataSet*> ( DBGrid1->DataSource->DataSet );

EditNombre->Text = VarToStrDef(DS->FieldValues["Name"], ""); // <-
EditPrecio->Text = VarToStrDef(DS->FieldValues["Area"], "0"); // <-

if ( EditUnidades->Text != "" && EditPrecio->Text != "" )
EditTotal->Text = EditUnidades->Text.ToDouble() *
EditPrecio->Text.ToDouble();
}

Por mi parte prefiero no usar la propiedad FieldValues ya que, debido a que usa Variants, es la opción mas lenta.

Mas rápido es:

...
void __fastcall TForm2::DBGrid1CellClick( TColumn *Column )
{
TDBGrid *GR = static_cast<TDBGrid*>( DBGrid1 );
TDataSet *DS = static_cast<TDataSet*>( DBGrid1->DataSource->DataSet );

EditNombre->Text = DS->FieldByName("Nombre")->AsString;
EditPrecio->Text = DS->FieldByName("Precio")->AsString;

if ( EditUnidades->Text != "" && EditPrecio->Text != "" )
EditTotal->Text = EditUnidades->Text.ToDouble() *
EditPrecio->Text.ToDouble();
}
...

Por último la opción mas eficiente es crear los campos persistentes del TDatSet y citarlos por su nombre.

Saludos :)

aguml
21-02-2017, 17:16:21
Que es eso de los campos persistentes?

ecfisa
21-02-2017, 20:24:45
Hola.
Que es eso de los campos persistentes?
Para crearlos en tiempo de diseño básicamente los pasos son:

Doble click sobre el componente DataSet (se abre ventana)
Click botón derecho sobre la nueva ventana
Click botón izquierdo sobre el ítem: Add all fields

Vas a encontrar una explicación detallada sobre el tema en el capítulo "Acceso a campos" de La cara oculta de Delphi 4 (http://terawiki.clubdelphi.com/Delphi/Manuales/?download=La_Cara_Oculta_De_Delphi_4_pdf_.zip).

Saludos :)