oct 7

Cálculos acumulados en la cabecera de página

Posted in ejercicios, foro, utilidades

Se dice, se comenta, se rumorea ….

Que no es posible incluir los acumulados de los importes de una página, al inicio de la página siguiente.

Eso es, lo que pretendemos es incluir un “Suma y sigue …” al inicio de cada página del informe, y surgen un problema en el calculo de los acumulados en las variables que utilizamos para la impresión de dichos importes.

A raíz de aqui, buscamos una solución sencilla que nos resuelva el problema:

y parte de esa solución esta en duplicar las variables y los calculos necesarios para los acumulados.

Asi es, puesto que tenemos dos variables PIE_DEB (para el acumulado del debe) y PIE_HAB (para el acumulado del haber) y que son las que utilizamos en el pie de página del informes (y estos cálculos los hace correctamente).

He decidido que necesitariamos otras 2 variables (aunque en la imagen solo se ve una de ellas) CAB_DEB (para el suma y sigue del Debe) y CAB_HAB (para el suma y sigue del Haber).

Y hasta aqui, no hay diferencias sustanciales en nuestro informe, salvo por el hecho de usar 4 variables en vez de 2.

El informe ya tenia 2 “Cálculos” PIE_DEB y PIE_HAB para realizar las operaciones con las variables PIE_DEB y PIE_HAB respectivamente, y las propiedades en cada uno de ellos para sumar en Modo: Acumulado y en Fórmula, el importe (#IMP_DEBE o #IMP_HABER) de cada una de las columnas.

Con esto, ya conseguimos que aparezcan las sumas en el pie de página correctamente …

Ahora, falta realizar los Cáculos para que aparezca el “Suma y sigue …” en la cabecera de cada página, antes de la primera línea de la página.

Y para eso creamos 2 nuevos Cálculos, uno llamado CAB_DEB y otro llamado CAB_HAB y en ellos usamos las propiedades Modo: Absoluto y en Fórmula, indicamos la diferencia entre el importe de la variable acumulada del pie de pagina anterior y el importe de la linea: PIE_DEB-#IMP_DEBE para la primera columna y PIE_HAB-#IMP_HABER para la segunda.

Y despues de realizar las pruebas con un informe con varias páginas de registros, he podido comprobar que funciona correctamente.

PDF Printer    Enviar artículo en formato PDF   
comments: 0 »
may 3

Proceso de importación

Posted in foro, utilidades

Como solución al problema planteado por Velavisual en este hilo:

Emulando importación y exportación de listas virtuales

He preferido realizar las pruebas partiendo de cero, por varios motivos:

  • Un formulario con demasiados eventos y dificil de localizar el problema
  • El uso de cestas locales y procesos en 3 plano, son dificiles de procesar
  • La falta de datos para revisar el buen funcionamiento de los objetos
  • Y la poca disponibilidad de tiempo para solucionarlo

Asi que me he puesto a realizar el ejemplo y el resultado es este:

1. He creado un fichero de texto similar al que se indica en el hilo del foro:

2. He creado un formulario sin origen para ejecutar la importacion y mostrar el resultado

3, He creado un objeto CESTA para almacenar los registros que se muestran en la rejilla

4. He creado el proceso que carga la rejilla desde el control objeto del formulario

5. En el formulario he incluido las propiedades del control objeto , ejecutar el proceso que retorna el contenido de la cesta y mostrar la rejilla con el resultado

6. He creado un evento en el formulario para IMPORTAR el fichero de texto y he asociado el evento a un boton llamado IMPORTAR

En el proceso de importacion no he usado la busqueda, para evitar crear otro objeto, y lo he cambiado por Cargar Lista, pero deberia funcionar exactamente igual en cualquiera de los casos.

7. He creado una accion que ejecuta y visualiza el formulario

8. He ejecutado la aplicacion y al abrir el formulario aparece una rejilla vacia, luego pulso el boton IMPORTAR, y la rejilla se muestra con los registros que hay en la lista del archivo de texto.

Las pruebas las he realizado con una tabla de facturas para comprobar que los registros del fichero de texto se corresponderian con un codigo de registro en la tabla.

Despues de esto, todo ha funcionado correctamente, ahora solo tienes que revisar los pasos y detectar el error.

PDF Printer    Enviar artículo en formato PDF   
comments: 2 »
dic 23

Procesar varios registros de una rejilla

Hace unos dias, en un artículo anterior, en el que comparabamos V6 y V7, no para criticar, sino para ver las diferentes formas de llegar a los mismos resultados en determinadas operaciones:

Encuentra las diferencias entre V6 y V7

Prometi a Miguel un ejemplo para ver como se realizaba un ejemplo para procesar varios elementos de una rejilla marcandolos con check como el de la imagen.

En V6 este ejemplo se podria realizar de 2 formas:

  1. Con una rejilla multiseleccion y una toolbar, creando un proceso con origen LISTA y recorriendo los registros para procesarlos y ejecutando el proceso desde la toolbar.
  2. Con una rejilla incrustada en un formulario y un boton que ejecuta el proceso para recorrer los rejistros seleccionados.

Como la misión no es desarrollar el ejemplo en V6, vamos a continuar y a ver como realizarlo en V7.

Y en V7 necesitariamos lo siguiente:

Un formulario, en el ejemplo hemos incluido 2 controles objeto, que muestran 2 rejillas de 2 tablas.

El ejercicio es conseguir procesar varios registros de la rejilla inferior y procesarlos para subirlos a la rejilla superior, pulsando el boton “INCLUIR”.

Para ello necesitamos crear un evento en el formulario como el siguiente:

En el se procesan los registros seleccionados de la rejilla inferior y recorremos la lista, realizando las operaciones necesarias en cada uno. Al finalizar el proceso ejecutamos las sentencias de “Interfaz: Recalcular control()” , para asegurarnos de que las rejillas se actualizan correctamente para reflejar los cambios.

Ahora ya solo nos queda incluir el boton y asignarle el evento anterior

Un ejercicio muy sencillo, cuando se sabe, claro.

PDF    Enviar artículo en formato PDF   
comments: 7 »
dic 21

Paginador de registros

En el articulo anterior, proponiamos una solución a un problema concreto, como siempre, una solucion sencilla a un problema aparentemente complejo, ¿Quitar o no quitar los punteros sigular de plural?

Pues bien, como no debemos quitar nada, porque “Quitar” es sinonimo de “Robar” y eso no esta bien, he decidido que para este ejemplo la frase apropiada es “¡Divide y venceras!”

Ademas, esta división tambien nos reporta beneficios, y no solo en tiempo, sino también economicos (cuando las tarifas de moviles se calculan por volumen de transmisión de datos), aunque el mejor, es la menor carga soportarda por el servidor, y que se traduce en beneficio para el resto de usuarios que trabajan simultaneamente. Ya sabeis, si mis operaciones no saturan la capacidad de vServer, este estará disponible para realizar otras operaciones en menos tiempo y de forma más eficiente.

Basicamente, cuando programamos mal, nos damos cuenta porque la consulta o tarea que esta realizando el servidor es excesivamente lenta y debemos mejorarla para ganar esa velocidad que nos falta. Pero cuando un proceso funciona aparentemente bien, pocas veces intentamos mejorarlo simplemente para quitar carga al servidor y mejorar las tareas de los demas.

Basandonos en esto, voy a explicar como realizar un paginador, que nos permita ver los registros de una tabla (con un volumen de datos elevado).

¿Quien ha pensado alguna vez en hacer una web  mostrando enormes volumenes de datos sin utilizar paginadores?

La respuesta es sencilla, en internet, son tan habituales que no hacerlo seria una excepción.

Y sin embargo, ¿porque? cuando mostramos una rejilla con vClient, nadie piensa en poner un paginador.

Sera porque la respuesta es rapida y no tenemos necesidad, y nos da igual.

En cualquier caso, aqui dejo el ejemplo, y para realizarlo vamos a necesitar los siguientes objetos:

  • una variable global, una para saber el numero de pagina actual
  • otra variable global, para saber el numero de registros a mostrar en cada pagina
  • una busqueda, para mostrar los registros de la tabla, en nuestro ejemplo, sera una busqueda por el indice ID completo, que retorne todos los registros.
  • un proceso para ejecutar la busqueda y retornar la lista de registros
  • una rejilla para mostrar el resultado
  • un formulario, con un control objeto para ejecutar el proceso y mostrar la rejilla y sobre todo, con algunos botones y eventos para controlar nuestro paginador, que es a fin de cuentas, el ejercicio que nos proponemos aqui.

Empecemos pues,

Aqui esta el resultado de nuestro formulario con la rejilla y el paginador, y ahora los vamos a desmenuzar para ver todos sus componentes.

En este momento, necesitaras crear una rejilla de la tabla para la que vas a realizar el ejercicio, y sobre el formulario, como puedes ver, aparece un control objeto que es donde se muestra la rejilla.

El control objeto ejecuta un proceso para retornar la rejilla. Este proceso se encarga de ejecutar la búsqueda y seleccionar los registros a visualizar dependiendo de la página activa en cada momento.

En este punto, si aún no has creado las variables globales, deberias crearlas para usarlas en el proceso, y recuerda que deben ser numéricas. Necesitas una variable global llamada $PAGINA_ACT, para saber en que página nos encontramos y otra llamada $PAGINADOR para saber el nº de registros a mostrar en cada página.

La búsqueda que vamos a definir no es nada compleja. Solo una simple búsqueda por ID con todos los registros de la tabla.

Ahora que yatenemos todos los objetos necesarios para realizar el ejercicio, ha llegado el momento de crear los Eventos del formulario, y el primer evento que vamos a ver es el de inicio del formulario. En este evento le vamos a indicar a las variables globales, los valores por defecto, página actual = 1 y el nº de registros que queremos visualizar en cada página.

Ahora, crea una conexión de evento y le asocias el evento creado, para que el evento se ejecute al inicar el formulario.

Seguimos creando el evento para movernos a la primera pagina y es muy similar al anterior, unicamente tenemos que refrescar el control objeto al finalizar el evento para actualizar nuevamente la rejilla.

Ahora veamos el evento para movernos a la página anterior, solo debemos comprobar si la página actual es > 1 y restar 1 a la variable global.

Ahora que ya tenemos los eventos, solo queda ir a las propiedades de los botones y asociarles su evento correspondiente a cada uno, mediante la propiedad “Ejecutar evento”.

El artículo esta incompleto, solo hemos visto los eventos para movernos a la “Primera página” y para ir a la “Página anterior“, pero con estos ejemplos, ya no deberia resultar dificil crear otros 2 eventos para ir a la “Página siguiente” y a la “Ultima página“, asi pues, consideralo parte del ejercicio y terminalo tú mismo.

En realidad, a pesar de todo este rollo que he metido, se tarda menos en realizar el ejercicio completo que en escribir el articulo.

PDF Printer    Enviar artículo en formato PDF   
comments: 15 »
dic 17

Nuevos servicios del blog

Posted in ideas, utilidades

Agradecemos todas aquellas peticiones que nos sirven para mejorar el servicio que intentamos prestar a la comunidad, y las tenemos todas en cuenta, y dicho esto, comunicampos algunos cambios que hemos efectuado en el blog con la unica intención de facilitar las siguientes tareas:

  • Al final de cada articulo y justo antes de los comentarios, hemos instalado nuevas opciones para facilitar la descarga de los articulos en PDF y el envio de los mismoa a una cuenta de eMail. A partir de ahora, podras guardar en tu equipo los articulos que sean de tú interés para poder leerlos cuando no tengas conexión.
  • También y para aquellos que nos solicitan la lectura del blog desde el móvil (si que estais pillados, :D ),  hemos activado un nuevo servicio precisamente para facilitar la lectura desde el iPhone, pero manteniendo nuestro estilo actual para aquellos que prefieren leernos desde su escritorio tradicional.

Otras peticiones, como el uso de etiquetas, se estan valorando pero creo que, más interesante que el propio uso de etiquetas para los articulos es el propio buscador, y es que, con el buscador, puedes localizar cualquier articulo publicado y por cualquiera de las palabras que aparecen en el texto del articulo.

De todas formas podeis dejar vuestras opiniones, pero personalmente no suelo usar las “nubes de etiquetas”, porque simplemente, me cuesta mas encontrar la palabra que busco entre todas las etiquetas, que escribir las palabras en el buscador. Ademas eso nos limita a que mediante la nube de etiquetas, solo encontrareis el articulo deseado si he realizado el etiquetado adecuadamente, lo que obliga a hacer uso de un excesivo numero de palabras para etiquetar y de elegir correctamente las palabras. Lo dicho, complicado tanto para vosotros como para mi.

Mi voto particular es por el buscador pero si lo considerais útil, usare las etiquetas también.

Y sobre todo, muy agradecido, porque este interes mostrado por mejorar este blog, solo puede significar una cosa, que os gusta leerme, aunque no siempre os guste lo que digo, y eso, a mi tambien me gusta, asi que, todos contentos. :)

