El uso de VBA en Excel nos permite realizar muchas tareas automatizadas, tanto de formatos como de datos en sí. La forma "tradicional" de trabajar datos es recorrer las líneas, trabajar las celdas como rangos, etc. Esto es muy útil, pero es trabajoso y lento. Si miramos en las herramientas administrativas los orígenes de datos ODBC, observamos que existe un driver ODBC para Excel ¿Nos permitirá Excel usar SQL para realizar tareas y, por tanto tener una mayor potencia a la hora de realizar búsquedas, modificaciones e inserciones? La respuesta es ¡¡Sí!! No solo eso, nos permite algo que es muy interesante, y es el poder trabajar con libros de Excel en equipos ¡que no tienen Excel instalado! Esto último es interesantísimo en servidores, para poder, por ejemplo, en una tarea programada que lance un script VBScript, que se lean datos o se guarden datos en un libro de Excel, lo que abre posibilidades maravillosas.
Imaginemos que tenemos un script VBScript que ponemos como tarea programada
para que comprima y envíe ficheros por correo a determinados destinatarios,
que pueda incluir varios destinatarios, tanto en el campo Para, CC como en el
CCO y que, además, cada correo pueda incluir más de un archivo
comprimido y cada archivo comprimido pueda incluir más de un fichero.
Si queremos que el script no lleve las tareas en sí dentro del código
(mala cosa a la hora de reutilizarle con distintos datos, pues supone retocar
el código), si no que lea lo que tiene que hacer de un fichero, el fichero
resultante sería muy complejo, con arrays dentro de arrays y diferentes
separadores para cada uno de ellos, siendo la tarea de establecer y recuperar
la información muy dificultosa. Sin embargo, en una estructura de bases
de datos, sería muy fácil leer esto, pues tendríamos una
tabla de tareas, otra con los archivos comprimidos con una clave externa a la
de tareas, otra de ficheros con una clave externa a la de archivos, y otra de
destinatarios y tipo de destinatario (Para, CC o CCO) con una clave externa
a la tabla de tareas. Bastaría realizar las consultas pertinentes, con
sus JOINS si fueran necesarios, para
recuperar la información de una forma muy sencilla. Este es un ejemplo
en el que una base de datos con Excel nos puede ayudar (sería mejor con
Access y se podría tambien
usar desde VBScript, pero tiene el
inconveniente de que para preparar los datos se necesita Access, y eso sale más caro que Excel,
al venir este último en los paquetes más básicos de Office).
En este artículo, veremos cómo se
trabaja
con un libro Excel desde VBScript usando ADODB.
Existen diferencias entre ambos proveedores, que se deben tener en cuenta a la hora de elegir uno u otro para establece la conexión:
Como se puede ver en lo expuesto anteriormente, es mejor usar el proveedor Jet que el ODBC, siendo preferible reservar el uso de éste cuando se tiene que acceder por fuerza vía ODBC con un DSN ya creado.
Respecto a los tipos de datos de las columnas, como hemos visto antes, ADO lo decide en función del contenido de éstas. Esta decisión se hace en función de cuál es el tipo que más ocurrencias tiene, si el numérico o el de cadena, sustituyendo los valores restantes por nulos. En caso de empate, decide que es numérico, dejando como nulos las cadenas que se presenten. Por ello, cuando es necesario que los datos sean mixtos, debemos almacenarlos como texto, de esa manera no perderemos las cadenas o los números.
La información que se pasa al proveedor para la conexión es la ruta + nombre del libro y la versión. Como versión de proveedor se debe usar la 4.0, pues la 3.51 no admite controladores Jet ISAM. Como versión de Excel se pasa:
Veamos dos ejemplos de conexión con el proveedor OLE DB de Microsoft Jet. Los ejemplos consisten en dos funciones que reciben la ruta más nombre de un libro de Excel y devuelven un objeto ADODB.Connection conectado al libro recibido como parámetro. La diferencia entre ambas estriba en la manera en la que se especifica el proveedor OLE DB de Microsoft Jet, asignándolo a la propiedad Provider del objeto ADODB.Connection o estableciéndolo en la propia cadena de conexión. Este es el ejemplo estableciéndolo con la propiedad Provider:
Function f_ConectarALibroExcel(str_Libro) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
'Establecemos la cadena de conexión
str_Conexion = _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=Excel 8.0"
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Establecemos el proveedor
ado_Conexion.Provider = "Microsoft.Jet.OLEDB.4.0"
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
Este otro ejemplo especifica el proveedor en la propia cadena de conexión:
Function f_ConectarALibroExcel(str_Libro) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
'Establecemos la cadena de conexión
str_Conexion = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=Excel 8.0"
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
Cuando queremos abrir un libro de Excel 2007, es necesario que establezcamos como proveedor Microsoft.ACE.OLEDB.12.0. Por tanto, las dos funciones anteriores, para que contemplaran la posibilidad de estar abriendo un libro de Excel 2007, podrían recibir una booleana que lo especificase y quedarían así:
'Esta es la versión que lo especifica con la propiedad Provider
Function f_ConectarALibroExcel(str_Libro, bol_2007) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
'Establecemos la cadena de conexión
str_Conexion = _
"Data Source=" & str_Libro & ";"
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Establecemos el proveedor y la versión
If bol_2007 Then
ado_Conexion.Provider = "Microsoft.ACE.OLEDB.12.0"
str_Conexion = str_Conexion & "Extended Properties=Excel 12.0"
Else
ado_Conexion.Provider = "Microsoft.Jet.OLEDB.4.0"
str_Conexion = str_Conexion & "Extended Properties=Excel 8.0"
End If
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
'Esta es la versión que pasa el proveedor en la propia cadena de conexión
Function f_ConectarALibroExcel(str_Libro, bol_2007) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
'Establecemos el proveedor y la versión
If bol_2007 Then
str_Conexion = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Extended Properties=Excel 12.0;"
Else
str_Conexion = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Extended Properties=Excel 8.0;"
End If
'Establecemos la cadena de conexión
str_Conexion = str_Conexion & _
"Data Source=" & str_Libro
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
Para establecer la conexión es necesario pasar el dato
de Driver, siendo el de Excel ({Microsoft
Excel Driver (*.xls)}
) el que se especifica y la ruta más
nombre del libro. Se puede especificar el proveedor, si bien no es imprescindible,
pues al recibir el dato de driver el objeto ya asume que se trata del proveedor
OLE
DB de Microsoft para controladores ODBC. Otro dato que se debe pasar es el
identificador de driver, DriverId, cuyo valor será (Accessing
Data with ADO):
Como se trata de ODBC, se puede conectar usando un DSN (Data Source Name) definido o sin usar un DSN. Al tratarse de libros Excel, y debido a que vamos orientados a abrir cualquier libro, no me pararé en las conexiones con DSN definido, sólo veremos las conexiones sin DSN. La siguiente función recibe una ruta más nombre de libro y una booleana que cuando es verdadera implica que el libro es de la versión Excel 97:
Function f_ConectarALibroExcel(str_Libro, bol_97) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
Dim str_Version 'As String
If bol_97 Then
str_Version = "790"
Else
str_Version = "278"
End If
'Establecemos la cadena de conexión
str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=" & str_Version & ";" & _
"Dbq=" & str_Libro
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
Si queremos conectar a un libro Excel 2007, es necesario que establezcamos, en la cadena de conexión, como proveedor {Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}, así pues, podemos retocar la anterior función para que reciba una booleana que especifique si es un libro de Excel 2007 o no:
Function f_ConectarALibroExcel(str_Libro, bol_97, bol_2007) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
Dim str_Version 'As String
If bol_97 Then
str_Version = "790"
Else
str_Version = "278"
End If
'Establecemos la cadena de conexión
If bol_2007 Then
str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};"
Else
str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls)};"
End If
str_Conexion = str_Conexion & _
"DriverId=" & str_Version & ";" & _
"Dbq=" & str_Libro
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
Cuando ser trata de conectar a libros de Excel 2007, es necesario instalar en el equipo los Componentes de conectividad de datos de Office 2007. Una vez conectados, la forma de establecer la conexión depende de si usamos OLE DB de Microsoft Jet o OLE DB de Microsoft para controladores ODBC:
A continuación, una función como las tres anteriores, que nos permite elegir qué proveedor se utilizará por medio de la booleana bol_ODBC (OLE DB de Microsoft para controladores ODBC en el caso de ser verdadera y OLE DB de Microsoft Jet en el caso de ser falsa), la versión del libro Excel por medio de la booleana bol_97 (Excel 95/97 si es verdadera, resto si es falsa) y el libro con el que se conectará, por medio de la cadena str_Libro:
Function f_ConectarALibroExcel(str_Libro, _
bol_ODBC, _
bol_97) 'As ADODB.Connection
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
Dim str_Version 'As String
'Establecemos la versión según proveedor
'Primero la versión 97 con ODBC
If bol_ODBC _
And bol_97 Then
str_Version = "790"
'Resto de versiones con ODBC
ElseIf bol_ODBC Then
str_Version = "278"
'Versión 97 con Jet
ElseIf bol_97 Then
str_Version = "Excel 5.0"
'Resto de versiones con Jet
ElseIf bol_2007 Then
str_Version = "Excel 12.0"
Else
str_Version = "Excel 8.0"
End If
'Creamos el objeto conexión
Set ado_Conexion = CreateObject("ADODB.Connection")
'Vamos crear la cadena de conexión en función del proveedor;
'Primero con ODBC
If bol_ODBC Then
If bol_2007 Then
str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};" & _
"DriverId=" & str_Version & ";" & _
"Dbq=" & str_Libro
Else
str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=" & str_Version & ";" & _
"Dbq=" & str_Libro
End If
'Ahora con Jet
ElseIf bol_2007 Then
'Establecemos la cadena de conexión
str_Conexion = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=" & str_Version
Else
'Establecemos la cadena de conexión
str_Conexion = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=" & str_Version
End If
'Conectamos el objeto al libro Excel
ado_Conexion.Open str_Conexion
'La función devuelve el objeto conexión
Set f_ConectarALibroExcel = ado_Conexion
'Vaciamos el objeto
Set ado_Conexion = Nothing
End Function 'f_ConectarALibroExcel
'Conectamos por Jet a un libro Excel 97
Set con_Pescados = f_ConectarALibroExcel("c:\Listados\Pescados.xls", False, True)
'Conectamos por ODBC a un libro de otra versión de Excel
Set con_Aves = f_ConectarALibroExcel("c:\Listados\Aves.xls", True, False)
Function f_RsHojaExcel(ado_Conexion, str_Hoja) 'As ADODB.Recordset
Dim str_Consulta 'As String
Dim rs_Consulta 'As ADODB.Recordset
'Montamos la consulta, agregando un dolar al final del nombre
'de la hoja y encerrando el resultado entre corchetes
str_Consulta = _
"SELECT " & vbCrLf & _
" * " & vbCrLf & _
"FROM " & vbCrLf & _
" [" & str_Hoja & "$]"
'Creamos el Recordset
Set rs_Consulta = CreateObject("ADODB.Recordset")
'Ejecutamos la consulta
rs_Consulta.Open str_Consulta, ado_Conexion
'La función devuelve el Recordset
Set f_RsHojaExcel = rs_Consulta
'Vaciamos el objeto
Set rs_Consulta = Nothing
End Function 'f_RsHojaExcel
Set rs_Tunidos = f_RsHojaExcel(con_Pescados, "Tunidos")
Function f_RsTablaExcel(ado_Conexion, _
str_Tabla, _
bol_Hoja) 'As ADODB.Recordset
Dim str_Consulta 'As String
Dim str_Origen 'As String
Dim rs_Consulta 'As ADODB.Recordset
'Guardamos el nombre de tabla en la variable str_Origen
str_Origen = str_Tabla
'Si es una hoja...
If bol_Hoja Then
'Ponemos el dolar final al nombre y encerramos todo
'entre corchetes
str_Origen = "[" & str_Origen & "$]"
End If
'Montamos la consulta
str_Consulta = _
"SELECT " & vbCrLf & _
" * " & vbCrLf & _
"FROM " & vbCrLf & _
" " & str_Origen
'Creamos el Recordset
Set rs_Consulta = CreateObject("ADODB.Recordset")
'Ejecutamos la consulta
rs_Consulta.Open str_Consulta, ado_Conexion
'La función devuelve el Recordset
Set f_RsTablaExcel = rs_Consulta
'Vaciamos el objeto
Set rs_Consulta = Nothing
End Function 'f_RsTablaExcel
'En este caso se trata de una hoja y ponemos la booleana a True
'En la SELECT se pondrá como tabla [Tunidos$]
Set rs_Tunidos = f_RsHojaExcel(con_Pescados, "Tunidos", True)
'En este otro es un rango con nombre y la ponemos a False
'En la SELECT se pondrá como tabla Serranidos
Set rs_Serranidos = f_RsTablaExcel(con_Pescados, "Serranidos", False)
Function f_RsTablaExcel(ado_Conexion, _
str_Tabla, _
str_Rango, _
bol_Hoja) 'As ADODB.Recordset
Dim str_Consulta 'As String
Dim str_Origen 'As String
Dim rs_Consulta 'As ADODB.Recordset
'Guardamos el nombre de tabla en la variable str_Origen
str_Origen = str_Tabla
'Si es una hoja...
If bol_Hoja Then
'Ponemos el corchete inicial, el dolar al
'final del nombre, concatenamos el rango y
'ponemos el corchete final
str_Origen = "[" & str_Origen & "$" & str_Rango & "]"
End If
'Montamos la consulta
str_Consulta = _
"SELECT " & vbCrLf & _
" * " & vbCrLf & _
"FROM " & vbCrLf & _
" " & str_Origen
'Creamos el Recordset
Set rs_Consulta = CreateObject("ADODB.Recordset")
'Ejecutamos la consulta
rs_Consulta.Open str_Consulta, ado_Conexion
'La función devuelve el Recordset
Set f_RsTablaExcel = rs_Consulta
'Vaciamos el objeto
Set rs_Consulta = Nothing
End Function 'f_RsHojaExcel
'En este caso se trata de una hoja y ponemos la booleana a True
'La tabla a la que hará referencia la SELECT será [Tunidos$]
Set rs_Tunidos = f_RsHojaExcel(con_Pescados, "Tunidos", "", True)
'En este otro es un rango con nombre y la ponemos a False
'La tabla a la que hará referencia la SELECT será Serranidos
Set rs_Serranidos = f_RsTablaExcel(con_Pescados, "Serranidos", "", False)
'Por último, ésta sería la forma de obtener un rango sin nombre
'La tabla a la que hará referencia la SELECT será [Tunidos$A1:F11]
Set rs_10Tunidos = f_RsHojaExcel(con_Pescados, "Tunidos", "A1:F11", True)
Podemos listar las tablas de un libro usando el método OpenSchema del objeto ADODB.Connection que devuelve un objeto ADODB.Recordset. A este método le debemos pasar el parámetro QueryType, que es un parámetro de tipoSchemaEnum, establecido a adSchemaTables (que tiene un valor entero decimal de 20). Este objeto ADODB.Recordset nos devolverá los nombres de las tablas y rangos con nombre en nueve campos, de los cuales sólo rellena cuatro, en el caso de Jet y tres en el de ODBC. Estos son los de Jet:
No obstante, tanto date_created como date_modified muestran siempre la misma fecha, que es la de última modificación; así pues, realmente, sólo tres de los cuatro campos son fiables: table_name, table_type y date_modified.
Respecto a ODBC, los campos que usa son estos tres:
Esta es la teoría, la práctica nos demuestra otra cosa: table_type es siempre de tipo TABLE,se trate de hojas o de rangos con nombre. Así pues, la única manera que tenemos de averiguar si se trata de uno u otro tipo es si aparece el caracter de dolar ($) al final del nombre; si es así, se trata de una hoja, si no, de un rango.
El siguiente método recibe la ruta más nombre de un libro de Excel y muestra por pantalla los nombres de sus tablas y rangos con nombre:Sub s_TablasEnLibro (str_Libro)
Const adSchemaTables = 20
Dim con_Libro 'As ADODB.Connection
Dim rs_Tablas 'As ADODB.Recordset
Dim str_Devolucion 'As String
Dim str_Linea 'As String
Dim bol_Hoja 'As Boolean
Dim str_Tabla 'As String
'Usamos la función de conexión a un libro de
'Excel para crear el objeto Conexión
Set con_Libro = f_ConectarAExcel (str_Libro)
'Creamos el Recordset con la información de
'las tablas del libro
Set rs_Tablas = con_Libro.OpenSchema (adSchemaTables)
'Recorremos los registros de la consulta
While Not rs_Tablas.EOF
'Obtenemos si se trata de un rango o una hoja
bol_Hoja = (Right(rs_Tablas.Fields("table_name").Value, 1) = "$")
'Guardamos el nombre de la tabla
str_Tabla = rs_Tablas.Fields("table_name").Value
'Ahora agregaremos si se trata de una hoja o de un
'rango con nombre y quitamos el dolar final si se trata de una
'hoja
If bol_Hoja Then
str_Tabla = Left(str_Tabla, Len(str_Tabla) - 1 )
str_Linea = "Nombre de tabla: " & str_Tabla & vbCrLf & _
"Tipo de Tabla: Hoja"
Else
str_Linea = "Nombre de tabla: " & str_Tabla & vbCrLf & _
"Tipo de tabla: Rango con nombre"
End If
WScript.Echo str_Linea
Wend
'Cerramos el Recordset y la conexion
rs_Tablas.Close
con_Libro.Close
'Limpieza de culete :-)
Set rs_Tablas = Nothing
Set con_Libro = Nothing
End Sub 's_TablasEnLibro
Sub s_VolcarDatosRS (rs_Tabla)
Dim int_Campo 'As String
Dim str_Linea 'As String
Dim str_Subrayado 'As String
'Mostramos los encabezados, para ello, recorremos los
'campos en un bucle For y almacenamos los nombres,
'separados por tabuladores
For int_Campo = 0 To rs_Tabla.Fields.Count - 1
'Almacenamos el nombre
str_Linea = str_Linea & _
rs_Tabla.Fields(int_Campo).Name & _
vbTab
str_Subrayado = str_Subrayado & _
String( _
Len(rs_Tabla.Fields(int_Campo).Name), _
"=") & _
vbTab
Next 'int_Campo
'Quitamos el tabulador final
If Len(str_Linea) > 0 Then
str_Linea = Left(str_Linea,Len(str_Linea) - 1)
str_Subrayado = Left(str_Subrayado,Len(str_Subrayado) - 1)
End If
'Mostramos los encabezados
WScript.Echo str_Linea
'Los subrayamos
WScript.Echo String(Len(str_Linea), "=")
'Vaciamos la variable con la línea
str_Linea = ""
'Recorremos ahora la consulta
While Not rs_Tabla.EOF
For int_Campo = 0 To rs_Tabla.Fields.Count - 1
'Almacenamos el nombre
str_Linea = str_Linea & _
rs_Tabla.Fields(int_Campo).Value & _
vbTab
Next 'int_Campo
'Quitamos el tabulador final
If Len(str_Linea) > 0 Then _
str_Linea = Left(str_Linea,Len(str_Linea) - 1)
'Mostramos los datos
WScript.Echo str_Linea
'Iniciamos la variable de la línea
str_Linea = ""
'Vamos al siguiente registro
rs_Tabla.MoveNext
Wend
'Cerramos y vaciamos el Recordset
rs_Tabla.Close
Set rs_Tabla = Nothing
End Sub 's_VolcarDatosRS
'Definimos la constante de cursor dinámico
Const adOpenDynamic = 2
'Creamos el Recordset
Set rs_Tabla = CreateObject("ADODB.Recordset")
'Abrimos el Recordset como dinámico
rs_Tabla.Open str_Consulta, ado_Conexion, adOpenDynamic
'Mostramos por pantalla el tipo de Recordset que se ha abierto
WScript.Echo "Tipo de Recordset: " & rs_Tabla.CursorType
Sí, has leído bien, podemos crear un libro Excel desde VBScript usando ADO, sin necesidad de tener Excel instalado. Es, realmente, muy sencillo utilizando DDL (Data Definition Language). Digamos que la forma más "normal" de crear un libro Excel desde VBScript, usando objetos de acceso a datos es utilizar ADOX. Para que un libro sea creado con ADOX es necesario:
'Constantes para el tipo de datos de los campos
Const adBoolean = 11
Const adCurrency = 6
Const adDate = 7
Const adDouble = 5
Const adVarWChar = 202
'Variables de objetos de datos
Dim ado_Conexion 'As ADODB.Connection
Dim ado_Catalogo 'As ADOX.Catalog
Dim ado_Tabla 'As ADOX.Table
Dim ado_Campo 'As ADOX.Column
'Creamos un objeto y lo conectamos a un libro inexistente
'de ruta más nombre igual al del libro que queremos crear
Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=c:\Listados\LibroNuevo.xls"
'Creamos un objeto catálogo y establecemos
'la conexión como su conexión activa
Set ado_Catalogo = CreateObject("ADOX.Catalog")
ado_Catalogo.ActiveConnection = ado_Conexion
'Creamos el objeto tabla
Set ado_Tabla = CreateObject("ADOX.Table")
'Establecemos su nombre
ado_Tabla.Name = "MiHoja"
'Creamos el campo adBoolean
Set ado_Campo = CreateObject("ADOX.Column")
With ado_Campo
.Name = "Booleano"
.Type = adBoolean
End With
'Lo agregamos a la tabla
ado_Tabla.Columns.Append(ado_Campo)
'Vaciamos el objeto campo
Set ado_Campo = Nothing
'Creamos el adCurrency
Set ado_Campo = CreateObject("ADOX.Column")
With ado_Campo
.Name = "Moneda"
.Type = adCurrency
End With
'Lo agregamos a la tabla
ado_Tabla.Columns.Append(ado_Campo)
'Vaciamos el objeto campo
Set ado_Campo = Nothing
'Creamos el adDate
Set ado_Campo = CreateObject("ADOX.Column")
With ado_Campo
.Name = "Fecha"
.Type = adDate
End With
'Lo agregamos a la tabla
ado_Tabla.Columns.Append(ado_Campo)
'Vaciamos el objeto campo
Set ado_Campo = Nothing
'Creamos el adDouble
Set ado_Campo = CreateObject("ADOX.Column")
With ado_Campo
.Name = "Numerico"
.Type = adDouble
End With
'Lo agregamos a la tabla
ado_Tabla.Columns.Append(ado_Campo)
'Vaciamos el objeto campo
Set ado_Campo = Nothing
'Creamos el adVarWChar
Set ado_Campo = CreateObject("ADOX.Column")
With ado_Campo
.Name = "Texto"
.Type = adVarWChar
End With
'Lo agregamos a la tabla
ado_Tabla.Columns.Append(ado_Campo)
'Vaciamos el objeto campo
Set ado_Campo = Nothing
'Agregamos la tabla al catálogo
ado_Catalogo.Tables.Append(ado_Tabla)
'Cerramos y vaciamos objetos
Set ado_Tabla = Nothing
Set ado_Catalog = Nothing
ado_Conexion.Close
Set ado_Conexion = Nothing
'Definición del objeto de conexión
Dim ado_Conexion 'As ADODB.Connection
'Variable para la instrucción DDL
Dim str_Consulta
'Creamos un objeto y lo conectamos a un libro inexistente
'de ruta más nombre igual al del libro que queremos crear
Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=c:\Listados\LibroNuevo.xls"
'Definimos la instrucción DDL
str_Consulta = _
"CREATE TABLE " & vbCrLf & _
" MiHoja " & vbCrLf & _
" (" & vbCrLf & _
" Booleano bit," & vbCrLf & _
" Moneda money," & vbCrLf & _
" Fecha datetime," & vbCrLf & _
" Numerico numeric," & vbCrLf & _
" Texto varchar" & vbCrLf & _
" )"
'Ejecutamos la instrucción DDL
ado_Conexion.Execute str_Consulta
'Cerramos la conexión y vaciamos el objeto
ado_Conexion.Close
Set ado_Conexion = Nothing
Bastante más simple que con ADOX
¿verdad? Si se tratara de crear una base de datos Access,
sería preferible ADOX, pues
nos permite definir muchas más propiedades de los campos, tipos de datos,
precisiones de los mismos, etc., pero teniendo en cuenta las limitaciones de
ADO al manejar Excel,
que estamos viendo a lo largo de este artículo, es más que suficiente
el uso de sentencias DDL.
Podemos insertar datos en una hoja o rango utilizando la parte DML (Data Manipulation Language) de
SQL, en
concreto la instrucción
INSERT INTO. Su sintaxis es:
INSERT INTO Tabla [(campo1, campo2, ...,
campoN)] VALUES
(valor1, valor2, ...,
valorN)
Como tabla tendremos que poner el nombre de la hoja o rango con nombre. Si insertamos en una hoja, lo hará en la línea inmediatamente por debajo de la última escrita, si se trata de un intervalo con nombre, lo hará en la primera línea a continuación de la última del rango, es decir, como si aumentara el rango una línea más, pero ojo, si la línea está ya escrita, se producirá el error -2147467259: No se puede expandir el intervalo con nombre. La sentencia de inserción será evaluada, esperando encontrar los tipos de datos adecuados. Cada tipo tiene sus normas:
Cosas a tener en cuenta:
'Definición del objeto de conexión
Dim ado_Conexion 'As ADODB.Connection
'Variable para la instrucción INSERT
Dim str_Consulta
'Creamos un objeto y lo conectamos al libro
Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=c:\Listados\LibroNuevo.xls"
'Definimos la instrucción INSERT
str_Consulta = _
"INSERT INTO " & vbCrLf & _
" [MiHoja$] " & vbCrLf & _
" (" & vbCrLf & _
" Booleano," & vbCrLf & _
" Moneda," & vbCrLf & _
" Fecha," & vbCrLf & _
" Numerico," & vbCrLf & _
" Texto" & vbCrLf & _
" )" & vbCrLf & _
" VALUES " & vbCrLf
" (" & vbCrLf & _
" False," & vbCrLf & _
" 1025.34," & vbCrLf & _
" #9/4#2008#," & vbCrLf & _
" 25436.3456," & vbCrLf & _
" 'Este es el texto'" & vbCrLf & _
" )"
'Ejecutamos la instrucción INSERT
ado_Conexion.Execute str_Consulta
'Cerramos la conexión y vaciamos el objeto
ado_Conexion.Close
Set ado_Conexion = Nothing
'Definición del objeto de conexión
Dim ado_Conexion 'As ADODB.Connection
'Variable para la instrucción UPDATE
Dim str_Consulta
'Creamos un objeto y lo conectamos al libro
Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=c:\Listados\LibroNuevo.xls"
'Definimos la instrucción UPDATE
str_Consulta = _
"UPDATE " & vbCrLf & _
" [MiHoja$] " & vbCrLf & _
"SET " & vbCrLf & _
" Booleano = True, " & vbCrLf & _
" Moneda = 3452.98, " & vbCrLf & _
" Numerico = 32.67538," & vbCrLf & _
" Texto = 'Registro modificado' " & vbCrLf & _
"WHERE " & vbCrLf
" Fecha = #9/6#2008#"
'Ejecutamos la instrucción UPDATE
ado_Conexion.Execute str_Consulta
'Cerramos la conexión y vaciamos el objeto
ado_Conexion.Close
Set ado_Conexion = Nothing
A continuaciòn pongo dos ejemplos de uso de ADO con libros de Excel. Si los quieres probar, hazlo desde un equipo que no tenga Excel instalado, será mas chulo -(|:o)).
Este script permite leer el contenido del libro de Excel que recibe como parámetro sin nombre requerido. El script volcará en pantalla el contenido de cada hoja. Su sintaxis es:
cscript [//nologo] leer-xls-con-ado.vbs [/S] [/?] libro
Siendo
Ejemplo: Se leerán los datos del libro "e:\datos chorizos\gang-chicharron.xls":
cscript //nologo leer-xls-con-ado.vbs "e:\datos chorizos\gang-chicharron.xls"
Este es el código del script:
'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
'*°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°*
'* leer-xls-con-ado.vbs *
'* *
'* Este script permite leer el contenido del libro de Excel que recibe *
'* como parámetro sin nombre requerido. El script volcará el contenido *
'* de cada hoja. Para leer el libro Excel utiliza ADO, lo que permite *
'* que se puedan leer sus datos en un equipo que no tenga Excel *
'* instalado (por ejemplo un servidor), y sí tenga el driver ODBC para *
'* Excel. *
'* *
'* Sintaxis *
'* *
'* cscript [//nologo] leer-xls-con-ado.vbs [/S] [/?] libro *
'* *
'* Siendo *
'* *
'* - libro (Requerido): *
'* Ruta y nombre del libro de Excel (XLS) que se ha de leer. *
'* *
'* - /S: encabezados (Opcional): *
'* Si se pasa este modificador, se considerará que las hojas *
'* no contienen encabezados, y por tanto la primera fila *
'* contiene datos; si no se pasa, la primera fila se *
'* considerará como nombre de los campos de la tabla. *
'* *
'* - /?: ayuda (Opcional): *
'* Muestra la ayuda en línea *
'* *
'* *
'* Ejemplos: *
'* *
'* - Se leerán los datos del libro "e:\datos *
'* chorizos\gang-chicharron.xls": *
'* *
'* cscript //nologo leer-xls-con-ado.vbs "e:\datos *
'* chorizos\gang-chicharron.xls" *
'* *
'* *
'* *
'* *
'* © Fernando Reyes *
'* Marzo De 2008 *
'*°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°*
'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
'Exigimos la declaración de variables
Option Explicit
Const adSchemaTables = 20
Dim str_Error 'As String
Dim int_Error 'As String
Dim str_Libro 'As String
Dim bol_SinEncabezados 'As Boolean
Dim ado_Conexion
Dim ado_Recordset
Dim int_Campo
Dim str_Linea
Dim str_Hoja
Dim str_Consulta
bol_SinEncabezados = False
'Validando los argumentos y almacenando
'sus valores
If f_RevisarArgumentos( _
str_Error, _
int_Error) Then
Call s_Ayuda(str_Error)
WScript.Quit int_Error
End If
Set ado_Conexion = f_ConectarAExcel(str_Libro, True)
str_Consulta = "SELECT " & vbCrLf & _
" * " & vbCrLf & _
"FROM " & vbCrLf & _
" [Informes$]"
Set ado_Recordset = f_RecordsetExcel(ado_Conexion, "",str_Consulta)
Call s_Volcar(ado_Recordset)
ado_Recordset.Close
ado_Conexion.Close
Set ado_Recordset = Nothing
Set ado_Conexion = Nothing
Sub s_VolcarDatosTabla(str_Hoja)
Dim ado_Recordset
WScript.Echo "Datos en hoja: " & str_Hoja
Set ado_Recordset = f_RecordsetExcel(ado_Conexion,str_Hoja,"")
For int_Campo = 0 To ado_Recordset.Fields.Count - 1
str_Linea = str_Linea & ado_Recordset.Fields(int_Campo).Name & vbTab
Next 'int_Campo
str_Linea = Left(str_Linea,Len(str_Linea)-1)
WScript.Echo str_linea
Do While Not ado_Recordset.EOF
For int_Campo = 0 To ado_Recordset.Fields.Count - 1
str_Linea = str_Linea & ado_Recordset.Fields(int_Campo).Value & vbTab
Next 'int_Campo
str_Linea = Left(str_Linea,Len(str_Linea)-1)
WScript.Echo str_linea
str_Linea = ""
ado_Recordset.MoveNext
Loop
ado_Recordset.Close
Set ado_Recordset = Nothing
End Sub
Function f_RevisarArgumentos( _
str_Error, _
int_Error _
) 'As Boolean
'***********************************************************************
'* Procedimiento: f_RevisarArgumentos *
'* Tipo : Función *
'* Devolución : Booleana *
'* Fecha y Hora : 2008-03-07 17:10:13 *
'* Autor : Fernando Reyes *
'*¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯*
'* Propósito : Esta función revisa los argumentos recibidos, *
'* recogiendo los posibles fallos por falta de *
'* argumentos requeridos y almacenando en las *
'* variables correspondientes los argumentos *
'* recibidos. recibe dos parámetros cuyo fin es ser de *
'* salida: una cadena que almacenará los errores *
'* detectados y un entero que almacenará el código de *
'* los errores detectados. Hay tres tipos de error; *
'* error 1 para los argumentos sin nombre requeridos y *
'* no encontrados, error 2 para los argumentos con *
'* nombre requeridos y no encontrados, por último, *
'* error 4 para los combos de argumentos opcionales *
'* (un combo de argumentos opcionales es aquel *
'* conjunto de argumentos opcionales que es requerido *
'* que se pase al menos uno de ellos y que si se pasa *
'* más de uno se ignorarán aquellos que estén detrás *
'* en la prioridad entre ellos; una característica *
'* clara de lo que es un combo de argumentos es cuando *
'* dos omás argumentos almacenan su valor en la misma *
'* variable). En el caso de producirse más de un tipo *
'* de error, el número de error será la suma de ambos *
'* de los errores recibidos, es decir 3, 5 o 6 *
'***********************************************************************
Dim bol_Devolucion 'As Boolean
Dim bol_Error1 'As Boolean
Dim bol_Error2 'As Boolean
Dim bol_Error4 'As Boolean
'Iniciamos los indicadores
bol_Devolucion = False
bol_Error1 = False
bol_Error2 = False
bol_Error4 = False
'Si hay que mostrar la ayuda, se muestra y
'termina el script
If WScript.Arguments.Named.Exists("?") Then
Call s_Ayuda("******************" & vbCrLf & _
"* AYUDA *" & vbCrLf & _
"******************")
WScript.Quit 0
End If
'Revisamos si están todos los argumentos
'sin nombre requeridos
If WScript.Arguments.Unnamed.Count < 1 Then
str_Error = "Error 1, falta/n argumento/s sin " & _
"nombre requerido/s"
bol_Error1 = True
Else
'Guardamos los argumentos en las variables
'correspondientes
If _
WScript.Arguments.Unnamed.Count - 1 _
>= 0 Then _
str_Libro = _
WScript.Arguments.Unnamed(0)
End If
'Preparamos las variables de devolucion:
'el entero como suma de los posibles errores 1, 2 y 4
int_Error = Abs(bol_Error1) + _
(2 * Abs(bol_Error2)) + _
(4 * Abs(bol_Error4))
'La devolucion de la función será True en caso de
'haber alguno de los errores
bol_Devolucion = (bol_Error1 Or bol_Error2 Or bol_Error4)
'Hacemos la devolución de la función
f_RevisarArgumentos = bol_Devolucion
End Function 'f_RevisarArgumentos
Sub s_Ayuda(str_Error)
'***********************************************************************
'* Procedimiento: s_Ayuda *
'* Tipo : Sub *
'* Devolución : *
'* Fecha y Hora : 2008-03-07 17:10:14 *
'* Autor : Fernando Reyes *
'*¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯*
'* Propósito : Este procedimiento muestra la ayuda en línea. *
'* Recibe un parámetro de tipo cadena que si viene *
'* será mostrado antes de la línea; pensado para que *
'* se muestre un error que se haya detectado. *
'***********************************************************************
'Si hay que mostrar algún texto previo a la ayuda, lo hacemos
If Len(str_Error) > 0 Then
WScript.Echo str_Error & vbCrLf & vbCrLf
End If
'A continuación, mostramos la ayuda por pantalla
WScript.Echo "Este script permite leer el contenido del libro d" & _
"e Excel que recibe como"
WScript.Echo "parámetro sin nombre requerido. El script volcará" & _
" el contenido de cada hoja."
WScript.Echo "Para leer el libro Excel utiliza ADO, lo que perm" & _
"ite que se puedan leer sus"
WScript.Echo "datos en un equipo que no tenga Excel instalado (" & _
"por ejemplo un servidor), y sí"
WScript.Echo "tenga el driver ODBC para Excel."
WScript.Echo ""
WScript.Echo "Sintaxis"
WScript.Echo ""
WScript.Echo "cscript [//nologo] leer-xls-con-ado.vbs [/S] [/?]" & _
" libro"
WScript.Echo ""
WScript.Echo "Siendo"
WScript.Echo ""
WScript.Echo "- libro (Requerido):"
WScript.Echo "Ruta y nombre del libro de Excel (XLS) que se ha " & _
"de leer."
WScript.Echo ""
WScript.Echo "- /S: encabezados (Opcional):"
WScript.Echo "Si se pasa este modificador, se considerará que l" & _
"as hojas no"
WScript.Echo "contienen encabezados, y por tanto la primera fil" & _
"a contiene"
WScript.Echo "datos; si no se pasa, la primera fila se consider" & _
"ará como"
WScript.Echo "nombre de los campos de la tabla."
WScript.Echo ""
WScript.Echo "- /?: ayuda (Opcional):"
WScript.Echo "Muestra la ayuda en línea"
WScript.Echo ""
WScript.Echo ""
WScript.Echo "Ejemplos:"
WScript.Echo ""
WScript.Echo "- Se leerán los datos del libro ""e:\datos choriz" & _
"os\gang-chicharron.xls"" y se"
WScript.Echo "considerará que las primeras líneas contienen los" & _
" nombres de los campos:"
WScript.Echo ""
WScript.Echo "cscript //nologo leer-xls-con-ado.vbs ""e:\datos " & _
"chorizos\gang-chicharron.xls"""
WScript.Echo ""
WScript.Echo "- Se leeran los datos del libro ""e:\datos chori" & _
"zos\gang-chicharron.xls"" y se"
WScript.Echo "considerará que las primeras líneas contienen dat" & _
"os, no los nombres de los"
WScript.Echo "campos:"
WScript.Echo ""
WScript.Echo "cscript //nologo leer-xls-con-ado.vbs /S ""e:\dat" & _
"os chorizos\gang-chicharron.xls"""
WScript.Echo ""
WScript.Echo ""
WScript.Echo ""
End Sub 's_Ayuda
Function f_ConectarAExcel(str_XLS, bol_Jet)
'***********************************************************************
'* Procedimiento: f_ConectarAExcel *
'* Tipo : Función *
'* Devolución : Objeto ADODB.Connection *
'* Fecha y Hora : 2008-02-29 17:37:13 *
'* Autor : Fernando Reyes *
'*¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯*
'* Propósito : Esta función recibe la ruta más nombre de libro de *
'* Excel y devuelve un objeto Conexión de ADODB *
'* conectado a dicho libro de Excel *
'***********************************************************************
Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection
'Establecemos la cadena de conexión con el proveedor
'OLE DB de Microsoft Jet si bol_Jet es verdadero
If bol_Jet Then
str_Conexion = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & str_XLS & "; " & _
"Extended Properties=Excel 8.0"
'Como bol_Jet es falso, establecemos la cadena de conexión
'con el proveedor OLE DB de Microsoft para controladores
'ODBC
Else
str_Conexion = "Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=" & str_XLS & ";"
End If
Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open str_Conexion
Set f_ConectarAExcel = ado_Conexion
WScript.Echo "Funcion de conexión conectada a " & f_ConectarAExcel.ConnectionString
' ado_Conexion.Close
Set ado_Conexion = Nothing
End Function 'f_ConectarAExcel
Function f_RecordsetExcel(ado_Conexion, str_Hoja, str_Consulta)
'***********************************************************************
'* Procedimiento: f_RecordsetExcel *
'* Tipo : Función *
'* Devolución : ADODB.Recordset *
'* Fecha y Hora : 2008-02-29 17:47:10 *
'* Autor : Fernando Reyes *
'*¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯*
'* Propósito : Esta función recibe una conexión Excel y un nombre *
'* de hoja Excel y devuelve un ADODB.Recordset con los *
'* datos de la tabla contenida en la hoja cuyo nombre *
'* es el recibido, hoja del libro al cual está *
'* conectado la conexión ADODB.Connection. Si se pasa *
'* vacío el parámetro hoja, se creará la consulta que *
'* se reciba con el parámetro str_Consulta *
'***********************************************************************
Dim ado_Recordset 'As ADODB.Recordset
If Len(Trim(str_Hoja)) > 0 Then
str_Consulta = "SELECT " & _
" * " & _
"FROM " & _
" " & str_Hoja
End If
Set ado_Recordset = CreateObject("ADODB.Recordset")
' WScript.Echo str_Consulta
ado_Recordset.Open str_Consulta, ado_Conexion
Set f_RecordsetExcel = ado_Recordset
' ado_Recordset.Close
Set ado_Recordset = Nothing
End Function 'f_RecordsetExcel
Sub s_Volcar(rs_Consulta)
Dim int_Campo 'As Integer
Dim str_Linea 'As String
Dim arr_Adjuntos 'As String
Dim str_Adjunto 'As String
For int_Campo = 0 To rs_Consulta.Fields.Count - 1
str_Linea = str_Linea & _
rs_Consulta.Fields(int_Campo).Name & _
vbTab
Next 'int_Campo
str_Linea = str_Linea & _
"Para" & vbTab & _
"CC" & vbTab & _
"CCO" & vbTab
str_Linea = Left(str_Linea,Len(str_Linea) - 1)
WScript.Echo str_Linea
str_Linea = ""
While Not rs_Consulta.EOF
For int_Campo = 0 To rs_Consulta.Fields.Count - 1
str_Linea = str_Linea & _
rs_Consulta.Fields(int_Campo).Value & _
vbTab
Next 'int_Campo
str_Linea = str_Linea & _
f_Cuentas(rs_Consulta.Fields("id_informe").Value,"Para") & vbTab & _
f_Cuentas(rs_Consulta.Fields("id_informe").Value,"CC") & vbTab & _
f_Cuentas(rs_Consulta.Fields("id_informe").Value,"CCO") & vbTab
arr_Adjuntos = f_Comprimir(rs_Consulta.Fields("id_informe").Value)
For Each str_Adjunto In arr_Adjuntos
MsgBox str_Adjunto
Next
str_Linea = Left(str_Linea,Len(str_Linea) - 1)
WScript.Echo str_Linea
str_Linea = ""
rs_Consulta.MoveNext
Wend
End Sub
Function f_Cuentas(id_Informe,str_Tipo) 'As String
Dim str_Consulta 'As String
Dim rs_Consulta 'As ado_Recordset
Dim str_Devolucion 'As String
str_Consulta = "SELECT " & vbCrLf & _
" destinatario, " & vbCrLf & _
" email " & vbCrLf & _
"FROM " & vbCrLf & _
" [" & str_Tipo & "$] " & vbCrLf & _
"WHERE " & vbCrLf & _
" id_informe = " & id_Informe
Set rs_Consulta = f_RecordsetExcel(ado_Conexion, "" ,str_Consulta)
If Not rs_Consulta.EOF Then
While Not rs_Consulta.EOF
str_Devolucion = str_Devolucion & _
rs_Consulta.Fields("Destinatario").Value & _
"<" & rs_Consulta.Fields("email").Value & ">;"
rs_Consulta.MoveNext
Wend
str_Devolucion = Left(str_Devolucion,Len(str_Devolucion) - 1)
End If
rs_Consulta.Close
Set rs_Consulta = Nothing
f_Cuentas = str_Devolucion
End Function
Function f_Comprimir(id_Informe)
Dim str_Consulta 'As String
Dim rs_Consulta 'As ADODB.Recordset
Dim str_Comando 'As String
Dim str_Adjuntos 'As String
str_Consulta = "SELECT " & vbCrLf & _
" nombre," & vbCrLf & _
" archivo " & vbCrLf & _
"FROM " & vbCrLf & _
" [Ficheros$] " & vbCrLf & _
"WHERE " & vbCrLf & _
" id_informe = " & id_Informe
Set rs_Consulta = f_RecordsetExcel(ado_Conexion,"",str_Consulta)
If Not rs_Consulta.EOF Then
While Not rs_Consulta.EOF
str_Comando = "7za a " & rs_Consulta.Fields("archivo").Value & _
" " & rs_Consulta.Fields("nombre").Value
MsgBox str_Comando
rs_Consulta.MoveNext
Wend
End If
rs_Consulta.Close
str_Consulta = "SELECT " & vbCrLf & _
" DISTINCT archivo " & vbCrLf & _
"FROM " & vbCrLf & _
" [Ficheros$] " & vbCrLf & _
"WHERE " & vbCrLf & _
" id_informe = " & id_Informe
Set rs_Consulta = f_RecordsetExcel(ado_Conexion,"",str_Consulta)
If Not rs_Consulta.EOF Then
While Not rs_Consulta.EOF
str_Adjuntos = str_Adjuntos & _
rs_Consulta.Fields("archivo").Value & _
vbTab
rs_Consulta.MoveNext
Wend
str_Adjuntos = Left(str_Adjuntos, Len(str_Adjuntos) - 1)
End If
rs_Consulta.Close
Set rs_Consulta = Nothing
f_Comprimir = Split(str_Adjuntos, vbTab)
End Function
Por último, presento un ejemplo de uso de un libro de Excel desde VBScript sin necesidad de tener instalada la aplicación en el equipo. En concreto desarrollé esto para enviar determinados informes a determinadas personas de forma programada. Basta con cambiar los registros del libro Excel para que los envíos cambien de destinatario, asunto, adjuntos, etc.
En el ejemplo hay dos ficheros:
La estructura del libro consta de las siguientes hojas y campos en ellas:
En el libro he dejado datos de ejemplo que implican que se envíen tres informes: