Refrescar vista de datos desde pestaña de separador de formularios


([N4] gontorre) #1

Os cuento el siguiente problema a ver si me podéis orientar.

Tengo un formulario maestro-detalle con origen DOCUMENTO. En el formulario tengo un separador de formulario con los campos de DOCUMENTO y una vista de datos con DETALLE.

Tengo un manejador de eventos en una de las pestañas del formulario que me carga las líneas de detalle desde una hoja de Excel. El problema que se me plantea es que la vista de datos no se actualiza después de cargar las líneas y desde el separador de formulario no tengo acceso a la vista de datos para hacer un Interfaz: Recalcular. Las líneas se cargan bien porque si cierro la ficha y la vuelvo a abrir me aparecen las líneas.

¿Hay alguna forma de hacer ese refresco de la vista de datos desde el separador de formularios?

Gracias y un saludo

Gonzalo Torre


([N3] pacosatu) #2

Hola Gonzalo.

Por la forma en que está construido Velneo solo podemos acceder al Separador de formularios desde el Formulario principal.

Te voy a proponer una solución que utiliza un mínimo de JavaScript y está basado en considerar que la carga del Detalle está diferida en el tiempo. Usaremos para ello el Timer de los formularios.

Necesitamos lo siguiente:

  • Un proceso en 2º plano PRO_CREAR_DETALLE_2P que en tu caso lee los datos desde Excel.
  • Una variable Global G_REFRESCAR que se pondrá a 1 cuando PRO_CREAR_DETALLE_2P termine. Recuerda que a los procesos en 2P no podemos pasarles parámetros ni fijar ni obtener Variables locales.

Tenemos 3 formularios: FRM_PRINCIPAL con un separador de 2 formularios FRM_DATOS y FRM_DETALLE

  • FRM_DATOS contiene la lógica que lanza el proceso en 2P PRO_CREAR_DETALLE_2P
  • FRM_DETALLE contiene la Vista de Datos del Detalle que inicialmente estará vacio
  • Solo podemos rellenar la Vista de datos de FRM_DETALLE desde el formulario principal FRM_PRINCIPAL

Empezamos:
Para iniciar y parar los Timer usaremos la función del API startTimer() y stopTimer().
Añadimos 2 manejadores de evento a FRM_DATOS


   // Manejador START_TIMER_JS
   theRoot.dataView().startTimer(200)

   // Manejador STOP_TIMER_JS
   theRoot.dataView().stoptTimer()

  • En FRM_DATOS usamos el siguiente código Velneo
    Manejador POS_INI (evento post-inicializado)

Rem ( Ejecutamos el proceso en 2P. Al terminar pondrá la Variable Global G_REFRESCAR a 1 )
Ejecutar proceso ( PRO_CREAR_DETALLE_2P@0PS_Ejercicios_app, 2º plano: Local multitarea (asíncrono), LOK, , )
Interfaz: Ejecutar manejador de evento ( START_TIMER_JS, )

Manejador ON_TIMER (evento Timer)


Rem ( Este evento se ejecuta antes que el del formulario principal )
Rem ( Comprueba si $REFRESCAR = 1 y si es cierto detiene el Timer )
Set ( LCOMPLETADO, $REFRESCAR@0PS_Ejercicios_dat.dat )
If ( LCOMPLETADO )
   // Paramos el Timer una vez completado el proceso en 2P
   Interfaz: Ejecutar manejador de evento ( STOP_TIMER_JS, )

  • En FRM_PRINCIPAL usamos el siguiente código Velneo
    Manejador ON_TIMER_PESTAÑA (evento Timer del subcontrol SEPARADOR.PESTAÑA1)

// Este Manejador captura el evento Timer de la pestaña FRM_DATOS
// Este Manejador se ejecuta después del manejador ON_TIMER de la pestaña FRM_DATOS
// Obtenemos el valor de la variable local LCOMPLETADO de la pestaña FRM_DATOS
Interfaz: Get variable local de vista de datos ( SEPARADOR.PESTAÑA1, LCOMPLETADO, LCOMPLETADO )
If ( LCOMPLETADO )
   // Cargamos el detalle
   Cesta: Crear cesta local ( LINEAS@0PS_Ejercicios_dat, oCes )
   Cargar plurales ( LINEAS_CABECERAS )
      Cesta: Agregar lista a la cesta ( oCes )
   Interfaz: Procesar ( SEPARADOR.PESTAÑA2.REJILLA, Todas )
      Cortar lista ( 0, )
      Cesta: Agregar a la lista en curso ( oCes )
   Interfaz: Activar subcontrol del contenedor de formularios ( SEPARADOR, PESTAÑA2 )

Con esto consigues demorar la carga del detalle en la Rejilla de la pestaña FRM_DETALLE.

En este ejemplo iniciamos el proceso en 2P desde el post-ini de FRM_DATOS pero puede hacerse en cualquier momento, incluso que lo lanze un botón. Recuerda siempre poner en marcha el Timer.

Hay otra forma de hacerlo mediante el API pero eso ya es otro tema.

Saludos
Paco Satué


([N4] gontorre) #3

Gracias Paco,

Funciona de fábula.

Lo del lanzar el proceso en 2º plano supongo que lo haces por si la carga es de muchos datos. En mi caso son ficheros muy pequeños porque se trata de carga las líneas de un pedido. Serán a lo sumo 15 0 20 líneas. Lo hago en primer plano y es instantáneo.

De nuevo gracias y un saludo

Gonzalo Torre


([N3] pacosatu) #4

Hola Gonzalo.

Sí efectivamente, el proceso se ejecuta en 2º plano porque de lo contrario se congelaría la visualización del formulario y quedaría un efecto poco estético. Solo es necesario para procesos largos o en redes lentas. En tu caso, para un proceso corto y en primer plano el Timer solo nos servirá para lanzar el evento ON_TIMER_PESTAÑA en el formulario principal. Puedes poner el valor de Timer tan pequeño como quieras (por ejem 10mseg).

Me alegro que haya funcionado.
Saludos
Paco Satué


([N4] Infortic) #5

No sé si lo he entendido bien, lo que quieres es refrescar una rejilla que está en otro subformulario de un separador.

Si es eso, yo a veces lo he hecho de forma guarrilla en js.

Si como dice Paco tenemos FRM_PRINCIPAL con un separador de 2 formularios FRM_DATOS y FRM_DETALLE al que llamamos SEPARADOR

FRM_DETALLE tiene la rejilla, que llamamos REJILLA.
FRM_DATOS tiene el manejador que carga desde excel.

En FRM_DETALLE:

  1. Creamos un manejador V7 llamado REFRESCA_REJILLA

Interfaz: Recalcular(REJILLA)

  1. Creamos un botón llamado BTN_REFRESCAR invisible (con condición de visible 0) que ejecuta el manejador anterior

En FRM_DATOS:

  1. Creamos un manejador JS llamado REFRESCAR_DETALLE

theMainWindow.currentView().centralWidget().control(“SEPARADOR”).form(“FRM_DETALLE”).control(“BTN_REFRESCAR”).click();

Cuando quieras refrescar la rejilla del otro subformulario simplemente llamas a ese manejador.


([N3] pacosatu) #6

Hola info()

OK, esa sería la forma de hacerlo mediante el API.
Yo quería exponer una forma puramente Velneo (a excepción de Iniciar/Parar el Timer).

De todas formas, ¡¡OJO!!
La función theMainWindow.currentView() solo es operativa para formularios en modo Vista. Cuando FRM_PRINCIPAL es un formulario en modo Diálogo ya no podemos acceder a él desde el objeto theMainWindow.

Está claro que debe mejorar mucho el Gestor de eventos de Velneo para que este tipo de cosas sea algo trivial.

Saludos
Paco Satué


([N4] Infortic) #7

Cierto, en modal se fastidiará el invento. ¿Se te ocurre con qué objeto acceder al formulario modal en curso ?


([N3] pacosatu) #8

Hola info.

En realidad, no creo que necesitemos nunca acceder a un formulario modal desde fuera de éste, ya que el resto de la Aplicación queda a la expectativa de que confirmemos el formulario modal.
Lo que sí necesitaremos es interactuar entre los subobjetos contenidos dentro del formulario modal.

Para ello tenemos las funciones VFormDataView.mainForm() que devuelve el Formulario principal desde cualquier subFormulario y la función VAbstractDataView.parentDataView() que devolverá el objeto Contenedor del subObjeto actual.

Así, el ejemplo que nos ocupa, usando el API quedaría:
theRoot.dataView().mainForm().control(“SEPARADOR”).form(“FRM_DETALLE”).control(“BTN_REFRESCAR”).click()

Saludos
Paco Satué


([N1] Ramiropa) #9

Buenas:

El problema de este problema es que la solución (JavaScript) no es una solución…

Mientras la estructura interna no permita que un hijo (pestaña de formulario, formulario de una pila, etc) acceda con código nativo V7 a las propiedades y eventos de sus hermanos (otras pestañas, otros formularios de la pila, etc) a través del formulario padre, estaremos a los pies de los caballos.

JavaScript no refactoriza y la documentación del API es horrenda. Malos mimbres…

El problema del problema es que no parece que vaya a tener solución… Life is soft.

Saludos. Ramiro


([N4] Infortic) #10

Es cierto Ramiro, js da muchas posibilidades, pero que no refactorice y no de errores de “compilación” hace que sea delicado usarlo para muchos menesteres.

Gracias Paco, no me había dado cuenta de mainForm(), con eso lo solucionas.