Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Procedimiento correcto para usar un memtable en grid (https://www.clubdelphi.com/foros/showthread.php?t=95101)

NeWsP 03-03-2021 16:52:06

Procedimiento correcto para usar un memtable en grid
 
Buenas tardes,

Estoy desarrollando una aplicación sencilla con un memtable y un query, es decir, hago una consulta a la base de datos con el query, recorro el query, y según la información me genero un memtable con toda la información que necesito para mostrarlo en un grid.

Si tengo que actualizar algún dato en la base de datos, ataco directamente a la base de datos con otro query, pero para poder actualizar los datos del grid, vuelvo a recorrer el primer query y actualizado la memtable y automáticamente el grid, pero claro, de esta forma pierdo la linea en la que estaba.

Con un LOCATE puedo volver a encontrarla, pero realmente se me desplazan las scrollbars y se nota bastante feo...

Alguna sugerencia de como poder evitar esto?

Muchas Gracias!

movorack 03-03-2021 18:09:30

Con DisableControls y EnableControls

Código Delphi [-]
miDataset.DisableControls;
try
  //Operaciones que mueven el dataset
finally
  miDataset.EnableControls;
end;

NeWsP 04-03-2021 11:34:24

Muchas gracias,

He probado y por un momento funcionaba y ahora otra vez no me funciona sin tocar nada :S

Es raro, porque si el grid esta en la parte inferior, parece que funciona bien.

Si el grid esta en otra posición, lo mueve hasta el centro de la pantalla.

Pongo el codigo que estoy utilizando: (seguro que es un desastre de codigo...)

Código Delphi [-]
procedure TTMSForm1.ActualizarPedidos(Operacion: Integer);
var
  lineasPedido: Integer;
  lineasAsignadas: Integer;
  estado: Integer;
  plazo: string;

begin

  MemPedidos.DisableControls;
  try
   TMSForm1.MemPedidos.EmptyDataSet;

    DBAdvGrid1.DataSource := nil;

    FDQuery1.SQL.Clear;
    With FDQuery1 do
    begin
      SQL.Clear;
      SQL.Add('SELECT FECPCL,CODPCL,CNOPCL FROM F_PCL WHERE ESTPCL<>2 ORDER BY CODPCL');
      open;
    end;

    TMSForm1.FDQuery1.First;
    while not TMSForm1.FDQuery1.eof do
    begin

      QueryOperaciones.SQL.Clear;
      QueryOperaciones.SQL.Add
        ('SELECT DISTINCT posicion FROM Pedidos WHERE pedido=:pedido');
      QueryOperaciones.ParamByName('pedido').Value :=
        FDQuery1.FieldByName('CODPCL').Value;
      QueryOperaciones.open();

      lineasAsignadas := QueryOperaciones.RecordCount;

      QueryOperaciones.SQL.Clear;
      QueryOperaciones.SQL.Add('SELECT plazo FROM plazos WHERE pedido=:pedido');
      QueryOperaciones.ParamByName('pedido').Value :=
        FDQuery1.FieldByName('CODPCL').Value;
      QueryOperaciones.open();

      if QueryOperaciones.RecordCount > 0 then
      begin
        plazo := QueryOperaciones.FieldByName('plazo').Value;
      end
      else
      begin
        plazo := ' --- '
      end;

      QueryFactu.SQL.Clear;
      QueryFactu.SQL.Add('SELECT POSLPC FROM F_LPC WHERE CODLPC=:pedido');
      QueryFactu.ParamByName('pedido').Value :=
        FDQuery1.FieldByName('CODPCL').Value;
      QueryFactu.open();

      lineasPedido := QueryFactu.RecordCount;

      if lineasPedido = lineasAsignadas then
      begin
        estado := 1;
      end;

      if (lineasPedido <> lineasAsignadas) AND (lineasAsignadas > 0) then
      begin
        estado := 2;
      end;

      if lineasAsignadas = 0 then
      begin
        estado := 0;
      end;

      with TMSForm1.MemPedidos do
      begin
        Append;
        Fields[0].AsInteger := estado;
        Fields[1].AsDateTime := TMSForm1.FDQuery1.FieldByName('FECPCL').Value;
        Fields[2].AsInteger := TMSForm1.FDQuery1.FieldByName('CODPCL').Value;
        Fields[3].AsString := TMSForm1.FDQuery1.FieldByName('CNOPCL').Value;
        Fields[4].AsString := plazo;
        Post;
      end;
      TMSForm1.FDQuery1.Next;
    end;
    DBAdvGrid1.Visible := True;

    DBAdvGrid1.DataSource := DataPedidos;

  finally
      MemPedidos.Locate('Pedido', pedidoActual, []);
      MemPedidos.EnableControls;

  end;
end;

Y así es como llamo al procedimiento, cuando he añadido un plazo nuevo:

Código Delphi [-]
if main.accion_plazo = 0 then
  begin
    FDQuery1.SQL.Clear;
    FDQuery1.SQL.Add
      ('INSERT INTO plazos (pedido,plazo,estado,año) VALUES(:pedido,:plazo,:estado,:ano)');
    FDQuery1.ParamByName('pedido').Value := main.TMSForm1.MemPedidos.FieldByName
      ('pedido').Value;
    FDQuery1.ParamByName('plazo').Value :=
      datetostr(AdvSmoothCalendar1.SelectedDate);
    FDQuery1.ParamByName('estado').Value := 0;
      FDQuery1.ParamByName('ano').Value := AdvSmoothCalendar1.Year;
    FDQuery1.ExecSQL;
  end
  else
  begin
     FDQuery1.SQL.Clear;
    FDQuery1.SQL.Add
      ('UPDATE plazos SET plazo=:plazo WHERE pedido=:pedido AND año=:ano');
      FDQuery1.ParamByName('plazo').Value:=  datetostr(ADVSmoothCalendar1.SelectedDate);
    FDQuery1.ParamByName('pedido').Value := main.TMSForm1.MemPedidos.FieldByName
      ('pedido').Value;
    FDQuery1.ParamByName('ano').Value := AdvSmoothCalendar1.Year;
    FDQuery1.ExecSQL;
  end;

  plazo.Form1.Close;

     main.TMSForm1.ActualizarPedidos(0);

Entonces lo que hace es que si estoy en la parte inferior del grid parece que es correcto, pero si estoy en otro sitio me centra la fila seleccionada.

Alguna sugerencia T_T?

kuan-yiu 04-03-2021 12:22:09

'Locate' funciona así. Posiciona la linea buscada en medio del grid, salvo que el número total de lineas en pantalla no se lo permita (o que sea la primera o la última). Por lo menos en las versiones de Delphi con las que he trabajado.

NeWsP 04-03-2021 12:58:53

Gracias por contestar,

He probado con:

Código Delphi [-]
  MemPedidos.SetKey;
    MemPedidos.FieldByName('Pedido').Value := pedidoactual;
    MemPedidos.GotoKey;

Pero me hace lo mismo.

Alguna sugerencia para posicionarme en la fila correcta sin que se mueva? T_T

mamcx 04-03-2021 16:11:00

Analizando tu código no hay como eso funcione. Lo que describes NO ES lo que haces. Tu NO "actualizas la memtable".

Como quieres que "recuerde" si nuleas la referencia, la limpias del todo y luego la asignas? Totalmente estas haciendo UN NUEVO OBJETO.

Antes gracia que medio ande :)

NeWsP 04-03-2021 16:36:15

Entonces cual seria el proceso para actualizar la memtable? realmente tengo que volver a recorrer el query para poder actualizar según los datos cambiados

Que propones entonces? actualizo con un query la base de datos y por otro lado actualizado la memtable? o actualizar el memtable y luego volcar a la base de datos?

Por eso preguntaba, como puedes ver en el titulo del post, cual es el procedimiento correcto.

Cita:

, vuelvo a recorrer el primer query y actualizado la memtable y automáticamente el grid,
creo que puse que recorría el query y así actualizaba la memtable, no propiamente he dicho hacer un update, sino volver a cargar los datos, pero vamos, se puede entender de muchas maneras.

Gracias por contestar

mamcx 04-03-2021 16:45:09

En terminos simples, debes hacer un MERGE/UPDATE de los datos viejos con los nuevos. Jalas los datos. Recorres el memtable y usando la llave primaria de los datos comparas con lo que tienes y actualizas los campos, de ser necesario.

NeWsP 04-03-2021 16:54:10

Gracias por contestar,

Ahora ya me has matado...

En principio por lo que entiendo (que no es mucho) al insertar un plazo nuevo en la base de datos, en vez de hacer el empty, tengo que recorrer el query otra vez pero sin hacer

Código Delphi [-]
 with TMSForm1.MemPedidos do
      begin
        Append;
        Fields[0].AsInteger := estado;
        Fields[1].AsDateTime := TMSForm1.FDQuery1.FieldByName('FECPCL').Value;
        Fields[2].AsInteger := TMSForm1.FDQuery1.FieldByName('CODPCL').Value;
        Fields[3].AsString := TMSForm1.FDQuery1.FieldByName('CNOPCL').Value;
        Fields[4].AsString := plazo;
        Post;
      end;

y en lugar de eso, ir comparando uno a uno recorriendo la memtable, y en el caso que el valor sea distinto actualizarlo con un

Código Delphi [-]
 with TMSForm1.MemPedidos do
      begin
        Edit;
        Fields[0].AsInteger := estado;
        Fields[1].AsDateTime := TMSForm1.FDQuery1.FieldByName('FECPCL').Value;
        Fields[2].AsInteger := TMSForm1.FDQuery1.FieldByName('CODPCL').Value;
        Fields[3].AsString := TMSForm1.FDQuery1.FieldByName('CNOPCL').Value;
        Fields[4].AsString := plazo;
        Post;
      end;

Es la primera vez que uso memtables, he mirado algo de información pero ando bastante perdido, por eso preguntaba como era el proceso.

Gracias otra vez

Edit: Aunque pensando fríamente, cuando introduzco un plazo, realmente ya se que fila de la tabla voy a modificar, podría hacer el edit directamente sobre esa fila, sin tener que hacer el query de recorrer, y unicamente hacer el query de actualizar la base de datos y asi me ahorro toda la comparación (que en otros sitios si que tendria que hacer... T_T)

Voy bien por ahi?


La franja horaria es GMT +2. Ahora son las 22:04:05.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi