Detectar operacion en in grid datatable

estimados,
tengo una grilla que se llena con un datable, y trabaja con eventos, es decir permite añadar y eliminar linea cuando se presiona el click derecho sobre una fila.
lo que quieres que esto también afecte a la db, es decir a mi UDT, ya que puedo eliminar pero al momento de abrir de nuevo la grilla este dato sigue alli, lo mismo para agregar y actualizar.
para actualizar quiero que si alguien modifica una celda esta se pueda actualizar igual.

muchas gracias-
saludos,

Hola! :grin:

Primero, debes definir en que momento vas a hacer la actualizacion de datos:

  1. Si se hace cada vez que el usuario actualiza una celda.
  2. Si se hace solo cuando se presione el boton “Actualizar”, tal como lo hace el estandar de SAP.

En ambos casos hay que saber cuando se modifica el contenido de una celda, bien sea para disparar el evento de actualizacion o para cambiar el boton de “Crear” u “OK” a “Modificar” (Si usas la misma logica de SAP en sus pantallas).

Para esto deberas tener una propiedad, campo o variable en el form que guarde el valor de una celda al hacer focus y verificar que al momento de salir de esta, el valor inicial sea distinto (eventos GotFocusAfter y ValidateBefore), con esto se determina cuando se habilita la actualizacion.

Por Ejemplo, para una columan de tipo String defino este campo en el form:

Private Col_StringDatoAnterior As String

Luego usando este campo cada vez que se hace foco a una celda:

Private Sub Grid1_GotFocusAfter(sboObject As System.Object, pVal As SAPbouiCOM.SBOItemEventArg) Handles Grid1.GotFocusAfter
            If (pVal.ColUID = "Mi Columna String1" or pVal.ColUID = "Mi Columna String2") Then
                Dim dtRow As Integer = Grid1.GetDataTableRowIndex(pVal.Row)
                Col_DatAnt = Grid1.DataTable.GetValue(pVal.ColUID, dtRow)  'Asigno el valor inicial de la celda'
            End If
        End Sub

Luego al validar la celda, verifico si el valor de esta a cambiado:

 Private Sub Grid1_ValidateBefore(sboObject As System.Object, pVal As SAPbouiCOM.SBOItemEventArg, ByRef BubbleEvent As System.Boolean) Handles Grid1.ValidateBefore
            Funciones.FreezeForm(oForm, True)
            If Grid1.DataTable.GetValue(pVal.ColUID, pVal.Row) <> Col_DatAnt Then 
                 ActualizaUDT(pVal.Row, pVal.ColUID) 'En Caso de que se Actualice Cada Vez que cambie una celda'
                 Button1.Caption = "Actualizar" 'En Caso de que se actualice por este boton'
            EndIf
            Funciones.FreezeForm(oForm, False)
        End Sub

Una vez que determinas cuando e que momento actualizar, deberas usar el objeto UserTables para Insertar:

oUserTable = oCompany.UserTables.Item("Mi_Tabla_UDT");
int iRet = 0;

try
{
	//oCompany.StartTransaction();
	oUserTable.Code = code;
        oUserTable.Name = name;
        oUserTable.UserFields.Fields.Item("U_Field1").Value = Valor1;
        oUserTable.UserFields.Fields.Item("U_Field2").Value = Valor2;
	iRet = oUserTable.Add();
}
catch (Exception ex)
            {
                return ex.Message;
            }

O Usar GetByKey para Actualizar:

oUserTable = oCompany.UserTables.Item("Mi_Tabla_UDT");
int iRet = 0;

try
{
	//oCompany.StartTransaction();
	oUserTable.GetByKey(Code);
        oUserTable.Name = name;
        oUserTable.UserFields.Fields.Item("U_Field1").Value = Valor1;
        oUserTable.UserFields.Fields.Item("U_Field2").Value = Valor2;
	iRet = oUserTable.Update();
}
catch (Exception ex)
            {
                return ex.Message;
            }

Saludos ! :vulcan_salute:

4 Me gusta

estimado, esto se haría en el mismo form o en program.cs ?
muchas gracias!

Esto se hace en el Form.

1 me gusta
  oUserTable.Code = Code;
                oUserTable.Name = name;
                oUserTable.UserFields.Fields.Item("U_Field1").Value = Valor1;
                oUserTable.UserFields.Fields.Item("U_Field2").Value = Valor2;

esto lo estoy poniendo en el boton, el temino valor 1 y 2, cuando se los doy? ya que estoy agregando una linea o modificandola, esos valors deberian venir de los campos de la grilla no?


    Funciones.FreezeForm(oForm, true);
            if (Grid2.DataTable.GetValue(pVal.ColUID, pVal.Row) != Col_StringDatoAnterior)
            {
                ActualizaUDT(pVal.Row, pVal.ColUID);
                Button0.Caption = "Actualizar";


                Funciones.FreezeForm(oForm, false);

y aca de donde se obtienes la funciones

muchas gracias!

Hola !:upside_down_face:

SI estas colocando ese codigo en el boton, asumo que estas haciendo el proceso de acuerdo al standar de SAP, es decir la informacion solo se actualiza cuando el usuario presiona el boton “Actualizar”.

Si es el caso, los valores dados en el ejemplo los deberas tomar desde el Grid, recorriendolo linea por linea y verificando si esta existe en la BD (GetByKey()), de ser asi se modifica, caso contrario se inserta el registro.

Las funcion ActualizaUDT() es un ejemplo solo si vas a modificar/insertar una linea al momento de dispararse el evento, y es el mismo codigo DIAPI con UserTables, solo que debe realizarse sobre una unica linea (La que esta activa y modificada). La funcion “Funciones.FreezeForm(oForm, True)” es lo mismo que decir oForm.Freeze(True).

Saludos.

2 Me gusta

muy bien modifique lo que dijiste y quedaria algo asi:

 private String Col_StringDatoAnterior ;

        private void Grid2_GotFocusAfter(System.Object sboObject, SAPbouiCOM.SBOItemEventArg pVal) {
            if ((pVal.ColUID == "U_CodigoEDC" || pVal.ColUID == "U_NombreEDC" || pVal.ColUID == "U_ProyectoEDC"))
            {
                int dtRow = Grid2.GetDataTableRowIndex(pVal.Row);
             //    Grid2.DataTable.Columns.Item("U_CodigoEDC").Cells.Item(dtRow).Value = "YOUR NEW VALUE";
                SAPbouiCOM.StaticText Col_StringDatoAnterior = (SAPbouiCOM.StaticText)Grid2.DataTable.GetValue(pVal.ColUID, dtRow); //Asigno el valor inicial de la celda
 }
        }
        private void Grid2_ValidateBefore(System.Object sboObject, SAPbouiCOM.SBOItemEventArg pVal, ref System.Boolean BubbleEvent) {
            oForm.Freeze(true);
            if (Grid2.DataTable.GetValue(pVal.ColUID, pVal.Row) != Col_StringDatoAnterior)
            {
              
                Button0.Caption = "Actualizar";


             oForm.Freeze(false);
            }
        }

despues de esto tendria que llamar a los metodos en el OnCustomInitialize()?
y despues hacer agregar el codigo al boton , donde se obtienen los datos con GetByKey?
estoy en lo correcto?
muchas gracias Gabriel, perdon si soy algo lento pero quiero entender ya que me he perdido un poco con el grid, con botons y edittext era mas facil, muchas gracias

1 - No estas asignando ningun valor a la variable private String Col_StringDatoAnterior en el evento Grid2_GotFocusAfter, deberia ser asi:

private void Grid2_GotFocusAfter(System.Object sboObject, SAPbouiCOM.SBOItemEventArg pVal) {
            if ((pVal.ColUID == "U_CodigoEDC" || pVal.ColUID == "U_NombreEDC" || pVal.ColUID == "U_ProyectoEDC"))
            {
                int dtRow = Grid2.GetDataTableRowIndex(pVal.Row);
                Col_StringDatoAnterior = Grid2.DataTable.GetValue(pVal.ColUID, dtRow).ToString(); //Asigno el valor inicial de la celda
               }
        }

Tecnicamente estos no son Metodos, son Eventos, por lo tanto debes asignarlos al grid en su correspondiente ventana para que se ejecuten al dispararse la accion correspondiente, por lo tanto no deben ser llamados explicitamente:

Respeto al GetByKey(Code), deberas en el Query que usas para llenar el DataTable del grid, traer los campos Code y Name de la UDT (Estos los puedes ocultar en el grid), con el campo Code puedes verificar si el registro existe (Al menos que la tabla UDT sea de tipo “Filas de Datos Maestros o Documento”, en ese caso cambian ciertas cosas).

muy bien, voy entendiendo mas,
este es mi query:

   select t0.Code,t0.Name,t0.U_CodigoEDC AS "Código" ,t0.U_NombreEDC as "Nombre",t0.U_ProyectoEDC as "Proyecto",t1.U_NombrePyto as [Nombre Proyecto] from [@EDICIONESCOL] as t0   left join [@PROYECTOSCOSTE] as t1 on t0.U_ProyectoEDC = (CAST (t1.U_CentroPyto AS VARCHAR) + '' + CAST (t1.U_DeptoPyto AS VARCHAR) + '' + CAST (t1.U_CodigoPyto AS VARCHAR)) 

le agregue el code y name, entonces con esto hare en el boton un getcode,
lo otro ya habilitad el Grid2_GotFocusAfte


lo malo que cuando intento llamar al otro Grid2_ValidateBefore me da un error de sobrecarga, como se soluciona para que no ocurra?

lo otro el boton lo manejare con

  SAPbouiCOM.Form oForm = oApp.Forms.ActiveForm;
            switch (oForm.Mode)
            {
                case SAPbouiCOM.BoFormMode.fm_ADD_MODE:

asi paea que haga cosa diferente cuando se agreg y cuando se actualice con el
case SAPbouiCOM.BoFormMode.fm_UPDATE_MODE:
que piensaS?
muchas gracias, te debo un pedazo de carne enorme xd, jej gracias, estare atento.
saludos

Puedes borrar el evento Grid2_GotFocusAfter y la linea que esta arrojando el error, luego, vas nuevamente a la pantalla de los eventos y le das doble click sobre “GotFocusAfter” para que genere el codigo automaticamente y alli agrega la programacion.

¿Viste este video? Alli se ven estos conceptos basicos:
h_tps://www.youtube.com/watch?v=hkSYrX_PvFk

Sobre el boton, me parece bien, pero si no estas usando el AutoManaged = true en el Form, no hace falta usar el oForm.Mode, solo hace falta cambier el caption del boton y luego en el evento ClickAfter del boton hacer la modificacion cuando el caption = ‘Actualizar’.

1 me gusta

“Code” es una variable que deberas cargar con el campo “Code” del registro correspondiente del DataTable , obviemente puedes llamar esta variable como quieras.

Algo asi:

    int Code = Grid2.DataTable.GetValue("Code", pVal.Row);
    if (oUserTable.GetByKey(Code)) // Esto devuelve true si existe el registro
    {
        Aqui modifico el registro
    }
    else
    {
        Aqui Agrego el Registro
    }
1 me gusta

hola Gabriel,

sabes sigo todo los eventos y va bien pero cuando quiero ser el update en el codigo que me pasaste me da un error
:

     int CODE = (int)(Grid2.DataTable.GetValue("CODE", pVal.Row));
                     int iRet = 0;

                           if (oUserTable.GetByKey(CODE.ToString())) // Esto devuelve true si existe el registro
                                {
                                     oCompany.StartTransaction();
                                     oUserTable.GetByKey("Code");
                                     oUserTable.GetByKey("Name");

es como que no lograra caputar el code, pero en los eventos si lo captura que podria ser?
muchas gracias

“Bad Data Source Offset” es un error que ocurre cuando trata de hacer referencia a una posicion que esta fuera del rango de registros del DataTable.
Verifica que valor esta arrojando pVal.Row y que valor tiene Grid2.DataTable.Rows.Count para ver si estan dentro del rango correcto.

1 me gusta

si lo hago dentro del evento Grid2_ValidateAfter llega el numero code, pero si lo trato de hacer en el boton, me da ese error, porque me trae el code null, igual lo cambie a string ya que no me dejaba convertir de object a int.

:upside_down_face: :flight_departure:

Debes entender que el parametro pVal es un objeto que cambia su contenido de acuerdo al evento donde se usa, obviamente si lo usas sobre un evento del Grid, te trae el numero del Row donde se activo el evento.
Si lo estas usando en un evento de un objeto tipo Button, no servira de nada (Porque estamos actuando sobre un boton, no sobre un grid). En este caso, deberas obtener el numero de fila que esta seleccionada en el grid (Asumiendo que la propiedad del grid “SelectionMode = ms_Single”). para esto se usa:

 int nRow = Grid2.Rows.SelectedRows.Item(0, SAPbouiCOM.BoOrderType.ot_RowOrder);
 int nCode = (int)Grid2.DataTable.GetValue("CODE", nRow);
2 Me gusta

gracias Gabriel, perdona lo básico de algunas preguntas, se pudo hacer, asi que muchas gracias por tus respuestas.
saludos,

1 me gusta

Este tema se cerró automáticamente 7 días después del último post. No se permiten nuevas respuestas.