Sabías que … (5)

Nuestro “Papá Noel” Particular nos ha regalado una nueva entrega  “Sabías que“. En este post veremos curiosidades sobre funciones, contenidos iniciales, rejillas y personalización de gráficos nativos mediante CSS.

Por si te perdiste las cuatro primeras entregas del “juego”, no está de mas recordarlas:

¿Sabías que..?

Si no te fijas bien, la función getStringRegExp() te puede jugar una mala pasada

    • La función de cadena getStringRegExp(cadena, expresionRegular, posIni, caseSensitive, numSubExpresion) recibe como expresión regular una cadena.
    • En las expresiones regulares se usan metacaracteres, algunos de los cuales deben escaparse y ¿cuál es el caracter de escape?, pues precisamente el caracter \.
    • Por lo tanto, en Velneo debemos escapar los metacaracteres con doble caracter \ para que funcione correctamente la función getStringRegExp

Un ejemplo para obtener el código a la derecha de la palabra Informe:
 getStringRegExp(“Informe  233421122”, “Informe (\\d{1,}$)”, 0, 0, 1)  = 233421122

    • Cuando copiéis expresiones regulares de Internet, prestad atención a estos detalles, o padeceréis horas de desconcierto

Podemos recorrer los controles de una Caja de grupo (QGroupBox) para aplicar una determinada acción

    • El API de Velneo es una herramienta muy útil y este es un ejemplo de ello.
    • La clase QGroupBox (control caja de Grupo) dispone de 2 funciones, childWidgetAt(nIndex) y childWidget(nCount), que nos permiten recorrer todos los controles contenidos en la caja de grupo.
    • La función childWidgetAt devuelve un objeto Widget al que podremos aplicar una determinada acción.

Se puede establecer el tiempo que se muestran los caracteres en las cajas de edición que tienen la propiedad Contraseña activada

    • Debemos usar un par de propiedades CSS, lineedit-password-character y lineedit-password-mask-delay
    • La propiedad CSS lineedit-password-character determina código UNICODE elegido para ocultar la contraseña.
      Ejem:  ● 9679  * 42
    • La propiedad CSS lineedit-password-mask-delay establece el retardo en milisegundos
QLineEdit { 
   lineedit-password-character: 9679;
   lineedit-password-mask-delay: 300;
}

La columna de la rejilla puede mostrar directamente un icono

    • Si solo deseamos mostrar un icono en la columna de un rejilla no es necesario hacerlo en la parte reservada para ello.
    • Podemos hacerlo en la zona reservada para el contenido de la columna.
    • El editor de fórmulas no nos dejará insertar, por ejemplo, el campo ICONO de la tabla estática. Lo tecleamos manualmente.
      #BLOQUEADO_ICO.ICON

¿En qué plano se determinan los valores iniciales de los campos de la tabla?

    • El plano donde se ejecuta el comando Crear nueva ficha en memoria es en el que se determinan los valores iniciales.
    • Si queremos que siempre se determinen en 3P tendremos que calcular el valor inicial en el Trigger anterior al Alta.
    • En el API con el VRegister, los valores iniciales se calculan en la función setTable(), ¡¡ cuidado con esto !!.

¿Para qué sirve la función de campo getID()?

    • ¿Qué sentido tiene la función GetID() si devuelve el mismo ID que uso para llamarla?
    • Pues nos permite refactorizar los nombres de campo de una tabla cuando éstos son renombrados
      Por ejemplo:
      Hay que pasar a una función un string con los nombres de campo separados por comas.
      Si renombramos los campos AUTOR, CSS_FINAL o NOTAS, la aplicación seguirá funcionando correctamente.