PDF    Enviar artículo en formato PDF   
comments: 5 »
nov 15

¿Tienes problemas con el control de licencias?

Posted in aplicaciones, utilidades, v7

Uno de los problemas de la actual v7.4.1 es, que cada instancia, cada aplicacion que ejecutamos con vClient, consume una licencia, incluso cuando estas se ejecutan en el mismo equipo y por el mismo usuario.

En A.S.C. hemos creado varias aplicaciones como:

Aplicación de cine (para cinefilos)

De Cine

Aplicación de flota (control de vehiculos)

Flota (by A.S.C.)

Aplicación de gimnasios

Gimnasios

Aplicación de logger (log de usuarios)

Log de usuarios

Aplicación de entities (entidades y basicos de dirección)

Modulos de  entidades

Aplicación de registro de documentos

Registro de documentos

Pero si ejecutamos todas estas aplicaciones simultaneamente en un mismo equipo con vClient o vWebClient, tenemos un problema importante, ¡estamos consumiendo 6 licencias!

Y claro, llega un momento en que intentamos abrir una aplicacion y nos aparece un sonoro error como este:

Error pro falta de licencias disponibles

Y claro, es un problema, pero tiene una solución muy sencilla:

Basta con crear un nuevo proyecto y heredar a todos los proyectos anteriores, creando un menu que nos da acceso al resto de aplicaciones.

