SSIS – Ejemplo de Package con origen de datos Excel dinámicos

Estimados amigos lectores, en éste, mi primer post sobre SSIS, quiero presentarles un ejemplo que seguramente les será muy útil si están dando sus primeros pasos con esta herramienta de Microsoft. Intentaré explicar con un ejemplo sencillo como crear un Package de SSIS (SQL Server Integration Services) para importar los datos de todos los documentos XLS (MS Excel) que se encuentran en un directorio particular, procesarlos y luego enviar los datos obtenidos y procesados a una tabla de una Base de datos de SQL Server. En post posteriores iré ampliando este Package, agregando más transformaciones para complejizarlo y ajustarlo más a la realidad de la vida cotidiana, pero para empezar, creo que este ejemplo estará más que bien. Bueno, arranquemos…
El ejemplo constará de 3 partes con la finalidad de simplificar su comprensión. Estas son:

1. Crear Orígenes y destino de Datos
2. Creación del Package sin iteración
3. Creación de iteración para el Package

1. Crear Orígenes y destino de Datos
Lo primero que debemos hacer es contar con 3 archivos XLS (Excel) en una carpeta de nuestra PC. Les sugiero que utilicen los mismos nombres y path que yo para evitar problemas. Si miran la imagen de abajo, verán el path y los nombres de archivos. Por ejemplo:
C:\SSIS\Alumnos\Alumnos ddmmaaaa.xls
Respetar el formato del nombre será importante para futuros post de ampliación del ejemplo. Fíjense que lo único que difiere en ese nombre es el año.


La estructura (columnas) del los 3 archivos debe ser igual, no así los datos de los alumnos, los que sólo deben ser diferentes los valores de la columna Curso en cada uno de los archivos. Por ejemplo, el Alumno Baresi Mateo en el archivo Alumnos 28022006.xls tendrá en la Columna “Curso” el valor 1, en el archivo Alumnos 28022007.xls el valor 2, y en el archivo Alumnos 28022008.xls el valor 3. La estructura del XLS debe ser la siguiente:


La tabla donde se almacenarán los datos obtenidos y transformados para este ejemplo se encuentra en la base de datos Examples y se llama TablaAlumnos (Tener presente que tanto la BD como la tabla han sido creadas para este ejemplo). La estructura de la tabla sería la siguiente:


Donde RowID será la clave principal y autoincremetal.

2. Creación del Package sin iteración
Una vez que ya contamos con los archivos de “origen” de datos y la tabla de “destino” creada procedemos a abrir el SQL Server Business Intelligence Development Studio para comenzar a crear el proceso. Creamos un nuevo Proyecto de Integration Services, le ponemos de nombre IMPORT_XLS y lo guardamos dentro de la carpeta SSIS que creamos con anterioridad.


Luego de creado el proyecto, se nos abre en el IDE del VS el paquete por defecto, cuyo nombre es Package.dtsx. Allí es donde debemos apelar a nuestra creatividad y comenzar a “dibujar” nuestro proceso!!!
Lo primero que vamos a hacer es crear las conexiones de origen y destino para los datos. Para crear el origen de datos de archivos Excel nos situamos en el Administrador de Conexiones, allí hacemos lo siguiente:
- click derecho en la superficie, seleccionamos la opción New Connection…
- Seleccionamos la opción EXCEL, y hacemos clic en Add….
- Luego hacemos click en el botón Browse y seleccionamos el archivo deseado, en nuestro caso seleccionaremos el archivo Alumnos 28022006.xls ubicado en C:\SSIS\Alumnos
- Dejamos chequeada la casilla First row has column name, ya que nuestras columnas tienen encabezado.
- Hacemos click en el botón OK y ya habremos creado el “Origen” de datos. Se llamará Excel connection Manager.


Para crear el “Destino” de datos haremos lo siguiente:
- click derecho en la superficie, seleccionamos la opción New OLE DB Connection…
- en la ventana de configuración hacemos click en la opción New… para crear una nueva conexión a la BD.
- En la nueva ventana de Connection Manager debemos especificar los datos de nuestra conexión. Para nuestro ejemplo, los datos pueden observarse en la figura siguiente.

- Damos Ok en las dos ventanas y ya tendremos creada también la conexión de destino hacia la base de datos llamada localhost.Examples.

Ahora procederemos a la creación del Package propiamente. Lo primero que haremos es insertar en el Control Flow (Flujo de Control) un nuevo Data Flow task (Tarea de Flujo de Datos), arrastrando dicho objeto hacia la superficie que aún se encuentra vacía.
Posteriormente, hacemos doble click sobre el Data Flow task para poder agregarle la funcionalidad adecuada. Una vez dentro del Data Flow, agregamos una Excel Source, ubicada en la sección Data Flow Sources de la Toolbox arrastrándola a la superficie. Hacemos click derecho sobre el elemento agregado, elegimos la opción Edit… Allí nos aseguramos que la conexión seleccionada sea la que creamos con anterioridad y luego sólo seleccionamos la hoja del fichero XLS que contiene la información (en nuestro caso seleccionamos Hoja1$)


Lo siguiente que haremos es agregar el destino de datos, para ello arrastraremos el componente OLE DB Destination desde la Sección Data Flow destination. Una vez insertado en el Package, nos situamos sobre el Excel Source y arrastramos la flecha verde hasta el OLE DB Destination que acabamos de insertar.



Lo siguiente que debemos hacer es Editar el OLE DB Destination y donde debemos en la opción Connection Manager nos aseguramos que la conexión sea la que creamos con anterioridad (localhost.Examples) y seleccionamos la TablaAlumnos. Luego debemos ir a la opción Mappings para relacionar cada una de las columnas de Excel con sus respectivos campos en TablaAlumnos.



Es muy posible que les surjan errores de compilación debido a que no se pueden mapear campos con diferentes tipos de datos. En nuestro caso, los errores surgen en algunos campos. Lo que debemos hacer es fijarnos en el OLEDB Destination los tipos de datos que corresponden a cada campo (posicionando el cursor unos segundos encima del mismo) y luego agregar un nuevo componente para realizar el cambio en el tipo de datos.

El componente a agregar es Derived Column, con el cual podremos crear columnas derivadas con el nuevo tipo de dato. El Data Flow debe quedar como se muestra en la figura siguiente.



Luego debemos Editar el componente Derived Column insertado, agregando columnas derivadas para cada uno de los campos que requieren transformación, para ello vea la siguiente figura y observe que la propiedad Length de de la columna derivada “DerivedDivision” es 1. Eso es porque puede ir solo un carácter en este caso.



Una vez ingresadas estas las columnas, damos click en OK para confirmar estos cambios. Lo que resta en esta primera parte es volver a mapear los campos del destino con problemas de tipo de datos con las nuevas columnas derivadas que acabamos de crear. Para ello debemos editar el componente OLEDB Destination, ir hasta la opción Mappings y allí vincular las nuevas columnas con sus respectivos campos en el destino.


Si damos OK en la ventana, ya habremos concluido esta parte del ejercicio y podremos llevar a cabo la primera prueba. Presionamos F5 para que ejecutar el Package y una vez concluida la ejecución, si nos dirigimos a la tabla TablaAlumnos de la Base de Datos podremos ver los datos importados. Deberíamos tener los siguientes datos:




3. Creación de iteración para el Package

Vamos por buen camino, ya falta menos!!! Hasta ahora el proceso funciona correctamente pero con sólo un fichero XLS. Lo que haremos ahora es agregar las iteraciones para que recorra todo el directorio C:\SSIS\Alumnos, cargando de esa forma los datos de todos los ficheros en la tabla TablaAlumnos.

Debemos situarnos en el Control Flow donde agregaremos un Foreach Loop Container sobre la superficie donde ya se encuentra el Data Flow Task. Luego arrastramos éste último dentro del componente Foreach Loop Container.



Ahora debemos configurar el Foreach, para ello hacemos click derecho sobre el mismo, y elegimos Edit. En la ventana del editor nos situamos en la opción collections en donde debemos poner el path y el tipo de archivo que vamos a recorrer. Donde debemos poner “C:\SSIS\Alumnos” y “*.XLS” respectivamente.



En la opción Variable Mappings debemos agregar una nueva variable que se llamará varFileName, será de tipo String y su valor será el primero de los ficheros XLS que tenemos en el directorio “c:\SSIS\Alumnos\Alumnos 28022006.xls”


Lo último que resta es configurar la conexión para el origen de datos Excel Connection Manager que creamos con anterioridad. Para ello hacemos click derecho sobre él, Propiedades, y en Expressions asignamos la variable varFileName a las propiedades ExcelFilePath y ServerName.


Damos OK y listo! El proceso ya está concluido.

Si ejecutamos nuevamente el proceso (es conveniente eliminar el contenido de la tabla TablaAlumnos antes de cada importación para evitar duplicación de datos) veremos cómo han sido cargados los datos de los 3 ficheros XLS de la carpeta C:\SSIS\Alumnos.

Espero les haya sido útil este ejemplo y en sucesivos posts iré ampliando este ejemplo con más funcionalidades. Saludos a todos los lectores!

23 comentarios:

