Una de las actividades más habituales con la que nos encontramos los desarrolladores es la importación de datos. Tanto por razones operativas de la aplicación, como por la migración de aplicaciones hacia nuevas versiones. En este artículo aprenderás a desarrollar la importación automática de datos con Velneo.
En el desarrollo de aplicaciones a medida la migración de datos es un capítulo importante y que debemos resolver desde el primer momento para contar con información real tanto para hacer pruebas como para preparar la migración definitiva el día de la puesta en producción.
Gracias al uso del API para JavaScript, en Velneo, es realmente sencillo y automático el proceso de migración de información de datos desde otros sistemas hacia Velneo, a través de ficheros de texto.
En esta píldora vamos a ver los realmente sencillo y práctico que puede ser realizar la importación de datos en tablas Velneo a través de un proceso automatizado JavaScript.
1º Un proceso principal Velneo que dirige la importación
Para conseguir preparar una importación automática de datos en múltiples tablas Velneo, lo primero que debemos hacer es preparar un proceso Velneo que se encargará de solicitar el directorio de importación, donde encontraremos los diferentes ficheros que vamos a procesar para proceder a la importación de sus datos. En la siguiente imagen podemos ver el contenido de este proceso Velneo estándar para la importación.
2º Un formulario para solicitar la senda de importación
Como vemos en la imagen, lo primero que hace es solicitar mediante un formulario la senda del directorio donde encontraremos todos los ficheros ASCII a importar.
Este formulario será el que utilizará el usuario para seleccionar el directorio de importación donde previamente a la importación habremos almacenado los ficheros que contienen los datos a importar. Contiene un control de tipo selección de directorio para la localización y selección del directorio de disco donde estarán almacenados los ficheros a importar.
Una vez seleccionado el directorio donde encontraremos los ficheros a procesar para su importación. El proceso Velneo se encarga de ejecutar el proceso JavaScript. En la imagen vemos que el proceso se ejecuta mediante los comandos de manejador de objeto y disparar objeto. El proceso se ejecuta en primer plano (cliente), pero se podría optimizar ejecutándolo en tercer plano (servidor), en este último caso los ficheros a importar deberían estar almacenados en una subcarpeta del servidor y, probablemente en lugar de seleccionar el usuario final la senda del directorio de importación, podría ser un directorio configurado.
Podemos observar que el proceso Velneo pasa valores al proceso JavaScript mediante el uso de variables locales, en concreto le pasa 2 valores: SENDA (senda del directorio donde se encuentran los ficheros a importar) y SEPARADOR, variable donde identificamos el carácter de separación entre valores de campos. Por defecto se asume el valor de separación de campos «\t» (el tabulador), salvo que le pasemos un caracter específico en la variable SEPARADOR.
3º Un proceso JavaScript que se encargará de la importación
// --------------------------------------------------------------------------------
// Devuelve el idRef de una tabla a partir de su Id
// --------------------------------------------------------------------------------
var tablaIdRef = function ( tablaId )
{
// ----------------------------
// Se lee el proyecto principal
// ----------------------------
var proyecto = theApp.mainProjectInfo();
// ----------------------------------------------------------------
// Se repasan todas las tablas buscando la recibida en el parámetro
// ----------------------------------------------------------------
for ( var numTabla = 0; numTabla < proyecto.allTableCount(); numTabla++ )
{
if ( proyecto.allTableInfo( numTabla ).id() == tablaId )
{
return proyecto.allTableInfo( numTabla ).idRef();
};
};
// ---------------------------------------
// Si no se ha encontrado se devuelve null
// ---------------------------------------
return null;
};
// --------------------------------------------------------------------------------
// Importación de registros en una tabla a partir los datos contenidos en un fichero ASCII
// --------------------------------------------------------------------------------
importClass("VDir");
importClass("VFile");
importClass("VTextFile");
// -------------------------
// Se recorre el direoctorio
// -------------------------
var dir = new VDir();
dir.cd( theRoot.varToString( "SENDA" ) );
dir.load();
// ---------------------------------------
// Se recorren los ficheros del directorio
// ---------------------------------------
for ( var numFichero = 0; numFichero < dir.count(); numFichero++ )
{
// ---------------------------------------------------------------------
// Se lee el fichero del directorio y se prepara su nombre sin extensión
// ---------------------------------------------------------------------
var fichero = dir.entryAt( numFichero );
var ficheroNombre = fichero.baseName();
// ---------------------------------------------------------
// Se prepara el idRef de la tabla destino de la importación
// ---------------------------------------------------------
var ficheroIdRef = tablaIdRef( ficheroNombre );
var registro = new VRegister( theRoot );
if ( registro.setTable( ficheroIdRef ) )
{
// -------------------------------------------
// Se prepara el valor del separador de campos
// -------------------------------------------
var separador = ( theRoot.varToString( "SEPARADOR" ) != null ) ? theRoot.varToString( "SEPARADOR" ) : "\t";
// --------------------------------
// Se abre transacción si no existe
// --------------------------------
bTransCurso = theRoot.existTrans();
if ( bTransCurso == false )
{
bTransNueva = theRoot.beginTrans( "Importando: " + fichero );
};
if ( bTransCurso || bTransNueva )
{
// ------------------------------------------
// Se abre el fichero en modo de sólo lectura
// ------------------------------------------
var ficheroTxt = new VTextFile( fichero.filePath() );
if ( ficheroTxt.open( VFile.OpenModeReadOnly ) )
{
// ------------------------------------------------------------------------------
// Se leen los nombres de los campos en la primera línea y se guardan en un array
// ------------------------------------------------------------------------------
var linea = ficheroTxt.readLine();
var aCampos = linea.split( separador );
// ----------------------------------------------------------
// Recorremos el fichero línea a línea guardando su contenido
// ----------------------------------------------------------
var aValores = new Array();
var nNumRegistro = 0;
theRoot.initProgressBar();
theRoot.setProgress( 100 );
while ( ficheroTxt.atEnd() == false )
{
// -----------------------------------------
// Leer la línea y los valores de los campos
// -----------------------------------------
linea = ficheroTxt.readLine();
aValores = linea.split( separador );
for ( var nCampo = 0; nCampo < aValores.length; nCampo++ )
{
registro.setField( aCampos[ nCampo ], aValores[ nCampo ] );
};
registro.addRegister();
// -----------------
// Mostrar el avance
// -----------------
theRoot.setTitle( "Importando registro nº " + nNumRegistro++ + " de la tabla " + ficheroNombre );
};
// --------------------
// Se cierra el fichero
// --------------------
ficheroTxt.close();
theRoot.endProgressBar();
};
// ---------------------------------------------
// Se cierra la transacción si se creó una nueva
// ---------------------------------------------
if ( bTransNueva )
{
theRoot.commitTrans();
};
};
};
};
En la primera función tablaIdRef() podemos observar como a partir del identificador de la tabla destino se devuelve el idRef o identificador completo de la tabla (alias/identificador). Esta función parte del principio de que en nuestra aplicación no existen tablas duplicadas con el mismo identificador (algo que deberíamos evitar siempre). En caso de que hubiese un identificador de tabla repetido, nos devolvería el idRef de la primera tabla encontrada.
Esta función es llamada por el proceso JavaScript principal para calcular el idRef de la tabla destino a partir del identificador de la tabla. El proceso asume que el nombre de la tabla se corresponde con el nombre del fichero en disco (sin la extensión).
Por lo tanto los ficheros a importar deben tener las siguientes características:
- El nombre del fichero a importar deben corresponderse con el identificador de la tabla de destino.
- En la primera línea del fichero deberán aparecer separados (por el carácter de separación) los identificadores de los campos de destino de cada dato/columna.
- El campo código debe tener el identificador ID.
- El campo nombre debe tener el identificador NAME.
- Los campos de tipo fecha deben exportarse en formato ISO AAAA-MM-DD para que se importen correctamente.
¿Cómo implementarlo?
Una vez que hemos visto las piezas, vamos a enlazarlas para implementar esta importación de datos:
- Crear un proceso Velneo, por ejemplo con el nombre IMP_TXT_SEL_DIR, que contenga los comandos que vemos en la primera imagen de este artículo.
- Debes crear un formulario para solicitar al usuario final el directorio de importación, por ejemplo con el identificador IMP_TXT_SEL_DIR.
- En el directorio de scripts crea un fichero JavaScript e incluye el script de JavaScript con la función tablaIdRef y el código que realiza la importación.
- Crea un proceso JavaScript, por ejemplo con el nombre IMP_TXT que tenga asignado como fichero script el creado en el punto anterior.
- Crea una acción, por ejemplo IMP_TXT, que se encargue de ejecutar el proceso Velneo IMP_TXT_SEL_DIR que lanzará el formulario y luego el proceso JavaScript de importación.
Para los amantes de Life is Soft
Te dejo el enlace de descarga de la instalación de la solución importaDatosJS que contiene todos los objetos explicados en esta píldora totalmente operativos para que los pruebes o uses directamente heredándolo en tus aplicaciones.
Por razones de seguridad, el fichero de instalación .vin lo descargarás comprimido en formato zip. Debes descomprimirlo para obtener el fichero con extensión ".vin".
Recuerda que este fichero de instalación está creado con la versión 7.14, por lo que necesitas instalarlo en un vServer que tenga esa versión o una superior.
Asier Amezaga dice
Muchas gracias por compartir!!
jarboleya dice
Gracias Asier.
synetic dice
Gracias Jesús por estas píldoras. Todas muy interesantes, pero esta en concreto es algo que a mi particularmente me sirve y mucho.
Tus píldoras dan siempre en el clavo y es que están pensadas para usar Velneo v7 de manera práctica, en la vida real. Nos soluciona problemas que o bien nos hemos encontrado o nos vamos a encontrar y resueltas de una manera lógica. El título del blog no podía estar mejor puesto.
Agradezco tu esfuerzo y te felicito por tu habilidad para comunicar, haciendo fácil cualquier tarea en v7.
Un saludo
jarboleya dice
Gracias por tu comentario synetic.
Jose Manuel dice
Muchisimas gracias, contigo todo parece mas fácil.
jarboleya dice
Gracias José Manuel.
Ebermuz dice
Gracias Jesús por.ese aporte muy interesante. Trate de instalarlo con el .vin, pero no se descarga la aplicación. Sin embargo programé lo que se encuentra en ésta importación automática de datos, pero no me funcionó.
Deseo bajarme la aplicación.
Saludos
jarboleya dice
Gracias Ebermuz.
jarboleya dice
Hola ebermuz.
Acabo de probar el enlace de descarga y funciona correctamente.
Me acaba de confirmar otro desarrollador que la bajó e instaló sin problemas.
Saludos.
Ebermuz dice
Jesús otras vez molestándote:
La aplicación se baja sin problema, pero al ejecutarla se presenta el mensaje
«Cargando proyecto de aplicación:Importa DatosJS_APP 1.0»
No se carga.
El sistema operativo que uso es : Windows 8
Saludos
jarboleya dice
Hola Ebermuz.
Prueba ahora a descargar el zip.
He vuelto a comprimir el .vin y a subirlo.
Recuerda que una vez descomprimido deberías tener el fichero con la extensión .vin o una carpeta que dentro contenga al archivo.
Recuerda que el archivo está guardado con la versión 7.14 de Velneo V7 por lo que necesitas instalarlo en un servidor que esté en esa versión o superior.
Saludos.
Ebermuz dice
Gracias Jesús
Excelente trabajo. Me funcinó
jarboleya dice
Me alegro de que ya te funcione correctamente.
Lydia dice
Hola, estoy probando este vin y todo este proceso pues me parece un excelente aporte y algo muy necesario sobre todo para los que estamos en v6 proceso de v7.
el problema es que no se usarlo, supongo que seré la única que le pasa pero … no se usarlo. O sea yo genero un txt, con el ID y el nombre. Este txt se llama como el identificador de la tabla de destino, quiero pasar dos campos, ID y Name, en principio intenté que el separador fuera ; pero no hizo nada y ahora lo intento con tabulador pero no hace nada….
¿que hago mal?
Lydia dice
Me respondo a mi misma que no tenia bien la ruta del script.
Muuuy buen aporte, por lo menos a mi me sirve de mucho, ya que estaba con el proceso de paso v6 a v7 con un montón de datos
Muchas gracias
Lydia dice
Buenos días.
Estoy encantada con este post y ya lo probé y está estupendo pero tengo un problemilla, sólo me funciona bien si paso un registro de la tabla.
Cuando quiero pasar 2, no se porqué me da de alta bien el primero, y el segundo me lo da de alta 3 veces.
Esto es lo que escribo en el txt
ID;NAME;CONSELLERIA;ORGANIsMO;
210;;DIRECCION GENERAL DE CARRETERAS;MINISTERIO DE FOMENTO;
310;;oho;Prueba;
Y el separador lo tengo como ;
El resultado es con codigo 210 Direccion general de carreteras… bien
310 oho prueba …bien
311 oho prueba
312 oho prueba
El script no lo toqué, es el que está en el archivo .vin
Muchas gracias
jarboleya dice
Hola Lydia.
Me alegro de que te guste esta utilidad.
Lo más probable es que tengas al final del archivos líneas en blanco lo que produce que se intenten importar, y como no tienen información se sigue repitiendo la del último. Aunque se podría mejorar el script para que no haga esto, lo mejor es que revises tu archivo txt y dejes que finalice justo después del ; de la última línea sin que tenga ninguna línea adicional.
Juan Figueroa dice
Gracias, Jesús. Funcionó a la primera.
Majestuoso. NO digo más
jarboleya dice
Gracias Juan.
Es un placer tenerte por aquí y más aún saber que te ha sido útil este código.
Un abrazo Maestro.
Juan Figueroa dice
Estimado Jesús,
Estoy usando muy satisfactoriamente tu importación de txt delimitado.
y he encontrado un problema, si puede llamarse así:
no me muestra el avance de la importación ni la Barra de progreso que se mencionan en el scripot desde la línea 98 a 104
………………………………
// Mostrar el avance
theRoot.setTitle( “Importando registro nº ” + nNumRegistro++ + ” de la tabla ” + ficheroNombre );
};
// Se cierra el fichero
ficheroTxt.close();
theRoot.endProgressBar();
¿Cómo podría hacer para que se mostrase esta información?
Gracias, Jesús
Un abrazo
Responder