Menu de acceso a todos los modulos

De esta forma, podemos tener acceso a todas las aplicaciones consuminedo una única licencia, pero claro, esto no es una solución al problema de las licencias consumidas por las diferentes instancias, tal y como se planteaba en este hilo del foro: ejecucion-simultanea-de-aplicaciones

Y es que, para que las instancias tampoco aumenten el consumo de licencias, Velneo deberia proveernos de una solución para poder cambiar de instancia directamente desde una aplicación en ejecución.

Espero que os haya servido para algo.

PDF Download    Enviar artículo en formato PDF   
comments: 4 »
oct 21

Te atreves a generar un Word

Ahora, visto esto, y pensando un poquito,

¿que pasaria si escribo un documento en Html y lo guardo con la extension “.DOC”?

<html>

<head>

<title>Ejemplo para generar un documento de Word</title>

… sigue tu con el Html, que me da verguenza

</head>

<body>

… escribe aqui el contenido del cuerpo

</body>

</html>

¿te atreves a probarlo?

si eres atrevido, cuentame el resultado

lo peor que podria pasar, seria que el universo se colapsara y todo volveria al comienzo, un nuevo “Big Bang!”, y se crearia un nuevo universo, sin Politicos, sin Clero, sin Abogados, sin Informaticos, vamos una “utopia” ;)