Enrique dijo...

Que tal, verifique el ejemplo de paquete con origen de datos dinámicos me ha ayudadmo mucho. Sólo que me gustaría hacer una pregunta: Tengo que realizar export diariamente de tablas de la BD a un archivo excel esto lo hago conun DTS). Cómo puedo hacer para que el nombre del archivo que se genera sea de forma foto_2008_09_11 18 hrs.xls. (Es decir, la fecha en año, mes, día y hora en que se genera el archivo). Muchas garcias por la atención. Saludos.

Miguel A. Ciacci dijo...

Buenas Enrique, es un gusto recibir tu comentario. Respondiendo a tu pregunta creo que lo se puede resolver creando una variable de tipo string en la cual debes poner el nombre del fichero que desees (foto_2008....xls). Puedes asignar ese nombre de fichero en la variable dinamicamente utilizando un Script en el Data Flow (mirate el siguiente link si tienes dudas sobre esto... http://mciacci.blogspot.com/2008/04/uso-de-precedence-constraint-para.html) y luego en la Excel Connection del fichero de destino vete a propiedades, Expressions y a la propiedad "Name" le asignas la variable antes mencionada y listo... debería funcionar.

Espero sea clara mi explicación, caso contrario avisame y lo repasamos nuevamente. Saludos

Anónimo dijo...

Hola Miguel, gracias por la información me fue muy útil. Tengo una pregunta. Qué objeto puedo utilizar para recorrer una tabla con una condición, y dependiendo del resultado me coloque un 1 o un cero en una columna de esa tabla?. Te agradezco la ayuda que me puedas brindar.
Johanna

ANDRES dijo...

Buenos dias la verdad me a sido muy util tu ayuda...

Ahora debo de escribir varios archivos en funcion de la data de mi base de datos es posible realizar esta tarea. Ejemplo

En mi base de datos tengo estos campos:

Empresa Empleado Salario
CADA jose 1000
CADA luis 2000
EPA pepe 3000

necesito crear dos archivos planos

ARCHIVO CADA.TXT
Empresa Empleado Salario
CADA jose 1000
CADA luis 2000

ARCHIVO EPA.TXT
Empresa Empleado Salario
EPA pepe 3000

Tengo el proceso donde me escribe todos los registros en un solo archivo pero necesito crear son multiples registros segun el nombre de la empresa de la base de datos

Miguel A. Ciacci dijo...

Hola Johana, perdón por al demora al responderte pero faló el sistema de seguimiento y no me notificó tu comentario :D!
Creo que en este post en el que hablo sobre condicionales en derived columns puedes encontrar informacion de utilidad (http://mciacci.blogspot.com/2008/04/ssis-uso-de-condicionales-en.html). Me avisas si no puedes solucionar el inconveniente. Saludos

ANDRES dijo...

Hola buenos dias, miguel, tienes una idea de como empezar esta tarea

ANDRES dijo...

Miguel, buenos dias, tienes una idea de que debo de hacer o por donde empezar

Miguel A. Ciacci dijo...

Buenas Andres, disculpa le demora en responderte. El caso que planteas puede resolverse utilizando un "Conditional Split" o "Division Condicional" dentro del Data Flow. Básicamente lo que debes hacer es agregar el Conditional Split y añadirle 2 CASE, el primero que sea [EMPRESA] == "CADA" y el segundo [EMPRESA] == "EPA". Luego agregas 2 Flat Destination (o el destino que tu prefieras). El primero de estos Flat Destination usará una connection al fichero CADA.TXT y el segundo Flat Destination usará una connection a EPA.TXT. Posteriormente unes la Salida "Case 1" del Split con el Flat Destination correspondiente al fichero CADA.TXT y el "Case 2" con el correspondiente al fichero EPA.TXT.

Espero me hayas comprendido y por cualquier duda sólo debes escribir nuevamente otro comentario. Saludos

ANDRES dijo...

Miguel, lo que me dices pienso que es valido si las empresas fueran estaticas, es decir si las empresas son las mismas, pero las empresas son dinamicas, y hoy pueden cargar 3 mas y deberia entonces de ingrear al ETL y hacer dos cases adicionales, y no es lo que quiero, penser hacer uso de un LOOP pero no tengo la menor idea de como hacerlo, lo que queiro practicamente es:
Lo que me gustaria hacer es crear en una tabla temporal las empresas que estan en base de datos ahora bien tomar el primer registro y poder llenar una variable con el nombre de esa empresa cosa que en la consulta pueda filtrar por la variable y pueda escribir el archivo plano con el nombre de la variable y asi llenar un archivo llamado CADA con todos los registros de CADA, ahora con el uso del LOOP tomar la siguiente empresa meterla en una variable y nuevamente en la consulta de sql filtrar con el nombre de la empresa y crear un archvio plano con el nombre de la empresa, ejecutar este proceso tantas empresas esten en mi tabla temporal de empresas, miguel me puedes enviar algun desarrollo pequeño donde aplique esto que trat de decirte a mi correo aleialei44@hotmail.com, o bien me des tu direccionde correo y podamos conversas por msn por que nose que debo de hacer

Miguel A. Ciacci dijo...

Andres, te contactaré por mail para ver si podemos sacar adalente este proceso.

Gerardo Enrique Fernandez Valladares dijo...

Muchas gracias por tu aporte, me ha sido de gran ayuda en mi trabajo.
Mil gracias man por este aporte.

Saludos desde El Salvador

Mauricio Net dijo...

Hola estimado señor, tengo la misma pregunta qeu andres y me gustaria saber como la soluciono??

Cuando los condicionales son dinamicos.

O si hay alguna forma de importar datos a tablas relacionadas Maestro - Detalle. Desde dos archivos en excel uno para el maestro y otro para el Detalle.

Ivonne dijo...

Miguel, muchas gracias por el articulo, resulto todo perfecto y resolvio un problema no menor en mi trabajo.
Muchisimas gracias por compartir esto!

Saludos,
Ivonne

Unknown dijo...

Hola tengo un problema al disenar un paquete, tengo el siguiente esquema el fichero a exportar y otro fichero que define las columnas que tiene el fichero a exportar, sucede que este fichero a exportar puede aumentar una nueva columna, como haria para que el paquete pueda detectar del fichero que define las columnas cual es la estructura para subir este fichero a la base de datos

Paul dijo...

Estimado Miguel muy buen aporte, tengo una duda segui el manual pero con ficheros CSV y ya al final en las expresiones no encuentro estas propiedades:ExcelFilePath y ServerName. Para este caso ¿que propiedad es la equivalente?

A la espera y muchas gracias de antemano por tu ayuda.

Juan Carlos dijo...

tengo un proble me pasan valores NULL en todos los campos y no los puedo eliminar ?? porfa ayudaa

Juan Carlos dijo...

me salen campos NULL en los atributos y no se pueden eliminar porfa ayudenme !

Luis dijo...

Estimado Miguel:
cuando voy a editar del contenedor for each simplemente no me muestra la ruta para personalizar a la carpeta, otro consulta es cuando tengo en esa carpeta tres archivos como datos de personal, marcaciones de asistencia y jornada de trabajo, puedo subir esos 3 archivos en un solo integration services

Unknown dijo...

Miguel una preguntita.

tengo un paquete que toma informacion de una base de datos y la traspasa a un archivo plano, el nombre del archivo plano se lo doy con una variable,este archivo plano lo guardo en una carpeta y ese archivo lo envio con una tarea enviar correo a una persona, me gustaria saber como se puede enviar el ultimo archivo creado por el paquete por correo, ya que al adjuntar el archivo en la tarea de enviar correo le adjunto la plantilla, pero la idea es que me envie por correo el ultimo archivo creado,
ojala me puedas ayudar, me seria de bastante ayuda

Saludos

Claudio

JesusDomRosas dijo...

hola si se puede tomar exceles dimicos se puede tomar columnas dinamicas tengo que hacer un DTS que me suba sus datos a unas tablas de una base de datos si me pordias ayudar te dejo mi gmail
ing.jesusdomrosas@gmail.com

Unknown dijo...

Buenas Noches!
Soy nueva en el Mundo de BI..

Estoy tratando de extraer datos de excel para el SQL..
pero me quede en el paso:
- click derecho en la superficie, seleccionamos la opción New Connection…
- Seleccionamos la opción EXCEL, y hacemos clic en Add….

No me sale la opcion "Excel" cuando sigo sus pasos..

Por favor si pudiese ayudarme.

Gracias

Unknown dijo...

Hola Miguel, pudiste resolverle el caso de Andres, tengo un problema similar de agecias variables y quiero que se exporte en archivos excel, con el nombre de las agencias y este que contenga todos sus registros, agradeceria tu apoyo es similar al caso de Andres, porfa me avisas: oscater@gmail.com

Unknown dijo...

Hol Miguel, muy buen aporte :), pero tengo un problema quiero generar un archivo en base a una tabla de sql,la cual sería dinámica según un archivo de excel con la que la genero primeramente. Quiero vaciar la información a un excel pero sin tener que hacer las asignaciones manualmente ya que la tabla de Sql nunca tendrían la misma estructura, gxs