Set (CLISTA_CAMPOS, "ID,NAME," + #AUTOR:getID() + "," + #CSS_FINAL:getID()  + "," + #NOTAS:getID()

Podemos usar el control Combobox en formularios sin Origen

    • El control combobox del formulario es muy cómodo de usar para el usuario si va a seleccionar de una lista corta, entre otras cosas, porque la lista se despliega directamente al pulsar con el ratón.
    • A veces tenemos un formulario sin origen y necesitamos desplegar los valores de una tabla maestra.
    • Una técnica habitual es crear una tabla temporal con todos los punteros a maestro que vayamos a usar en controles de selección
    • En el formulario sin origen añadimos una Ficha de Extensión FIEXT que se alimente por proceso, Alta, Baja y Modificación estarán a cero.
Crear nueva ficha en memoria (hMaestros, MAESTROS_TEMP@MiApp_app)
        Añadir ficha a la salida
    • Añadimos el control combobox y lo asociamos al campo puntero a maestro de la Ficha de Extensión FIEXT.
    • Ya sabemos que el valor seleccionado en el Combobox se lee mediante ##FIEXT.EMPRESA.ID.

Podemos personalizar los Gráficos nativos con CSS

    • El nuevo gráfico de Velneo es un control nativo LifeIsSoft y por lo tanto desesperadamente poco personalizable.
    • Sin embargo, teniendo en cuenta que los Títulos y Etiquetas son objetos Label de Qt, podemos usar tags HTML y código CSS.

Veamos 2 ejemplos que puedes probar en la aplicación del cloud vatp://pruebas:pruebas@c6.velneo.com:16400/0PS__MisCSS_iapp:

/* Gráfico nativo */
/* No existe selector de clase
Aunque podemos usar los tags HTML y código CSS en los Títulos y etiquetas del Gráfico
Pero limitados al subconjunto de HTML4 - http://doc.qt.io/qt-5/richtext-html-subset.html */

/* Cada etiqueta QLbel personaliza un elemento del gráfico.
Lo que hacemos es parsear el código CSS y aplicar un Atributo HTML style="font: bold 18px verdana; ...." mediante variables locales 
definidas en el Gráfico nativo que se añaden como prefijo a los Títulos y Etiquetas
*/

QLabel#GRAF_TITULO {
   font: bold 18px verdana;
   text-align: center;
   background-color: WhiteSmoke;
   color: DarkSlateGray;
   padding: 0 80 0 80;
}
QLabel#GRAF_TITULO_EJEY {
   font: bold 12px arial;
   text-align: center;
   color: DarkSlateGray;
}
QLabel#GRAF_TITULO_EJEX {
   font: bold 11px arial;
   text-align: center;
   color: DarkSlateGray;
}
QLabel#GRAF_ETIQUETAS_EJEY {
   font: bold 12px arial;
   text-align: center;
   color: DimGray;
}
QLabel#GRAF_ETIQUETAS_EJEX {
   font: bold 10px arial;
   background-color: IndianRed;
   color: Cornsilk;
   padding: 3 10 3 10;
}
QLabel#GRAF_ETIQUETAS_SERIE1 {
   font: bold 12px verdana;
   background-color: DarkGreen;
   color: HoneyDew;
   padding: 3 10 3 10;
}
QLabel#GRAF_ETIQUETAS_SERIE2 {
   font: bold 12px arial;
   color: white;
}

Las funciones CurrentDateTime() y CurrentUTCDateTime() tienen truco

    • Un día quise obtener el huso horario de vClient y como no me acordaba de la función getSysTimeZone(), hice lo siguiente:
set ( NDIF_HOR, secondsTo(currentDateTime(), currentUTCDateTime()))

Sin embargo, el resultado es cero.

    • Consultado a soporte, resulta que currentDateTime() y currentUTCDateTime() representan internamente la misma fecha, lo que ocurre es que las variables de tipo Tiempo guardan el huso horario en el que han sido creadas y Velneo no nos proporciona ese dato. Estas funciones devuelven fechas distintas en algunas operaciones y en otras actúan como valores iguales, lo que crea una gran confusión. Como muchas veces ocurre, no está documentado.
    • Así que tenerlo en cuenta:
dateTimeToTime(currentUTCDateTime()) es distinto de dateTimeToTime(currentDateTime())
dateTimeToString(currentUTCDateTime(), "hh:mm") es distinto de dateTimeToTime(currentDateTime(), "hh:mm")
pero
currentUTCDateTime() es igual a currentDateTime()
    • Si no existiera getSysTimeZone() la forma correcta de obtener el huso horario sería:
// Creamos 2 variables Tiempo nuevas a partir de información devuelta por las funciones currentDateTime y currentUTCDateTime
Set (THORA_LOCAL, setDateTime(dateTimeToDate(currentDateTime()), dateTimeToTime(currentDateTime()))
Set (THORA_UTC, setDateTime(dateTimeToDate(currentUTCDateTime()), dateTimeToTime(currentUTCDateTime()))
// Ya podemos operar con las variables Tiempo
Set (NDIF_HORARIA , secondsTo(THORA_UTC, THORA_LOCAL) / 3600)
Mensaje ("Hora local: " + dateTimeToString(currentDateTime(), "dd/MM/yyyy hh:mm") + "<br>" + 
"Hora UTC: " + dateTimeToString(currentUTCDateTime(), "dd/MM/yyyy hh:mm") + "<br>" +
"Diferencia horaria: " + numberToString(NDIF_HORARIA, "L", 0)

Los formularios del Bloc de Formularios no ejecutan el evento PRE_INI

    • Los formularios pueden ser los contenedores de los registros en algunos controles de Vista de datos de tipo Lista como el Bloc de formularios.
    • En este caso hay que tener en cuenta lo siguiente:
      • El evento Pre-inizialización del formulario solo se ejecutará cuando se muestra el Bloc de formularios, es decir, solo se ejecuta para el formulario mostrado en ese momento. Cuando navegamos por la Lista de registros no se dispara este evento.
      • Aparece un evento Item: pre cambio de seleccionado que funciona al contrario que el evento Pre-inizialización. En este caso se ejecuta solo cuando navegamos por la LIsta de registros.
      • En el Bloc de formularios no podemos usar en el manejador PRE_INI código que dependa del registro de la tabla, sobre todo el código que determina el nivel de acceso del Usuario a los registros. 

Y ahora confiesa… ¿cuántas de estas curiosidades sobre gráficos, rejillas y funciones sabías? 

Déjame un comentario mas abajo y comenzamos el debate.

La entrada Sabías que … (5) aparece primero en AyudaVelneo.

Sabías que … (5)

Nuestro “Papá Noel” Particular nos ha regalado una nueva entrega  “Sabías que“. En este post veremos curiosidades sobre funciones, contenidos iniciales, rejillas y personalización de gráficos nativos mediante CSS.

Por si te perdiste las cuatro primeras entregas del “juego”, no está de mas recordarlas:

¿Sabías que..?

Si no te fijas bien, la función getStringRegExp() te puede jugar una mala pasada

    • La función de cadena getStringRegExp(cadena, expresionRegular, posIni, caseSensitive, numSubExpresion) recibe como expresión regular una cadena.
    • En las expresiones regulares se usan metacaracteres, algunos de los cuales deben escaparse y ¿cuál es el caracter de escape?, pues precisamente el caracter \.
    • Por lo tanto, en Velneo debemos escapar los metacaracteres con doble caracter \ para que funcione correctamente la función getStringRegExp

Un ejemplo para obtener el código a la derecha de la palabra Informe:
 getStringRegExp(“Informe  233421122”, “Informe (\\d{1,}$)”, 0, 0, 1)  = 233421122

    • Cuando copiéis expresiones regulares de Internet, prestad atención a estos detalles, o padeceréis horas de desconcierto

Podemos recorrer los controles de una Caja de grupo (QGroupBox) para aplicar una determinada acción

    • El API de Velneo es una herramienta muy útil y este es un ejemplo de ello.
    • La clase QGroupBox (control caja de Grupo) dispone de 2 funciones, childWidgetAt(nIndex) y childWidget(nCount), que nos permiten recorrer todos los controles contenidos en la caja de grupo.
    • La función childWidgetAt devuelve un objeto Widget al que podremos aplicar una determinada acción.

Se puede establecer el tiempo que se muestran los caracteres en las cajas de edición que tienen la propiedad Contraseña activada

    • Debemos usar un par de propiedades CSS, lineedit-password-character y lineedit-password-mask-delay
    • La propiedad CSS lineedit-password-character determina código UNICODE elegido para ocultar la contraseña.
      Ejem:  ● 9679  * 42
    • La propiedad CSS lineedit-password-mask-delay establece el retardo en milisegundos
QLineEdit { 
   lineedit-password-character: 9679;
   lineedit-password-mask-delay: 300;
}

La columna de la rejilla puede mostrar directamente un icono

    • Si solo deseamos mostrar un icono en la columna de un rejilla no es necesario hacerlo en la parte reservada para ello.
    • Podemos hacerlo en la zona reservada para el contenido de la columna.
    • El editor de fórmulas no nos dejará insertar, por ejemplo, el campo ICONO de la tabla estática. Lo tecleamos manualmente.
      #BLOQUEADO_ICO.ICON

¿En qué plano se determinan los valores iniciales de los campos de la tabla?

    • El plano donde se ejecuta el comando Crear nueva ficha en memoria es en el que se determinan los valores iniciales.
    • Si queremos que siempre se determinen en 3P tendremos que calcular el valor inicial en el Trigger anterior al Alta.
    • En el API con el VRegister, los valores iniciales se calculan en la función setTable(), ¡¡ cuidado con esto !!.

¿Para qué sirve la función de campo getID()?

    • ¿Qué sentido tiene la función GetID() si devuelve el mismo ID que uso para llamarla?
    • Pues nos permite refactorizar los nombres de campo de una tabla cuando éstos son renombrados
      Por ejemplo:
      Hay que pasar a una función un string con los nombres de campo separados por comas.
      Si renombramos los campos AUTOR, CSS_FINAL o NOTAS, la aplicación seguirá funcionando correctamente.
Set (CLISTA_CAMPOS, "ID,NAME," + #AUTOR:getID() + "," + #CSS_FINAL:getID()  + "," + #NOTAS:getID()

Podemos usar el control Combobox en formularios sin Origen

    • El control combobox del formulario es muy cómodo de usar para el usuario si va a seleccionar de una lista corta, entre otras cosas, porque la lista se despliega directamente al pulsar con el ratón.
    • A veces tenemos un formulario sin origen y necesitamos desplegar los valores de una tabla maestra.
    • Una técnica habitual es crear una tabla temporal con todos los punteros a maestro que vayamos a usar en controles de selección
    • En el formulario sin origen añadimos una Ficha de Extensión FIEXT que se alimente por proceso, Alta, Baja y Modificación estarán a cero.
Crear nueva ficha en memoria (hMaestros, MAESTROS_TEMP@MiApp_app)
        Añadir ficha a la salida
    • Añadimos el control combobox y lo asociamos al campo puntero a maestro de la Ficha de Extensión FIEXT.
    • Ya sabemos que el valor seleccionado en el Combobox se lee mediante ##FIEXT.EMPRESA.ID.

Podemos personalizar los Gráficos nativos con CSS

    • El nuevo gráfico de Velneo es un control nativo LifeIsSoft y por lo tanto desesperadamente poco personalizable.
    • Sin embargo, teniendo en cuenta que los Títulos y Etiquetas son objetos Label de Qt, podemos usar tags HTML y código CSS.

Veamos 2 ejemplos que puedes probar en la aplicación del cloud vatp://pruebas:pruebas@c6.velneo.com:16400/0PS__MisCSS_iapp:

/* Gráfico nativo */
/* No existe selector de clase
Aunque podemos usar los tags HTML y código CSS en los Títulos y etiquetas del Gráfico
Pero limitados al subconjunto de HTML4 - http://doc.qt.io/qt-5/richtext-html-subset.html */

/* Cada etiqueta QLbel personaliza un elemento del gráfico.
Lo que hacemos es parsear el código CSS y aplicar un Atributo HTML style="font: bold 18px verdana; ...." mediante variables locales 
definidas en el Gráfico nativo que se añaden como prefijo a los Títulos y Etiquetas
*/

QLabel#GRAF_TITULO {
   font: bold 18px verdana;
   text-align: center;
   background-color: WhiteSmoke;
   color: DarkSlateGray;
   padding: 0 80 0 80;
}
QLabel#GRAF_TITULO_EJEY {
   font: bold 12px arial;
   text-align: center;
   color: DarkSlateGray;
}
QLabel#GRAF_TITULO_EJEX {
   font: bold 11px arial;
   text-align: center;
   color: DarkSlateGray;
}
QLabel#GRAF_ETIQUETAS_EJEY {
   font: bold 12px arial;
   text-align: center;
   color: DimGray;
}
QLabel#GRAF_ETIQUETAS_EJEX {
   font: bold 10px arial;
   background-color: IndianRed;
   color: Cornsilk;
   padding: 3 10 3 10;
}
QLabel#GRAF_ETIQUETAS_SERIE1 {
   font: bold 12px verdana;
   background-color: DarkGreen;
   color: HoneyDew;
   padding: 3 10 3 10;
}
QLabel#GRAF_ETIQUETAS_SERIE2 {
   font: bold 12px arial;
   color: white;
}

Las funciones CurrentDateTime() y CurrentUTCDateTime() tienen truco

    • Un día quise obtener el huso horario de vClient y como no me acordaba de la función getSysTimeZone(), hice lo siguiente:
set ( NDIF_HOR, secondsTo(currentDateTime(), currentUTCDateTime()))

Sin embargo, el resultado es cero.

    • Consultado a soporte, resulta que currentDateTime() y currentUTCDateTime() representan internamente la misma fecha, lo que ocurre es que las variables de tipo Tiempo guardan el huso horario en el que han sido creadas y Velneo no nos proporciona ese dato. Estas funciones devuelven fechas distintas en algunas operaciones y en otras actúan como valores iguales, lo que crea una gran confusión. Como muchas veces ocurre, no está documentado.
    • Así que tenerlo en cuenta:
dateTimeToTime(currentUTCDateTime()) es distinto de dateTimeToTime(currentDateTime())
dateTimeToString(currentUTCDateTime(), "hh:mm") es distinto de dateTimeToTime(currentDateTime(), "hh:mm")
pero
currentUTCDateTime() es igual a currentDateTime()
    • Si no existiera getSysTimeZone() la forma correcta de obtener el huso horario sería:
// Creamos 2 variables Tiempo nuevas a partir de información devuelta por las funciones currentDateTime y currentUTCDateTime
Set (THORA_LOCAL, setDateTime(dateTimeToDate(currentDateTime()), dateTimeToTime(currentDateTime()))
Set (THORA_UTC, setDateTime(dateTimeToDate(currentUTCDateTime()), dateTimeToTime(currentUTCDateTime()))
// Ya podemos operar con las variables Tiempo
Set (NDIF_HORARIA , secondsTo(THORA_UTC, THORA_LOCAL) / 3600)
Mensaje ("Hora local: " + dateTimeToString(currentDateTime(), "dd/MM/yyyy hh:mm") + "<br>" + 
"Hora UTC: " + dateTimeToString(currentUTCDateTime(), "dd/MM/yyyy hh:mm") + "<br>" +
"Diferencia horaria: " + numberToString(NDIF_HORARIA, "L", 0)

Los formularios del Bloc de Formularios no ejecutan el evento PRE_INI

    • Los formularios pueden ser los contenedores de los registros en algunos controles de Vista de datos de tipo Lista como el Bloc de formularios.
    • En este caso hay que tener en cuenta lo siguiente:
      • El evento Pre-inizialización del formulario solo se ejecutará cuando se muestra el Bloc de formularios, es decir, solo se ejecuta para el formulario mostrado en ese momento. Cuando navegamos por la Lista de registros no se dispara este evento.
      • Aparece un evento Item: pre cambio de seleccionado que funciona al contrario que el evento Pre-inizialización. En este caso se ejecuta solo cuando navegamos por la LIsta de registros.
      • En el Bloc de formularios no podemos usar en el manejador PRE_INI código que dependa del registro de la tabla, sobre todo el código que determina el nivel de acceso del Usuario a los registros. 

Y ahora confiesa… ¿cuántas de estas curiosidades sobre gráficos, rejillas y funciones sabías? 

Déjame un comentario mas abajo y comenzamos el debate.

La entrada Sabías que … (5) aparece primero en AyudaVelneo.

Nueva revisión 1.1 de la Open App vTools

El pasado 17 de noviembre de 2011 hemos actualizado el componente vTools a su versión 1.1. Se han corregido varios bugs y se han incluído nuevas funcionalidades.

Os recuerdo que este componente incluye una serie de funciones realmente útiles como, por ejemplo, uso de diccionarios para almacenar información, un parseador simple de xml, etc.

Puedes ver más información de cómo ver este componente en estos dos artículos: Descubriendo el componente vTools 1 y Descubriendo el componente vTools 2.

vJavaScript: VApp

¿Qué es vJavaScript?

 
vJavaScript es la implementación realizada en Velneo sobre el lenguaje de programación JavaScript al que se le han añadido un conjunto de clases que aportan objetos y funciones adicionales para obtener una integración completa en la plataforma de desarrollo de aplicaciones empresariales Velneo V7.

 

VApp

 
Este objeto representa a la aplicacion. Dispone de funciones para ver información de sus proyectos, acceso a variables globales y utilidades de base de datos. En el blog del vArquitecto encontrarás la información detallada sobre este objetos y sus funciones “Objeto VApp para vJavaScript“.

 

Funciones

 
Están combinadas parejas de funciones por equivalencia de uso de datos para almacenamiento y lectura de las variables globales.

 
 

Variable global alfabética

// Almacena un valor cadena en una variable global alfabética.
void setGlobalVar( String szIdRefVar, String szValue );

//Devuelve el valor de una variable global alfabética. 
String globalVarToString( String szIdRefVar );
// VJAVASCRIPT_STRING es una variable global alfabética declarada en el proyecto de datos VEST_DAT.
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_STRING", "ABC")
var resultado = VApp.globalVarToString("VEST_DAT/VJAVASCRIPT_STRING"); 

 
 

Variable global numérica (con decimales y signo)

// Almacena un valor numérico en una variable global numérica.
void setGlobalVar( String szIdRefVar, Number nValue );

// Devuelve el valor de una variable global numérica con formato Double.
double globalVarToDouble( String szIdRefVar );
// VJAVASCRIPT_NUMBER es una variable global numérica declarada en el proyecto de datos VEST_DAT.
// En el ejemplo se puede observar como se pasan valores con decimales y signo.
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_NUMBER", -9876543.21)
var resultado = VApp.globalVarToDouble("VEST_DAT/VJAVASCRIPT_NUMBER");

 
 

Variable global numérica (entero)

// Almacena un valor numérico en una variable global numérica.
void setGlobalVar( String szIdRefVar, Number nValue );

// Devuelve el valor de una variable global numérica con formato Int.
int globalVarToInt( String szIdRefVar );
// VJAVASCRIPT_NUMBER es una variable global numérica declarada en el proyecto de datos VEST_DAT.
// La función para almacenar valores numéricos es la misma tanto si es double, int o boolean.
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_NUMBER", 987654321)
var resultado = VApp.globalVarToInt("VEST_DAT/VJAVASCRIPT_NUMBER");

 
 

Variable global booleana

// Almacena un valor 1 ó 0 en una variable global booleana.
void setGlobalVar( String szIdRefVar, Boolean bValue );

// Devuelve el valor de una variable global booleana.
int globalVarToInt( String szIdRefVar );
// VJAVASCRIPT_BOOLEAN es una variable global booleana declarada en el proyecto de datos VEST_DAT.
// La función para almacenar valores numéricos es la misma tanto si es double, int o boolean.
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_BOOLEAN", 1)
var resultado = VApp.varGlobalToInt("VEST_DAT/VJAVASCRIPT_BOOLEAN");

 
 

Variable global de tiempo

// Almacena un valor fecha y hora en una variable global de tiempo.
void setGlobalVar( String szIdRefVar, QDateTime dtValue );
// Devuelve el valor de una variable global de tiempo.
QDateTime globalVarToDateTime( String szIdRefVar );
// VJAVASCRIPT_DATETIME es una variable global de tiempo declarada en el proyecto de datos VEST_DAT.
// Nota: En la función Date() de JavaScript el parámetro mes admite valores de (0=enero a 11=diciembre)
var fecha_hora_original = new Date(2012, 11, 31, 12, 34, 56, 123);
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_DATETIME", fecha_hora_original);
var fecha_hora_devuelta = VApp.globalVarToDateTime("VEST_DAT/VJAVASCRIPT_DATETIME");

 
 

Variable global de fecha

// Almacena un valor fecha en una variable global de fecha.
void setGlobalVar( String szIdRefVar, QDate dValue );
// Devuelve el valor de una variable global de fecha.
QDate globalVarToDate( String szIdRefVar );
// VJAVASCRIPT_DATE es una variable global de fecha declarada en el proyecto de datos VEST_DAT.
// En la función Date() de JavaScript el parámetro mes admite valores de (0=enero a 11=diciembre)
var fecha_original = new Date(2012, 11, 31);
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_DATE", fecha_original);
var fecha_devuelta = VApp.globalVarToDate("VEST_DAT/VJAVASCRIPT_DATE");

 
 

Variable global de hora

// Almacena un valor hora en una variable global de hora.
void setGlobalVar( String szIdRefVar, QTime tValue );
// Devuelve el valor de una variable global de hora.
QTime globalVarToTime( String szIdRefVar );
// VJAVASCRIPT_TIME es una variable global de hora declarada en el proyecto de datos VEST_DAT.
var hora_original = new Date(2012, 11, 31, 12, 34, 56, 000);
VApp.setGlobalVar("VEST_DAT/VJAVASCRIPT_TIME", hora_original);
var fecha_devuelta = VApp.globalVarToTime("VEST_DAT/VJAVASCRIPT_TIME");

 
 

Verificar si una variable global está vacía

// Devuelve el valor 1 sí la variable global está vacía y el valor 0 si tiene contenido.
Boolean isGlobalVarEmpty( String szIdRefVar );
// VJAVASCRIPT_STRING es una variable global alfabética declarada en el proyecto de datos VEST_DAT.
var resultado = VApp.isGlobalVarEmpty("VEST_DAT/VJAVASCRIPT_STRING");

Nueva Open App: Automatización de tareas

Con esta nueva Open App podemos automatizar en una sola aplicación la ejecución de tareas periódicas, desde el envío y recepción de correos, la sincronización de los datos contra v6 o bases de datos externas, ejecución de funciones remotas en distintas aplicaciones, etc.

Se compone de dos soluciones, el configurador y el ejecutor propiamente dicho de las tareas.

Plantilla Automatización de tareas

vJavaScript: VTableInfo


¿Qué es una prueba funcional?

 
Definición de Wikipedia: “Una prueba funcional es una prueba basada en la ejecución, revisión y retroalimentación de las funcionalidades previamente diseñadas para el software. Las pruebas funcionales se hacen mediante el diseño de modelos de prueba que buscan evaluar cada una de las opciones con las que cuenta el paquete informático.”

 

¿Qué es vEST?

 
vEST es el conjunto de aplicaciones y scripts que permiten realizar pruebas funcionales de Velneo V7 en distintos sistemas operativos y relacionado con el sistema de integración continua. Se distinguen pruebas funcionales de pruebas de interfaz debido a su distinto tratamiento. vEST sólo realiza comprobaciones de tareas sin interfaz.

 

¿Qué es vJavaScript?

 
vJavaScript es la implementación realizada en Velneo sobre el lenguaje de programación JavaScript al que se le han añadido un conjunto de clases que aportan objetos y funciones adicionales para obtener una integración completa en la plataforma de desarrollo de aplicaciones empresariales Velneo V7.

 

VTableInfo

 
Los objetos de esta clase contienen la información de la estructura de una tabla. Tiene funciones generales de la tabla, como ver su id o su tipo, y funciones para obtener información de sus subobjetos: campos, indices e históricos. También nos permite obtener otros VTablaInfo de las tablas enlazadas como maestros o históricos. En el blog del vArquitecto encontrarás la información detallada sobre esta clase y sus funciones “Class VTableInfo para vJavaScript“.

 

Testeo de las funciones

 
En vEST se ha incluido el testeo de un grupo de funciones de la clase VTableInfo. A continuación se muestran las capturas de los códigos de las pruebas que espero te puedan ayudar como material de consulta sobre la codificación de estas funciones.

vEST graba en la tabla LOG los resultados de las pruebas. Por ese motivo el script comienza abriendo la transacción en la que se incluirán las altas de los registros con los resultados de las pruebas. La tabla de entrada del proceso que ejecuta el script es precisamente la tabla LOG, es precisamente contra esta tabla contra la que se lanzarán las funciones.

 
Todos los testeos se realizan de la misma forma:

  • 1º Se guarda en una variable el resultado de la ejecución de la función.
  • 2º Se modifica el campo NAME de la tabla LOG con la descripción de la función testada.
  • 3º Se modifica el campo RESULTADO de la tabla LOG con el resultado de la comparación del valor retornado por la función y la constante que contiene el resultado esperado.
  • 4º Se añade el nuevo registro en la tabla LOG.

 
 

id()

// Devuelve el valor de la propiedad identificador de la tabla.
VTableInfo.id()
var resultado = VRegisterListIn.tableInfo().id();
registro.setField("NAME", "VJS_TBI_001 - Tabla VTableInfo.id()");
registro.setField("RESULTADO", String(resultado == "LOGS"));
registro.addRegister();

 
 

name()

//Devuelve el valor de la propiedad nombre plural de la tabla.
VTableInfo.name()
var resultado = VRegisterListIn.tableInfo().name();
registro.setField("NAME", "VJS_TBI_002 - Tabla VTableInfo.name()");
registro.setField("RESULTADO", String(resultado == "Logs"));
registro.addRegister();

 
 

singleName()

// Devuelve el valor de la propiedad nombre singular de la tabla.
VTableInfo.singleName()
var resultado = VRegisterListIn.tableInfo().singleName();
registro.setField("NAME", "VJS_TBI_003 - Tabla VTableInfo.singleName()");
registro.setField("RESULTADO", String(resultado == "Log"));
registro.addRegister();

 
 

type()

// Devuelve el valor de la propiedad tipo de tabla.
VTableInfo.type()</strong>
var resultado = VRegisterListIn.tableInfo().type();
registro.setField("NAME", "VJS_TBI_004 - Tabla VTableInfo.type()");
registro.setField("RESULTADO", String(resultado == 0));
registro.addRegister();

 
 

isInMemory()

// Devuelve un 1 si la tabla está definida con persistencia en memoria.
// Devuelve un 0 si la tabla está definida con persistencia en disco.
VTableInfo.isInMemory()
var resultado = VRegisterListIn.tableInfo().isInMemory();
registro.setField("NAME", "VJS_TBI_005 - Tabla VTableInfo.isInMemory()");
registro.setField("RESULTADO", String(resultado == 0));
registro.addRegister();

 
 

registerLength()

// Devuelve el tamaño del registro de la tabla en bytes.
VTableInfo.registerLength()
var resultado = VRegisterListIn.tableInfo().registerLength();
registro.setField("NAME", "VJS_TBI_006 - Tabla VTableInfo.registerLength()");
registro.setField("RESULTADO", String(resultado == 142));
registro.addRegister();

 
 

fieldCount()

// Devuelve el número de campos de la tabla.
VTableInfo.fieldCount()
var resultado = VRegisterListIn.tableInfo().fieldCount();
registro.setField("NAME", "VJS_TBI_007 - Campos VTableInfo.fieldCount()");
registro.setField("RESULTADO", String(resultado == 6));
registro.addRegister();

 
 

fieldId()

// Devuelve el valor de la propiedad identificador de un número de campo.
VTableInfo.fieldId( Number nCampo );
// Se hace un bucle concatenando el valor de la propiedad identificador de todos los campos de la tabla.
var resultado = ""
for (var x=0; x < VRegisterListIn.tableInfo().fieldCount(); x++)
{
	var resultado = resultado + VRegisterListIn.tableInfo().fieldId(x) + " ";	
}
registro.setField("NAME", "VJS_TBI_008 - Campos VTableInfo.fieldId()");
registro.setField("RESULTADO", String(resultado == "ID NAME RESULTADO EQUIPO TIEMPO VALOR "));
registro.addRegister();

 
 

fieldName()

// Devuelve el valor de la propiedad descripción de un número de campo.
VTableInfo.fieldName( Number nCampo )
// Se hace un bucle concatenando el valor de la propiedad descripción de todos los campos de la tabla.
var resultado = ""
for (var x=0; x < VRegisterListIn.tableInfo().fieldCount(); x++)
{
	var resultado = resultado + VRegisterListIn.tableInfo().fieldName(x) + " ";	
}
registro.setField("NAME", "VJS_TBI_009 - Campos VTableInfo.fieldName()");
registro.setField("RESULTADO", String(resultado == "Codigo Nombre Resultado Equipo TIEMPO Valor "));
registro.addRegister();

 
 

fieldType()

// Devuelve el tipo de campo de un número de campo.
VTableInfo.fieldType( Number nCampo )
// Se hace un bucle concatenando el valor del tipo de campo de todos los campos de la tabla.
var resultado = ""
for (var x=0; x < VRegisterListIn.tableInfo().fieldCount(); x++)
{
	var resultado = resultado + VRegisterListIn.tableInfo().fieldType(x) + " ";	
}
registro.setField("NAME", "VJS_TBI_010 - Campos VTableInfo.fieldType()");
registro.setField("RESULTADO", String(resultado == "6 1 10 3 9 6 "));
registro.addRegister();

Nueva Velneo Open App: Get Date-Time Excel

Este sencillo y práctico componente permite interpretar y formatear la información leída de una celda de Excel y transformarla en formato Velneo.

Excel guarda internamente las Fechas-Horas como un número, con parte entera y decimal. Al leer una celda de Excel se obtiene dicho número, que es necesario transformar para grabar por separado Fecha y Hora en campos de tablas Velneo.

A las funciones incluidas en esta vOpen App se les pasa, como único parámetro, el valor numérico leído por la dll y devuelven la fecha y la hora.

Componente Get Date-Time Excel

Códigos funciones para fórmulas dinámicas

En Velneo V7 no tenemos fórmulas dinámicas (por el momento) pero en V6 sí, y son súper útiles. Nosotros las usamos mucho para por ejemplo tablas de configuración, parámetros de la aplicación, entre otros fines.

En las tablas de configuración solemos poner valores por defecto en las fórmulas dinámicas para así agilizar el trabajo a la hora de la instalación etc. pero las funciones de Velneo tienen una particularidad al referirnos a ellas en contenidos iniciales y procesos en campos de tipo fórmula dinámica. Se trata de que no se puede poner en el proceso o contenido inicial la función directamente, sino que va con un código. Y también ese código de la función se muestra cuando se pone el campo fórmula dinámica en una rejilla o al imprimir la fórmula dinámica

Me pasó ayer, y cogí “el toro por los cuernos” y recopilé, de una vez por todas y para siempre (mientras no añadan más funciones en Velneo V6) los códigos que corresponden a las funciones:

Velneo V6x Funciones en Formulas Dinamicas codificacion

Los parámetros de las funciones serían exactamente igual que en la función original, separados por , si corresponde y entre paréntesis.

Un ejemplo de contenido inicial de la fórmula dinámica sería así:

“f025( %CAMPO-CONDICION%,  %CAMPO1%, %CAMPO2%)” + fRepiteCadena( “”, 1 )

El fRepiteCadena siempre lo pongo al final porque en caso contrario da error (y ciertamente no me acuerdo cómo lo averigüé)

Espero que pronto podamos tener las fórmulas dinámicas en V7, o algo mejor ;-)