PDF Download    Enviar artículo en formato PDF   
comments: 3 »
oct 21

Generar hojas de calculo Excel sin DLL

Se trata de un pequeño truco, y lo importante no es “el que” hace, sino “el como“.

Se trata de generar una hoja de calculo de Excel, pero como se indica en el titulo, lo vamos a generar desde cualquiera de las versiones de Velneo, incluida V7, por supuesto.

Pero antes de continuar, vamos a probar si funciona o no,

Copia este texto:

<table>
<tr>
<td>fila-1-col-1</td>
<td>fila-1-col-2</td>
<td>fila-1-col-3</td>
<td>fila-1-col-4</td>
<td>fila-1-col-5</td>
</tr>
<tr>
<td>fila-2-col-1</td>
<td>fila-2-col-2</td>
<td>fila-2-col-3</td>
<td>fila-2-col-4</td>
<td>fila-2-col-5</td>
</tr>
<tr>
<td>fila-3-col-1</td>
<td>fila-3-col-2</td>
<td>fila-3-col-3</td>
<td>fila-3-col-4</td>
<td>fila-3-col-5</td>
</tr>
</table>

Como podras comprobar, es texto HTML, puro y duro, y corresponde a una tabla

Copialo en el Bloc de notas, ahora guarda el archivo con extension XLS, y despues prueba a abrir el archivo con excel.

Sorprendido, pues eso,

Ahora como lo hacemos en V6, V7, etc,

Pues sencillo, solo necesitas un proceso que te genere el texto Html correspondiente a la tabla,

luego guardas el archivo:

Fichero abrir “lectura/escritura”

Fichero “guardar linea”: texto-html

y no olvides que el archivo debes cuardarlo con extension XLS, propia de Excel

ya ta

more easy is impossibol
no DLL, no complicate, nodin de nodin,

tengo que mejorar este Manche-Inglis, :D

la vida ya es bastante complicada desde que existen los “informaticos”, hagamosla un poco mas sencilla, “simple is beautifull”

PDF Download    Enviar artículo en formato PDF   
comments: 6 »
sep 30

Mejorar el rendimiento en ejecución

Posted in analisis, foro, ideas, utilidades

Estas ultimas semanas ha habido mucho ambiente con algunos temas del foro, y pese a que me gustaria haber participado mas, no he podido. Ya sabeis, ¡me he pasado mucho tiempo en la cocina!, :)

Y al margen de suplicas y quejas, el trasfondo de todo, es que muchas veces hacemos las cosas mal, y la primera reaccion es intentar culpar a los demas.

Como no he tenido fisicamente tiempo, no he podido realizar pruebas de rendimiento para concretar esta informacion con mas detalle, pero si hay conceptos que deberiamos tener muy claros para mejorar la respuesta de las aplicaciones.

Pero, igual que antes he tratado de defender a Velneo que no tiene la culpa de nuestros errores como programadores, tambien voy a decir que si tiene la culpa de no publicar un articulo donde se haga hincapie en estos aspectos, y se deje claro que opciones son las mas recomendables, en segun que situaciones.

Y es que, cuando nosotros trabajamos bien, y realizamos desarrollos ejemplares, los clientes estan contentos y hablan bien de Velneo y tambien de nosotros, pero cuando no es asi, el cliente termina cansado, descontento y la culpa, no suele ir al programador, porque el programador trata de liberarse del problema culpando a la herramienta.

Sea por una razon o por otra, lo que si esta claro, es que deberiamos tener una serie de Test comparativos de respuesta en distintas situaciones:

Tenemos o deberiamos tener claro que:

  1. un proceso en 1 plano (ejecutado en la maquina del cliente), es mas lento que un proceso en 3 plano (ejecutado en el servidor). Pero hay veces que no podemos ejecutar el proceso en 3 plano, p.e. cuando tenemos que mostrar mensajes en el interfaz del cliente, o en el proceso debe interactuar el usuario de alguna forma.
  2. una busqueda en 1 plano (en el cliente), es mas lenta que si ejecutamos la misma busqueda en 3 plano (en el servidor).
  3. una lupa es mucho mas lenta siempre que Cargar lista y que una Busqueda por un indice, pero si no tenemos mas remedio, al menos, deberiamos ejecutar la lupa en 3 plano (tutor de busquedas y lupas en 3 plano).
  4. mostrar una rejilla de una tabla siempre es mas rapido si no aparecen campos Formula en el contenido de las columnas, es mucho mejor mostrar campos numericos o alfabeticos con contenido inicial.
  5. mostrar campos en una rejilla usando “punteros singular de plural por indice“, penaliza el rendimiento con grandes cantidades de registros (incluido el dia 15-dic-2010)
  6. un campo numerico con una formula en su contenido inicial es mucho mas eficiente que un campo formula, sobre todo si este debe aparecer en rejillas o informes con calculos masivos.

Pero hay otros conceptos que no quedan tan claros, ¿que es mas rapido?, o ¿como afecta al servidor? en las siguientes comparaciones:

  1. Un proceso con Cargar lista, o un proceso que lanza una Busqueda, si tenemos en cuenta que en ambos casos se utilizaria el mismo indice o grupo de indices, sabiendo que los 2 se ejecutarian en el mismo plano. Que diferencias habria si ejecutasemos en 1 plano y que diferencias habria si ejecutasemos en 3 plano, p.e.
  2. Del mismo modo, y bajo el mismo plano de ejecucion, cuando las circunstancias lo permitan, que se debe usar, el Tubo “de Lista” o “de Ficha“.
  3. En una rejilla, el rendimiento de Suma acumulada de toda la columna, deberia ser igual que usar la suma acumulada de un campo, si indicamos como campo esa misma columna y no indicamos condiciones. Pero, ¿es asi?
  4. Cuanto tiempo puede permanecer en ejecucion un proceso en el servidor antes de que sea interrumpido y las transacciones deshechas.
  5. Si tenemos que hacer un proceso de carga masiva de datos, creando registros nuevos, que es mas rapido, el Tubo de ficha o Crear nueva ficha en memoria + Alta de ficha

Seguro que algo se queda en el tintero pero si sois tan amables, ire actualizando el “post” a medida que se aporten nuevas cuestiones.

Visto esto, no se trata de comparar rendimientos de Velneo V7 con otras herramientas, ¡NO!, no nos interesa saber que V7 es mejor o peor que SQL server o que Oracle.

Lo que realmente nos interesa es como aprovechar el rendimiento del servidor al maximo, eso ¡SI!

¡¡¡ queremos programar bien, y optener el mejor rendimiento de la base de datos !!! y para ello necesitamos conocer esos pequeños detalles que marcan la diferencia entre un “funcionamiento correcto” y un “funcionamiento optimo

Create PDF    Enviar artículo en formato PDF   
comments: 4 »
sep 29

Variables de tipo Array en 3D

Posted in ideas, utilidades

Como os dije hace poco tiempo, ese mismo dia que iniciamos la gran comilona, :D , es posible usar variables de tipo Array en 3D, y hoy vamos a desvelar como.

Para empezar dire que hay 2 metodos que se me ocurren ahora mismo, pero eso no significa que sean los unicos, asi que os animo a comentar si teneis nuevas ideas:

  1. Como he dicho se me ocurren 2 formas, y esta primera es la mas sencilla. Para ponerla en practica solo necesitas buscar unas gafas 3D de las que usaste para ver la peli de Avatar, y veras como tu Array empieza a salir de la pantalla como si te fuera a comer, ;)
  2. Y la segunda, es algo mas complicado, pero no te comera. Para este segundo metodo, necesitas unicamente una “Tabla”, si tan sencillo como eso, ahora te lo explico con mas detalle.

Vamos a crear una tabla, y unicamente necesitamos 4 campos:

  • #DIM_1 , este campo debe ser numerico y se corresponde con el identificador que usaremos para la primera dimension del Array
  • #DIM_2 , este campo debe ser numerico y se corresponde con el identificador que usaremos para la segunda dimension del Array
  • #DIM_3 , este campo debe ser numerico y se corresponde con el identificador que usaremos para la tercera dimension del Array
  • #CONTENIDO, es un campo alfabetico o numerico, dependiendo de cual sea el contenido que almacenaremos en el Array

Ya tenemos la tabla, ahora crearemos 3 indices, uno para cada uno de los campos #DIM_? y esto nos facilitara la labor de busqueda de valores en el array.

De esta forma, con una busqueda compleja, que usa los 3 indices podemos buscar cualquier valor, del array y en cualquiera de las dimensiones.

Para crear el array, solo necesitamos un proceso con 3 bucles anidados que permiten crear todos los valores,

¿Crees que es posible viajar en el tiempo?

Pues si eres de los que creen, estas de suerte, toma nota:

Crea un nuevo campo #DIM_4 en la tabla, crea un nuevo indice para ese campo, modifica la busqueda para incluir el nuevo indice en ella, y modifica los procesos para crear el array anidando un 4 bucle, y realiza estos cambios en todos los demas objetos que sean necesarios, y veras como el milagro se hace realidad y entras en la 4ª Dimension :D (el tiempo)

No se si es lo que esperabas, pero es una solucion a un problema concreto.

Quiza esperabas que de verdad, los Arrays podian ser en 3D, pero piensalo bien, una tabla en memoria definida con esta estructura y un Array “Local”, en que se diferencian. Y si necesitas que el Array sea “Global” o “Publico”, pues solo tienes que hacerlo en una Tabla con persistencia en disco.

Este truco es valido para V7 y tambien para su hermana (v6.x) ;)

Si estas decepcionado, lo siento, … para hacer milagros me estoy entrenando.

Create PDF    Enviar artículo en formato PDF   
comments: 6 »