You are on page 1of 50

http://www.microsoft.com/downloads/details.aspx?

displaylang=es&FamilyID=7554f536-8c28-4598-9b72-
ef94e038c891

Usar ODBC para acceder a Excel Con VBScript


Introduccion
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 lneas, trabajar las celdas como rangos, etc. Esto
es muy til, pero es trabajoso y lento. Si miramos en las herramientas administrativas los orgenes 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 bsquedas, 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 interesantsimo 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 enve
ficheros por correo a determinados destinatarios, que pueda incluir varios destinatarios, tanto en el campo
Para, CC como en el CCO y que, adems, cada correo pueda incluir ms de un archivo comprimido y cada
archivo comprimido pueda incluir ms de un fichero. Si queremos que el script no lleve las tareas en s dentro
del cdigo (mala cosa a la hora de reutilizarle con distintos datos, pues supone retocar el cdigo), si no que lea
lo que tiene que hacer de un fichero, el fichero resultante sera muy complejo, con arrays dentro de arrays y
diferentes separadores para cada uno de ellos, siendo la tarea de establecer y recuperar la informacin muy
dificultosa. Sin embargo, en una estructura de bases de datos, sera muy fcil leer esto, pues tendramos 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. Bastara realizar las consultas pertinentes, con sus JOINS si fueran
necesarios, para recuperar la informacin de una forma muy sencilla. Este es un ejemplo en el que una base de
datos con Excel nos puede ayudar (sera mejor con Access y se podra tambien usar desde VBScript, pero tiene
el inconveniente de que para preparar los datos se necesita Access, y eso sale ms caro que Excel, al venir este
ltimo en los paquetes ms bsicos de Office).

En este artculo, veremos cmo se trabaja con un libro Excel desde VBScript usando ADODB.

Como Abrir Una Conexin ADO A Un Libro Excel


Para conectarse con ADO a un libro Excel se utiliza un objeto ADODB.Connection. La conexin puede ser
realizada por medio de dos proveedores:

1. Proveedor OLE DB de Microsoft Jet.


2. Proveedor OLE DB de Microsoft para controladores ODBC.

Consideraciones De Los Proveedores

Existen diferencias entre ambos proveedores, que se deben tener en cuenta a la hora de elegir uno u otro para

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


establece la conexin:

Con Jet podemos especificar si tendr o no encabezados la tabla en las porpiedades extendidas con
HDR=yes o HDR=No (de forma predeterminada se considera que s, por lo que si se omite HDR Jet
asumir que la primera fila son encabezados de columna), mientras que con el proveedor ODBC se
puede establecer si tiene o no encabezados con FirstRowHasNames=<valor> (valor es 1 en caso
verdadero y 0 en caso falso), pero no funciona, est de adorno, por lo que siempre ODBC considerar
que tiene encabezados de columnas (veas el artculo de la Knowledge Base 288343).
Las conexiones con Jet son de lectura/escritura, mientras que de forma predeterminada son de slo
lectura en el caso de ODBC, pudiendo cambiar este comportamiento estableciendo la propiedad
Readonly como False.
Para determinar los tipos de datos de las columnas, tanto Jet como ODBC examinan los primeros 8
registros y operan en consecuencia. Con Jet se puede establecer cuntas filas se examinarn para decidir
el tipo de datos, pero con ODBC no, siempre son 8 filas, pues a pesar de existir la propiedad
RowsToScan, que permite establecer el nmero de filas a examinar, sta no funciona y adems, si una
columna contiene cadenas que deben ser superiores a 255 caracteres pero ninguno de los valores de las
primeras 8 filas supera estos 255 caracteres, las cadenas que los superen sern truncadas. sto se puede
solucionar para libros de Excel posteriores a la versin 97 retocando el registro como se explica en el
artculo de la Knowledge Base 189897.

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 va ODBC con un DSN ya creado.

Tipos De Datos De Las Columnas

Respecto a los tipos de datos de las columnas, como hemos visto antes, ADO lo decide en funcin del
contenido de stas. Esta decisin se hace en funcin de cul es el tipo que ms ocurrencias tiene, si el
numrico o el de cadena, sustituyendo los valores restantes por nulos. En caso de empate, decide que es
numrico, 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 nmeros.

Conexin Con El Proveedor OLE DB De Microsoft Jet

La informacin que se pasa al proveedor para la conexin es la ruta + nombre del libro y la versin. Como
versin de proveedor se debe usar la 4.0, pues la 3.51 no admite controladores Jet ISAM. Como versin de
Excel se pasa:

1. Excel 5.0: para Excel 95


2. Excel 8.0: para Excel 2000/XP/2003/2007
3. Excel 12.0: para Excel 2007

Veamos dos ejemplos de conexin con el proveedor OLE DB de Microsoft Jet. Los ejemplos consisten en dos
funciones que reciben la ruta ms nombre de un libro de Excel y devuelven un objeto ADODB.Connection
conectado al libro recibido como parmetro. La diferencia entre ambas estriba en la manera en la que se
especifica el proveedor OLE DB de Microsoft Jet, asignndolo a la propiedad Provider del objeto
ADODB.Connection o establecindolo en la propia cadena de conexin. Este es el ejemplo establecindolo
con la propiedad Provider:

Function f_ConectarALibroExcel(str_Libro) 'As ADODB.Connection

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Dim str_Conexion 'As String
Dim ado_Conexion 'As ADODB.Connection

'Establecemos la cadena de conexin


str_Conexion = _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=Excel 8.0"

'Creamos el objeto conexin


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 funcin devuelve el objeto conexin


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 conexin:

Function f_ConectarALibroExcel(str_Libro) 'As ADODB.Connection

Dim str_Conexion 'As String


Dim ado_Conexion 'As ADODB.Connection

'Establecemos la cadena de conexin


str_Conexion = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=Excel 8.0"

'Creamos el objeto conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Conectamos el objeto al libro Excel


ado_Conexion.Open str_Conexion

'La funcin devuelve el objeto conexin


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, podran recibir una booleana que lo especificase y
quedaran as:
'Esta es la versin que lo especifica con la propiedad Provider

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 conexin


str_Conexion = _
"Data Source=" & str_Libro & ";"

'Creamos el objeto conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Establecemos el proveedor y la versin


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 funcin devuelve el objeto conexin


Set f_ConectarALibroExcel = ado_Conexion

'Vaciamos el objeto

Set ado_Conexion = Nothing

End Function 'f_ConectarALibroExcel

'Esta es la versin que pasa el proveedor en la propia cadena de conexin


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 versin


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 conexin


str_Conexion = str_Conexion & _
"Data Source=" & str_Libro

'Creamos el objeto conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Conectamos el objeto al libro Excel


ado_Conexion.Open str_Conexion

'La funcin devuelve el objeto conexin


Set f_ConectarALibroExcel = ado_Conexion

'Vaciamos el objeto

Set ado_Conexion = Nothing

End Function 'f_ConectarALibroExcel

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Conexin Con El Proveedor OLE DB de Microsoft para controladores ODBC

Para establecer la conexin es necesario pasar el dato de Driver, siendo el de Excel ({Microsoft Excel
Driver (*.xls)}) el que se especifica y la ruta ms 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):

1. Excel 95/97: 790


2. Versiones posteriores: 278

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, slo veremos las conexiones sin DSN. La siguiente funcin recibe una ruta ms
nombre de libro y una booleana que cuando es verdadera implica que el libro es de la versin 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 conexin


str_Conexion = _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=" & str_Version & ";" & _
"Dbq=" & str_Libro

'Creamos el objeto conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Conectamos el objeto al libro Excel


ado_Conexion.Open str_Conexion

'La funcin devuelve el objeto conexin


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 conexin, como
proveedor {Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}, as pues, podemos retocar la
anterior funcin 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

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 conexin


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 conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Conectamos el objeto al libro Excel


ado_Conexion.Open str_Conexion

'La funcin devuelve el objeto conexin


Set f_ConectarALibroExcel = ado_Conexion

'Vaciamos el objeto
Set ado_Conexion = Nothing

End Function 'f_ConectarALibroExcel

Conexin A Libros De Excel 2007

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 conexin depende de si
usamos OLE DB de Microsoft Jet o OLE DB de Microsoft para controladores ODBC:

OLE DB de Microsoft Jet: se debe poner como proveedor, en la cadena de conexin,


Microsoft.ACE.OLEDB.12.0
OLE DB de Microsoft para controladores ODBC: en la especificacin del driver de la conexin se debe
poner Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)}".

Unindolo Todo

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


A continuacin, una funcin 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 versin 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 versin segn proveedor


'Primero la versin 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"

'Versin 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 conexin


Set ado_Conexion = CreateObject("ADODB.Connection")

'Vamos crear la cadena de conexin en funcin 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 & ";" & _

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


"Dbq=" & str_Libro

End If

'Ahora con Jet


ElseIf bol_2007 Then

'Establecemos la cadena de conexin


str_Conexion = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & str_Libro & ";" & _
"Extended Properties=" & str_Version

Else

'Establecemos la cadena de conexin


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 funcin devuelve el objeto conexin


Set f_ConectarALibroExcel = ado_Conexion

'Vaciamos el objeto
Set ado_Conexion = Nothing

End Function 'f_ConectarALibroExcel

Para llamar a esta funcin es tan simple como hacer as:


'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 versin de Excel


Set con_Aves = f_ConectarALibroExcel("c:\Listados\Aves.xls", True, False)

Con eso habremos, en una sola lnea, conectado al libro Excel que deseemos, con tan solo pasar su ruta y
nombre, si queremos conectar por ODBC o por Jet y su versin de Excel Cmodo, eh?

Los Datos
Como vimos antes, es importante que tengamos en cuenta que ADO considera la primera lnea siempre como
nombres de campo (siempre que no establezcamos lo contrario con HDR en el proveedor Jet; como vimos con
el proveedor ODBC, la primera lnea siempre ser considerada de encabezados). Esto quiere decir que los
datos los deberamos tener siempre con encabezados, pues si estos no existen, la primera lnea de datos la
perderemos y se convertir en los nombres de los campos (lo cual puede dar errores debido a caracteres
prohibidos, etc.). Tambin vimos que la estructura de los datos debe ser coherente, pues ADO lee las primeras
ocho lneas de datos para decidir qu tipo de dato tienen los campos.

Con ADO podemos leer hojas, rangos con nombre y rangos sin nombre.

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Leer Hojas

Las hojas son lo que el ADO considera tablas de tipo tabla de sistema. A la hora de hacer referencia a una
hoja en una SQL, se debe aadir a su final un caracter de dolar ($) y al conjunto encerrarlo entre corchetes([]);
esto es, la hoja Tunidos, debe ponerse en la SELECT como [Tunidos$]. La siguiente funcin nos
devuelve un objeto ADODB.Recordset con los datos de la hoja recibida como parmetro. Esto lo hace con
la conexin que tambin recibe como parametro:

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 funcin devuelve el Recordset


Set f_RsHojaExcel = rs_Consulta

'Vaciamos el objeto
Set rs_Consulta = Nothing

End Function 'f_RsHojaExcel

Para obtener un Recordset con los datos de la tabla, es tan simple como esto:

Set rs_Tunidos = f_RsHojaExcel(con_Pescados, "Tunidos")

Sealar que es tambin posible encerrar el nombre de la hoja entre acentos graves, en lugar de corchetes; es
decir, es lo mismo [Tunidos$] que `Tunidos$`

Leer Rangos Con Nombre

Los rangos con nombre son lo que el driver considera tablas de tipo tabla. Se consultan igual que las hojas,
pero poniendo el nombre sin ms, no es necesario encerrar entre corchetes o acentos graves, ni poner un dolar
al final del nombre de la tabla; para tener esto en cuenta, podramos cambiar la anterior funcin para indicarle,
por medio de una booleana, si se trata de un rango con nombre o de una hoja:

Function f_RsTablaExcel(ado_Conexion, _
str_Tabla, _
bol_Hoja) 'As ADODB.Recordset

Dim str_Consulta 'As String

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 funcin devuelve el Recordset


Set f_RsTablaExcel = rs_Consulta

'Vaciamos el objeto
Set rs_Consulta = Nothing

End Function 'f_RsTablaExcel

Para usar esta funcin:

'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)

Leer Rangos Sin Nombre

Tambin es posible leer directamente el rango que queramos sin que ste tenga nombre. Para ello,
especificamos la hoja y las coordenadas de ese rango. La sintaxis es:

[nombre de hoja$coordenada 1:coordenada 2]

Por ejemplo, para referirnos al rango A1:F24 de la hoja Tunidos, lo haramos como
[Tunidos$A1:F24]. Podramos retocar la funcin anterior para que nos permita especificar un rango
dentro de una hoja. Ser necesario que la booleana la pasemos como True:

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 funcin devuelve el Recordset


Set f_RsTablaExcel = rs_Consulta

'Vaciamos el objeto
Set rs_Consulta = Nothing

End Function 'f_RsHojaExcel

Para usar este funcin:

'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 sera 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)

Listar Las Tablas De Un Libro

Podemos listar las tablas de un libro usando el mtodo OpenSchema del objeto ADODB.Connection que

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


devuelve un objeto ADODB.Recordset. A este mtodo le debemos pasar el parmetro QueryType, que es
un parmetro 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 slo rellena cuatro, en el caso de Jet y tres en el de ODBC. Estos son los de Jet:

table_name: nombre de la tabla o rango con nombre.


table_type: con dos posibles valores.
TABLE: rango con nombre.
SYSTEM TABLE: hoja.
date_created: Fecha de creacin de la tabla.
date_modified: Fecha de ltima modificacin de la tabla.

No obstante, tanto date_created como date_modified muestran siempre la misma fecha, que es la de ltima
modificacin; as pues, realmente, slo tres de los cuatro campos son fiables: table_name, table_type
y date_modified.

Respecto a ODBC, los campos que usa son estos tres:

table_name: nombre de la tabla o rango con nombre.


table_type: con dos posibles valores.
TABLE: rango con nombre.
SYSTEM TABLE: hoja.
table_catalog: carpeta en la que se encuentra el libro.

Esta es la teora, la prctica 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 mtodo recibe la ruta ms 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 funcin de conexin a un libro de


'Excel para crear el objeto Conexin
Set con_Libro = f_ConectarAExcel (str_Libro)

'Creamos el Recordset con la informacin de


'las tablas del libro
Set rs_Tablas = con_Libro.OpenSchema (adSchemaTables)

'Recorremos los registros de la consulta


While Not rs_Tablas.EOF

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


'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

Volcar Los Datos De Las Consultas

Para volcar los datos de una consulta, podemos usar un mtodo como el que sigue. El mtodo recibe un objeto
ADODB.Recordset y muestra por pantalla los datos que contiene. Este es un mtodo tpico a la hora de
recorrer los registros de un Recordset cualquiera, da igual que sea ADO, DAO, etc.
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), _

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


"=") & _
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 lnea


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 lnea


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

Nota: El ADODB.Recordset creado cuando no se especifica el tipo de cursor es de tipo


adOpenForwardOnly, que es el predeterminado. Se puede indicar el tipo de cursor de esta manera:

objetoRS.Open consulta, objeto_conexion, tipo

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Siendo el tipo uno de los de la enumeracin CursorTypeEnum. Por ejemplo, para abrir un cursor dinmico:

'Definimos la constante de cursor dinmico


Const adOpenDynamic = 2

'Creamos el Recordset
Set rs_Tabla = CreateObject("ADODB.Recordset")

'Abrimos el Recordset como dinmico


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

Perfecto, ya podemos movernos adelante y atrs con este cursor, agregar, modificar y borrar registros! Va ser
que no... La ltima lnea del cdigo nos mostrar el tipo de cursor abierto por pantalla, que debera haber sido
2, correspondiente a adOpenDynamic, sin embargo mostrar un 3, el correspondiente a adOpenStatic, que
nos permite movernos adelante y atrs en el Recordset, pero no permite actualizaciones, inserciones ni
borrados. Esto es debido a que el

Creacin De Un Libro Excel Desde ODBC


S, has ledo 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
ms "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:

1. Crear un objeto ADODB.Connection.


2. Conectarlo a un libro Excel inexistente (ruta y nombre del libro que queremos crear).
3. Crear un objeto ADOX.Catalog.
4. Establecer la conexin creada como conexin activa del objeto ADOX.Catalog.
5. Crear un objeto ADOX.Table.
6. Crear, al menos, un objeto ADOX.Column y agregarlo a la tabla.
7. Agregar la tabla al catlogo.

Veamos un ejemplo de creacin de un libro con ADOX

'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 ms nombre igual al del libro que queremos crear

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Set ado_Conexion = CreateObject("ADODB.Connection")
ado_Conexion.Open _
"Driver={Microsoft Excel Driver (*.xls)};" & _
"DriverId=790;" & _
"Dbq=c:\Listados\LibroNuevo.xls"

'Creamos un objeto catlogo y establecemos


'la conexin como su conexin 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

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


'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 catlogo


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

Como podemos ver, es bastante trabajoso, de ah el que yo prefiera usar la potencia de SQL, en concreto la
parte DDL. Al usar DDL los pasos a dar son:

1. Crear un objeto ADODB.Connection.


2. Conectarlo a un libro Excel inexistente (ruta y nombre del libro que queremos crear).
3. Ejecutar la instruccin DDL con el mtodo Execute del objeto ADODB.Connection.

Veamos ahora la creacin del mismo libro de antes usando DDL. La instruccin DDL para la creacin de
tablas es CREATE TABLE, cuya sintaxis es:

CREATE TABLE Tabla (campo1 tipo1[, campo2 tipo2][,...][, campoN tipoN])

Los tipos posibles para Excel desde ADO son:

1. Booleano: bit.
2. Fecha: datetime.
3. Moneda: money.
4. Numrico: numeric.
5. Texto: varchar.

La mxima precisin es de 15 decimales, que es la mxima precisin de Excel. Aunque el mximo tamao de
contenido de una celda sea de 32 Kbytes, el driver ODBC de Excel slo permite texto de 255 caracteres, a no
ser que sea Excel 2000 o posterior y retoquemos el registro (Knowledge Base 189897); este problema no lo
tiene Jet.
'Definicin del objeto de conexin
Dim ado_Conexion 'As ADODB.Connection

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


'Variable para la instruccin DDL
Dim str_Consulta

'Creamos un objeto y lo conectamos a un libro inexistente


'de ruta ms 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 instruccin 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 instruccin DDL


ado_Conexion.Execute str_Consulta

'Cerramos la conexin y vaciamos el objeto


ado_Conexion.Close
Set ado_Conexion = Nothing

Bastante ms simple que con ADOX verdad? Si se tratara de crear una base de datos Access, sera preferible
ADOX, pues nos permite definir muchas ms 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 artculo, es ms que suficiente el uso de sentencias DDL.

Insercin De Datos En Una Hoja O Rango


Podemos insertar datos en una hoja o rango utilizando la parte DML (Data Manipulation Language) de SQL,
en concreto la instruccin 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 lnea inmediatamente por debajo de la ltima escrita, si se trata de un intervalo con nombre, lo har en la
primera lnea a continuacin de la ltima del rango, es decir, como si aumentara el rango una lnea ms, pero
ojo, si la lnea est ya escrita, se producir el error -2147467259: No se puede expandir el
intervalo con nombre. La sentencia de insercin ser evaluada, esperando encontrar los tipos de datos
adecuados. Cada tipo tiene sus normas:

Booleano: escribiremos True o False (True).


Moneda: escribiremos como nmero, siendo el separador decimal el punto (427,65).
Fecha: se escribir encerrada entre almohadillas y en el formato M/D/YYYY (#1/2/2008#; esto es 2 de
enero de 2008).

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Numrico: se escribir como nmero, siendo el separador decimal el punto (398,432).
Texto: se escribir encerrado entre comillas simples o dobles; en el caso de usar comillas dobles, al
estar stas dentro de una cadena, se debern escribir como dobles comillas dobles ('Este texto' o
""Este texto"").

Cosas a tener en cuenta:

Dado que Excel interpreta el tipo de datos de las columnas analizando el tipo de los primeros 8
registros, si la tabla est vaca, al no tener datos suficientes para decidir los tipos de datos de las
columnas, lo considerar todo como texto, aun cuando hubieramos creado la tabla con ADODB
estableciendo otro tipo de datos en las columnas. Una vez se tiene al menos un registro con los datos
claramente definidos en su tipo, la insercin la har con el tipo requerido y adems dar error el intentar
insertar un dato de un tipo diferente al de la columna, por ejemplo al intentar escribir texto en una
columna numrica.
Los textos los inserta siempre con una comilla simple por delante; es decir, si ponemos que inserte en
un campo Este texto, en el libro excel aparecer como contenido de la celda 'Este texto.
Si borrramos todos los registros dejando los encabezados, al hacer una nueva insercin se realizar en
la lnea inmediatamente por debajo del ltimo registro que haba, a pesar de estar las lineas superiores
sin nada. Para evitar esto hay que eliminar las lneas, no borrarlas.
Se considerar ltima lnea escrita de una hoja no la ltima de la tabla de la hoja en s, si no la ltima
lnea escrita en la hoja; esto quiere decir que si tuviramos ms de una tabla en una hoja (la tabla propia
de la hoja y una o ms creadas en rangos con nombre), en el caso de escribir en la hoja (no en un rango
con nombre, pues ya vimos que slo se puede escribir en la primera lnea por debajo del rango, si est
vaca), se escribira en la lnea siguiente a la ltima ocupada en cualquiera de las tablas que contenga la
hoja, eso s, en las columnas correspondientes a la tabla en la que se escribe.

Nota: La sintaxis de sentencia INSERT que he puesto ms arriba no es la nica posible, solo se trataba de explicar el ejemplo expuesto.
Es posible insertar de golpe muchos registros basado en una consulta. Para una descripcin ms profunda de INSERT INTO:

INSERT INTO Statement (Microsoft Access SQL)

Veamos un ejemplo de insercin de un registro en la tabla anteriormente creada:

'Definicin del objeto de conexin


Dim ado_Conexion 'As ADODB.Connection

'Variable para la instruccin 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 instruccin INSERT


str_Consulta = _
"INSERT INTO " & vbCrLf & _
" [MiHoja$] " & vbCrLf & _
" (" & vbCrLf & _
" Booleano," & vbCrLf & _
" Moneda," & vbCrLf & _

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


" 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 instruccin INSERT


ado_Conexion.Execute str_Consulta

'Cerramos la conexin y vaciamos el objeto


ado_Conexion.Close
Set ado_Conexion = Nothing

Modificacin De Datos
Podemos modificar datos por medio de la instruccin UPDATE de SQL, cuya sintaxis es:

UPDATE Tabla SET campo1 = valor1[, campo2 = valor2][,...][, campoN =


valorN] [WHERE condiciones]

Podemos cambiar uno o varios campos de uno o varios registros. La parte SET se encarga de establecer qu
campos se cambian y qu valores se les ponen y la parte WHERE se encarga de especificar qu registros son
los afectados; si no se especifica parte WHERE, todos los registros son modificados.

'Definicin del objeto de conexin


Dim ado_Conexion 'As ADODB.Connection

'Variable para la instruccin 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 instruccin 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 instruccin UPDATE

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


ado_Conexion.Execute str_Consulta

'Cerramos la conexin y vaciamos el objeto


ado_Conexion.Close
Set ado_Conexion = Nothing

No se pueden modificar frmulas (el contenido de la celda empieza por el caracter igual =), pues las frmulas
son de slo lectura.

Borrado De Datos
Esto va ser muy rpido: no se pueden borrar registros, pues se produce el error Este ISAM no admite
la eliminacin de datos de tablas vinculadas. Slo se puede borrar campo por campo, es
decir, vaciar de contenido el registro, aunque, realmente, ste no desaparece, al no haberse eliminado la lnea.
Tampoco se pueden borrar celdas que contengan frmulas de Excel, produciendose el error Operacin no
permitida en este contexto.

Ejemplos
A continuacin 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)).

Ejemplo 1

Este script permite leer el contenido del libro de Excel que recibe como parmetro 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

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 lnea

Ejemplo: Se leern 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 cdigo del script:

'*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
'**
'* leer-xls-con-ado.vbs *
'* *
'* Este script permite leer el contenido del libro de Excel que recibe *
'* como parmetro 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 *

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


'* 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 lnea *
'* *
'* *
'* Ejemplos: *
'* *
'* - Se leern 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 declaracin 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

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Function f_RevisarArgumentos( _
str_Error, _
int_Error _
) 'As Boolean
'***********************************************************************
'* Procedimiento: f_RevisarArgumentos *
'* Tipo : Funcin *
'* Devolucin : Booleana *
'* Fecha y Hora : 2008-03-07 17:10:13 *
'* Autor : Fernando Reyes *
'**
'* Propsito : Esta funcin revisa los argumentos recibidos, *
'* recogiendo los posibles fallos por falta de *
'* argumentos requeridos y almacenando en las *
'* variables correspondientes los argumentos *
'* recibidos. recibe dos parmetros cuyo fin es ser de *
'* salida: una cadena que almacenar los errores *
'* detectados y un entero que almacenar el cdigo 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 *
'* ms de uno se ignorarn aquellos que estn detrs *
'* en la prioridad entre ellos; una caracterstica *
'* clara de lo que es un combo de argumentos es cuando *
'* dos oms argumentos almacenan su valor en la misma *
'* variable). En el caso de producirse ms de un tipo *
'* de error, el nmero 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 estn todos los argumentos


'sin nombre requeridos

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 funcin ser True en caso de
'haber alguno de los errores
bol_Devolucion = (bol_Error1 Or bol_Error2 Or bol_Error4)

'Hacemos la devolucin de la funcin


f_RevisarArgumentos = bol_Devolucion

End Function 'f_RevisarArgumentos

Sub s_Ayuda(str_Error)
'***********************************************************************
'* Procedimiento: s_Ayuda *
'* Tipo : Sub *
'* Devolucin : *
'* Fecha y Hora : 2008-03-07 17:10:14 *
'* Autor : Fernando Reyes *
'**
'* Propsito : Este procedimiento muestra la ayuda en lnea. *
'* Recibe un parmetro de tipo cadena que si viene *
'* ser mostrado antes de la lnea; pensado para que *
'* se muestre un error que se haya detectado. *
'***********************************************************************

'Si hay que mostrar algn texto previo a la ayuda, lo hacemos


If Len(str_Error) > 0 Then

WScript.Echo str_Error & vbCrLf & vbCrLf

End If

'A continuacin, mostramos la ayuda por pantalla


WScript.Echo "Este script permite leer el contenido del libro d" & _
"e Excel que recibe como"
WScript.Echo "parmetro 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 (" & _

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


"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 lnea"
WScript.Echo ""
WScript.Echo ""
WScript.Echo "Ejemplos:"
WScript.Echo ""
WScript.Echo "- Se leern los datos del libro ""e:\datos choriz" & _
"os\gang-chicharron.xls"" y se"
WScript.Echo "considerar que las primeras lneas 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 lneas 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 : Funcin *
'* Devolucin : Objeto ADODB.Connection *
'* Fecha y Hora : 2008-02-29 17:37:13 *
'* Autor : Fernando Reyes *
'**
'* Propsito : Esta funcin recibe la ruta ms nombre de libro de *
'* Excel y devuelve un objeto Conexin de ADODB *
'* conectado a dicho libro de Excel *

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


'***********************************************************************

Dim str_Conexion 'As String


Dim ado_Conexion 'As ADODB.Connection

'Establecemos la cadena de conexin 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 conexin


'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 conexin 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 : Funcin *
'* Devolucin : ADODB.Recordset *
'* Fecha y Hora : 2008-02-29 17:47:10 *
'* Autor : Fernando Reyes *
'**
'* Propsito : Esta funcin recibe una conexin 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 conexin ADODB.Connection. Si se pasa *
'* vaco el parmetro hoja, se crear la consulta que *
'* se reciba con el parmetro str_Consulta *
'***********************************************************************

Dim ado_Recordset 'As ADODB.Recordset

If Len(Trim(str_Hoja)) > 0 Then

str_Consulta = "SELECT " & _


" * " & _
"FROM " & _
" " & str_Hoja

End If

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


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 & _

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


"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

Ejemplo 2

Por ltimo, presento un ejemplo de uso de un libro de Excel desde VBScript sin necesidad de tener instalada
la aplicacin en el equipo. En concreto desarroll esto para enviar determinados informes a determinadas

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


personas de forma programada. Basta con cambiar los registros del libro Excel para que los envos cambien
de destinatario, asunto, adjuntos, etc.

En el ejemplo hay dos ficheros:

Un script que ser el que realice los envos de correos segn los datos que lee del libro de Excel.
Un libro de Excel con los datos de destinatarios, correos, adjuntos, etc.

La estructura del libro consta de las siguientes hojas y campos en ellas:

Informes: hoja con los datos de los informes a enviar. Consta de las columnas:
id_informe (numrico): identificador del informe. Hace de clave primaria de la tabla.
nombre (texto): nombre del informe.
asunto (texto): asunto del correo.
cuerpo (texto): cuerpo del correo.
smtp (texto): URL del servidor SMTP con el que se realizar el envo.
puerto (numrico): puerto TCP del servidor SMTP.
cuenta (texto):cuenta de correo que remite el mensaje.
usuario (texto): nombre de usuario con el que se conecta al servidor SMTP.
clave (texto): contrasea del usuario de conexin.
Ficheros: hoja con los datos correspondientes a los adjuntos de los correos. Consta de las columnas:
id_informe (numrico): identificador del informe. Hace de clave externa a la hoja de informes.
id_fichero (numrico): identificador del fichero en el mensaje. La conjuncin de id_informe e
id_fichero genera la clave primaria de esta hoja.
nombre (texto): ruta y nombre del fichero a adjuntar. Admite caracteres comodn (asterisco,
interrogacin)
archivo (texto): ruta y nombre del archivo ZIP al que se aadir el fichero. De esta manera los
adjuntos sern enviados comprimidos. Para ello es necesario que se instale en el sistema el
ejecutable independiente de 7-Zip, es decir, 7za.exe.
Tres hojas de estrucutra idntica que son Para, CC y CCO. Contienen los datos de los destinatarios en el
campo Para, en el campo con copia y en el campo con copia oculta. Las columnas de las que constan
estas hojas son:
id_informe (numrico): identificador del informe que se enva. Se trata de la clave externa a la
hoja de informes.
destinatario (texto): nombre para mostrar del destinatario.
email (texto): direccin de correo del destinatario.

En el libro he dejado datos de ejemplo que implican que se enven tres informes:

http://freyes.svetlian.com/ADOExcel/ado-excel.htm 14/12/2016 8:39 p. m.


Connection Object

Connection Object
Represents an open connection to a data source.

Remarks
A Connection object represents a unique session with a data source. In the case of a client/server database system, it may be
equivalent to an actual network connection to the server. Depending on the functionality supported by the provider, some
collections, methods, or properties of a Connection object may not be available.

With the collections, methods, and properties of a Connection object, you can do the following:

Configure the connection before opening it with the ConnectionString, ConnectionTimeout, and Mode properties.
ConnectionString is the default property of the Connection object.
Set the CursorLocation property to client to invoke the Microsoft Cursor Service for OLE DB, which supports batch
updates.
Set the default database for the connection with the DefaultDatabase property.
Set the level of isolation for the transactions opened on the connection with the IsolationLevel property.
Specify an OLE DB provider with the Provider property.
Establish, and later break, the physical connection to the data source with the Open and Close methods.
Execute a command on the connection with the Execute method and configure the execution with the
CommandTimeout property.

NoteTo execute a query without using a Command object, pass a query string to the Execute method
of a Connection object. However, a Command object is required when you want to persist the
command text and re-execute it, or use query parameters.

Manage transactions on the open connection, including nested transactions if the provider supports them, with the
BeginTrans, CommitTrans, and RollbackTrans methods and the Attributes property.
Examine errors returned from the data source with the Errors collection.
Read the version from the ADO implementation used with the Version property.
Obtain schema information about your database with the OpenSchema method.

You can create Connection objects independently of any other previously defined object.

You can execute named commands or stored procedures as if they were native methods on a Connection object, as shown
below. When a named command has the same name as that of a stored procedure, invoke the "native method call" on a
Connection object always execute the named command instead of the store procedure.

NoteDo not use this feature (calling a named command or stored procedure as if it were a native method on
the Connection object) in a Microsoft .NET Framework application, because the underlying implementation
of the feature conflicts with the way the .NET Framework interoperates with COM.

Execute a command as a native method of a Connection object

To execute a command, give the command a name using the Command object Name property. Set the Command object's

https://msdn.microsoft.com/en-us/library/ms808744(d=printer).aspx 14/12/2016 8:40 p. m.


Connection Object

ActiveConnection property to the connection. Then issue a statement where the command name is used as if it were a
method on the Connection object, followed by any parameters, then followed by a Recordset object if any rows are
returned. Set the Recordset properties to customize the resulting Recordset. For example:

Dim cnn As New ADODB.Connection


Dim cmd As New ADODB.Command
Dim rst As New ADODB.Recordset
...
cnn.Open "..."
cmd.Name = "yourCommandName"
cmd.ActiveConnection = cnn
...
'Your command name, any parameters, and an optional Recordset.
cnn.yourCommandName "parameter", rst

Execute a stored procedure as a native method of a Connection object

To execute a stored procedure, issue a statement where the stored procedure name is used as if it were a method on the
Connection object, followed by any parameters. ADO will make a "best guess" of parameter types. For example:

Dim cnn As New ADODB.Connection


...
'Your stored procedure name and any parameters.
cnn.sp_yourStoredProcedureName "parameter"

The Connection object is safe for scripting.

This section contains the following topic.

Connection Object Properties, Methods, and Events

See Also
Command Object | Errors Collection | Properties Collection | Recordset Object | Appendix A: Providers

2016 Microsoft

https://msdn.microsoft.com/en-us/library/ms808744(d=printer).aspx 14/12/2016 8:40 p. m.


OLE DB Provider for ODBC

OLE DB Provider for ODBC


This document describes the Microsoft OLE DB Provider for ODBC, explains the procedures for installing, configuring, and
testing the provider, and lists the limitations of the current implementation.

Although using this provider is a convenient way to access data through ODBC data sources, it is possible to obtain better
performance and reliability by using a native provider. For more information about other OLE DB providers written to access
specific data stores, see Microsoft OLE DB Providers Overview, visit the Microsoft Data Access and Storage Developer Center,
or contact your software vendor.

Security Considerations
Review OLE DB Security Best Practices for information about security with OLE DB.

This section contains the following topics:

Version Compliance

Supported Platforms

Implementing the ODBC Providerr

Data Types

Query-Based Updates

Known Limitations

Appendix A: Data Type Conversions

Appendix B: Supported Interfaces

Appendix C: ODBC Provider Properties

2016 Microsoft

https://msdn.microsoft.com/en-us/library/ms712975(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

Accessing Data with ADO


ActiveX Data Objects (ADO) are an easy-to-use yet extensible technology for adding database access to your Web pages. You
can use ADO to write compact and scalable scripts for connecting to OLE DB compliant data sources, such as databases,
spreadsheets, sequential data files, or e-mail directories. OLE DB is a system-level programming interface that provides
standard set of COM interfaces for exposing database management system functionality. With ADO's object model you can
easily access these interfaces (using scripting languages, such as VBScript or JScript) to add database functionality to your
Web applications. In addition, you can also use ADO to access Open Database Connectivity (ODBC) compliant databases.

If you are a scripter with a modest understanding of database connectivity, you will find ADO's command syntax
uncomplicated and easy-to-use. If you are an experienced developer you will appreciate the scalable, high-performance
access ADO provides to a variety of data sources.

For more information about ADO, visit the Data Access Technologies Web site on MSDN.

Creating a Connection String


The first step in creating a Web data application is to provide a way for ADO to locate and identify your data source. This is
accomplished by means of a connection string, a series of semicolon delimited arguments that define parameters such as
the data source provider and the location of the data source. ADO uses the connection string to identify the OLE DB
provider and to direct the provider to the data source. The provider is a component that represents the data source and
exposes information to your application in the form of rowsets.

The following table lists OLE DB connection strings for several common data sources:

Data source OLE DB connection string

Access Provider=Microsoft.Jet.OLEDB.4.0;Data Source=physical path to .mdb file

SQL Server Provider=SQLOLEDB.1;Data Source=path to database on server

Oracle Provider=MSDAORA.1;Data Source=path to database on server

Indexing Service Provider=MSIDXS.1;Data Source=path to file

To provide for backward compatibility, the OLE DB Provider for ODBC supports ODBC connection string syntax. The
following table lists commonly used ODBC connection strings:

Data source driver ODBC connection string

Access Driver={Microsoft Access Driver (*.mdb)};DBQ=physical path to .mdb file

SQL Server DRIVER={SQL Server};SERVER=path to server

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

Oracle DRIVER={Microsoft ODBC for Oracle};SERVER=path to server

Excel Driver={Microsoft Excel Driver (*.xls)};DBQ=physical path to .xls file;


DriverID=278

Excel 97 Driver={Microsoft Excel Driver (*.xls)};DBQ=physical path to .xls


file;DriverID=790

Paradox Driver={Microsoft Paradox Driver (*.db)};DBQ=physical path to .db


file;DriverID=26

Text Driver={Microsoft Text Driver (*.txt;*.csv)};DBQ=physical path to .txt file

Visual FoxPro (with a database Driver= {Microsoft Visual FoxPro Driver};SourceType=DBC;SourceDb=physical


container) path to .dbc file

Visual FoxPro (without a database Driver= {Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDb=physical


container) path to .dbf file

Note:

Connection strings that use a UNC path to refer to a data source located on a remote computer can pose a potential
security issue. To prevent unauthorized access of your data source, create a Windows account for computers requiring
access to the data and then apply appropriate NTFS permissions to the data source.

Advanced Issues to Consider When Designing Web Data Applications


For performance and reliability reasons, it is strongly recommended that you use a client-server database engine for the
deployment of data driven Web applications that require high-demand access from more than approximately 10
concurrent users. Although ADO works with any OLE DB compliant data source, it has been extensively tested and is
designed to work with client server databases such as SQL Server.

ASP supports shared file databases (Access or FoxPro) as valid data sources. Although some ASP examplecodeuse a
shared file database, it is recommended that these types of database engines be used only for development purposes or
limited deployment scenarios. Shared file databases may not be as well suited as client-server databases for very
high-demand, production-quality Web applications.

If you are developing an ASP database application intended to connect to a remote SQL Server database you should also
be aware of the following issues:

Choosing Connection Scheme for SQL Server

You can choose between the TCP/IP Sockets and Named Pipes methods for accessing a remote SQL Server database. With
Named Pipes, database clients must be authenticated by Windows before establishing a connection, raising the possibility
that a remote computer running named pipes might deny access to a user who has the appropriate SQL Server access

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

credentials, but does not have a Windows user account on that computer. Alternatively, connections using TCP/IP Sockets
connect directly to the database server, without connecting through an intermediary computer - as is the case with Named
Pipes. And because connections made with TCP/IP Sockets connect directly to the database server, users can gain access
through SQL Server authentication, rather than Windows authentication.

ODBC 80004005 Error

If the connection scheme for accessing SQL Server is not set correctly, users viewing your database application may receive
an ODBC 80004005 error message. To correct this situation, try using a local named pipe connection instead of a network
named pipe connection if SQL Server is running on the same computer as IIS. Windows Server2003 family security rules
will not be enforced because the pipe is a local connection rather than a network connection, which can be impersonated
by the anonymous user account. Also, in the SQL Server connection string (either in the Global.asa file or in a page-level
script), change the parameter SERVER=server name to SERVER=(local). The keyword (local) is a special parameter
recognized by the SQL Server ODBC driver. If this solution does not work, then try to use a non-authenticated protocol
between IIS and SQL Server, such as TCP/IP sockets. This protocol will work when SQL Server is running locally or on a
remote computer.

Note:

To improve performance when connecting to a remote databases, use TCP/IP Sockets.

SQL Server Security

If you use SQL Server's Integrated or Mixed security features, and the SQL Server database resides on a remote server, you
will not be able to use integrated Windows authentication. Specifically, you cannot forward integrated Windows
authentication credentials to the remote computer. This means that you may have to use Basic authentication, which relies
on the user to provide user name and password information.

For more information about these issues, see the Microsoft Product Support Services Web site.

Connecting to a Data Source


ADO provides the Connection object for establishing and managing connections between your applications and OLE DB
compliant data sources or ODBC compliant databases. The Connection object features properties and methods you can
use to open and close database connections, and to issue queries for updating information.

To establish a database connection, you first create an instance of the Connection object. For example, the following script
instantiates the Connection object and proceeds to open a connection:

<%
'Create a connection object.
Set cnn = Server.CreateObject("ADODB.Connection")
'Open a connection using the OLE DB connection string.
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MarketData

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

\ProjectedSales.mdb"
%>

Note:

The connection string does not contain spaces before or after the equal sign (=).

In this case, the Connection object's Open method refers to the connection string.

Executing SQL Queries with the Connection Object


With the Execute method of the Connection object you can issue commands to the data sources, such as Structured
Query Language (SQL) queries. (SQL, an industry standard language for communicating with databases, defines commands
for retrieving and updating information.) The Execute method can accept parameters that specify the command (or query),
the number of data records affected, and the type of command being used.

The following script uses the Execute method to issue a query in the form of a SQL INSERT command, which inserts data
into a specific database table. In this case, the script block inserts the name Jose Lugo into a database table named
Customers.

<%
'Define the OLE DB connection string.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data
\Employees.mdb"

'Instantiate the Connection object and open a database connection.


Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString

'Define SQL SELECT statement.


strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Jose','Lugo')"

'Use the Execute method to issue a SQL query to database.


cnn.Execute strSQL,,adCmdText + adExecuteNoRecords
%>

Note that two parameters are specified in the statement used to execute the query: adCmdText and
adExecuteNoRecords. The optional adCmdText parameter specifies the type of command, indicating that the provider
should evaluate the query statement (in this case, a SQL query) as a textual definition of a command. The
adExecuteNoRecords parameter instructs ADO to not create a set of data records if there are no results returned to the
application. This parameter works only with command types defined as a text definition, such as SQL queries, or stored

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

database procedures. Although the adCmdText and adExecuteNoRecords parameters are optional, you should specify
theses parameters when using the Execute method to improve the performance of your data application.

Important Note:

ADO parameters, such as adCmdText, need to be defined before you can use them in a script. A convenient way to
define parameters is to use a component type library, which is a file containing definitions for all ADO parameters. To
implement a component type library, it must first be declared. Add the following the <METADATA> tag to your .asp file
or Global.asa file to declare the ADO type library:

<!--METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library" TYPE="TypeLib" UUID="


{00000205-0000-0010-8000-00AA006D2EA4}"-->

For details about implementing component type libraries, see the Using Constants section of the Using Variables and
Constants topic.

In addition to the SQL INSERT command, you can use the SQL UPDATE and , you can use the SQL UPDATE and DELETE
commands to change and remove database information.

With the SQL UPDATE command you can change the values of items in a database table. The following script uses the
UPDATE command to change the Customers table's FirstName fields to Jeff for every LastName field containing the last
name Smith.

<%
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
cnn.Execute "UPDATE Customers SET FirstName = 'Jeff' WHERE LastName = 'Smith'
",,adCmdText + adExecuteNoRecords
%>

To remove specific records from a database table, use the SQL DELETE command. The following script removes all rows
from the Customers table where the last name is Smith:

<%
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
cnn.Execute "DELETE FROM Customers WHERE LastName = 'Smith'",,adCmdText +
adExecuteNoRecords

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

%>

Note:

You must be careful when using the SQL DELETE command. A DELETE command without an accompanying WHERE
clause will delete all rows from a table. Be sure to include a SQL WHERE clause, which specifies the exact rows to be
deleted.

Using the Recordset Object to Manipulate Results


For retrieving data, examining results, and making changes to your database, ADO provides the Recordset object. As its
name implies, the Recordset object has features that you can use, depending on your query constraints, for retrieving and
displaying a set of database rows, or records. The Recordset object maintains the position of each record returned by a
query, thus enabling you to step through results one item at a time.

Retrieving a Record Set


Successful Web data applications employ both the Connection object, to establish a link, and the Recordset object, to
manipulate returned data. By combining the specialized functions of both objects you can develop database applications
to carry out almost any data handling task. For example, the following server-side script uses the Recordset object to
execute a SQL SELECT command. The SELECT command retrieves a specific set of information based on query constraints.
The query also contains a SQL WHERE clause, used to narrow down a query to a specific criterion. In this example, the
WHERE clause limits the query to all records containing the last name Smith from the Customers database table.

<%
'Establish a connection with data source.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data
\Employees.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString

'Instantiate a Recordset object.


Set rstCustomers = Server.CreateObject("ADODB.Recordset")

'Open a recordset using the Open method


'and use the connection established by the Connection object.
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
rstCustomers.Open strSQL, cnn

'Cycle through record set and display the results


'and increment record position with MoveNext method.
Set objFirstName = rstCustomers("FirstName")
Set objLastName = rstCustomers("LastName")

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop

%>

Note that in the previous example, the Connection object established the database connection, and the Recordset object
used the same connection to retrieve results from the database. This method is advantageous when you need to precisely
configure the way in which the link with the database is established. For example, if you needed to specify the time delay
before a connection attempt aborts, you would need to use the Connection object to set this property. However, if you
just wanted to establish a connection using ADO's default connection properties, you could use Recordset object's Open
method to establish a link:

<%
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data
\Employees.mdb"
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
Set rstCustomers = Server.CreateObject("ADODB.Recordset")

'Open a connection using the Open method


'and use the connection established by the Connection object.
rstCustomers.Open strSQL, strConnectionString

'Cycle through the record set, display the results,


'and increment record position with MoveNext method.
Set objFirstName = rstCustomers("FirstName")
Set objLastName = rstCustomers("LastName")
Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop
%>

When you establish a connection using the Recordset object's Open method to establish a connection, you are implicitly
using the Connection object to secure the link. For more information, see Microsoft ActiveX Data Objects (ADO)Help
available from the Microsoft Universal Data Access Web site.

Note:

To significantly improve the performance of your ASP database applications, consider caching the recordset in
Application state. For more information, see Caching Data.

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

It is often useful to count the number of records returned in a recordset. The Open method of the Recordset object
enables you to specify an optional cursor parameter that determines how the underlying provider retrieves and navigates
the recordset. By adding the adOpenKeyset cursor parameter to the statement used to execute the query, you enable the
client application to fully navigate the recordset. As a result, the application can use the RecordCount property to
accurately count the number of records in the recordset. See the following example:

<%
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM NewOrders", "Provider=Microsoft.Jet.OLEDB.3.51;Data
Source='C:\CustomerOrders\Orders.mdb'", adOpenKeyset, adLockOptimistic, adCmdText

'Use the RecordCount property of the Recordset object to get count.


If rs.RecordCount >= 5 then
Response.Write "We've received the following " & rs.RecordCount & " new orders<BR>"

Do Until rs.EOF
Response.Write rs("CustomerFirstName") & " " & rs("CustomerLastName") & "<BR>"
Response.Write rs("AccountNumber") & "<BR>"
Response.Write rs("Quantity") & "<BR>"
Response.Write rs("DeliveryDate") & "<BR><BR>"
rs.MoveNext
Loop

Else
Response.Write "There are less than " & rs.RecordCount & " new orders."
End If

rs.Close
%>

Improving Queries with the Command Object


With the ADO Command object you can execute queries in the same way as queries executed with the Connection and
object you can execute queries in the same way as queries executed with the Connection and Recordset object, except
that with the Command object you can prepare, or compile, your query on the database source and then repeatedly
reissue the query with a different set of values. The benefit of compiling queries in this manner is that you can vastly
reduce the time required to reissue modifications to an existing query. In addition, you can leave your SQL queries partially
undefined, with the option of altering portions of your queries just prior to execution.

The Command object's Parameters collection saves you the trouble of reconstructing your query each time you want to
reissue your query. For example, if you need to regularly update supply and cost information in your Web-based inventory
system, you can predefine your query in the following way:

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

<%
'Open a connection using Connection object. Notice that the Command object
'does not have an Open method for establishing a connection.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data
\Inventory.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString

'Instantiate Command object; use ActiveConnection property to attach


'connection to Command object.
Set cmn= Server.CreateObject("ADODB.Command")
Set cmn.ActiveConnection = cnn

'Define SQL query.


cmn.CommandText = "INSERT INTO Inventory (Material, Quantity) VALUES (?, ?)"

'Save a prepared (or pre-compiled) version of the query specified in CommandText


'property before a Command object's first execution.
cmn.Prepared = True

'Define query parameter configuration information.


cmn.Parameters.Append cmn.CreateParameter("material_type",adVarChar, ,255 )
cmn.Parameters.Append cmn.CreateParameter("quantity",adVarChar, ,255 )

'Define and execute first insert.


cmn("material_type") = "light bulbs"
cmn("quantity") = "40"
cmn.Execute ,,adCmdText + adExecuteNoRecords

'Define and execute second insert.


cmn("material_type") = "fuses"
cmn("quantity") = "600"
cmn.Execute ,,adCmdText + adExecuteNoRecords
.
.
.
%>

Important Note:

ADO parameters, such as adCmdText, are simply variables, this means that before using an ADO parameter in a data
access script you need to define its value. Since ADO uses a large number of parameters, it is easier to define
parameters by means of a component type library, a file containing definitions for every ADO parameter and constant.
For details about implementing ADO's type library, see the Using Constants section of the Using Variables and
Constants topic.

In the previous example, you will note that the script repeatedly constructs and reissues a SQL query with different values,
without having to redefine and resend the query to the database source. Compiling your queries with the Command
object also offers you the advantage of avoiding problems that can arise from concatenating strings and variables to form

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

SQL queries. In particular, by using the Command object's Parameter collection, you can avoid problems related to
defining certain types of string, date, and time variables. For example, SQL query values containing apostrophes (') can
cause a query to fail:

strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Robert','O'Hara')"

Note that the last name O'Hara contains an apostrophe, which conflicts with the apostrophes used to denote data in the
SQL VALUES keyword. By binding the query value as a Command object parameter, you avoid this type of problem.

Combining HTML Forms and Database Access


Web pages containing HTML forms can enable users to remotely query a database and retrieve specific information. With
ADO you can create surprisingly simple scripts that collect user form information, create a custom database query, and
return information to the user. Using the ASP Request object, you can retrieve information entered into an HTML form and
incorporate this information into your SQL statements. For example, the following script block inserts information supplied
by an HTML form into a table. The script collects the user information with the Request object 's Form collection.

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

<%
'Open a connection using Connection object. The Command object
'does not have an Open method for establishing a connection.
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\CompanyCatalog
\Seeds.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString

'Instantiate Command object


'and use ActiveConnection property to attach
'connection to Command object.
Set cmn= Server.CreateObject("ADODB.Command")
Set cmn.ActiveConnection = cnn

'Define SQL query.


cmn.CommandText = "INSERT INTO MySeedsTable (Type) VALUES (?)"

'Define query parameter configuration information.


cmn.Parameters.Append cmn.CreateParameter("type",adVarChar, ,255)

'Assign input value and execute update.


cmn("type") = Request.Form("SeedType")
cmn.Execute ,,adCmdText + adExecuteNoRecords
%>

For more information about forms and using the ASP Request object, see Processing User Input.

Managing Database Connections


One of the main challenges of designing a sophisticated Web database application, such as an online order entry
application that services thousands of customers, is properly managing database connections. Opening and maintaining
database connections, even when no information is being transmitted, can severely strain a database server's resources
and result in connectivity problems. Well designed Web database applications recycle database connections and
compensate for delays due to network traffic.

Timing Out a Connection


A database server experiencing a sudden increase in activity can become backlogged, greatly increasing the time required
to establish a database connection. As a result, excessive connection delays can reduce the performance of your database
application.

With the Connection object's ConnectionTimeout you can limit the amount of time that your application waits before
abandoning a connection attempt and issuing an error message. For example, the following script sets the
ConnectionTimeout property to wait twenty seconds before cancelling the connection attempt:

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

Set cnn = Server.CreateObject("ADODB.Connection")


cnn.ConnectionTimeout = 20
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Inventory.mdb"

The default for the ConnectionTimeout property is 30 seconds.

Note:

Before incorporating the ConnectionTimeout property into your database applications, make sure that your
connection provider and data source support this property.

Pooling Connections
Connection pooling enables your Web application to use a connection from a pool, or reservoir of free connections that do
not need to be reestablished. After a connection has been created and placed in a pool, your application reuses that
connection without having to perform the connection process. This can result in significant performance gains, especially if
your application connects over a network or repeatedly connects and disconnects. In addition, a pooled connection can be
used repeatedly by multiple applications.

OLE DB Session Pooling


OLE DB has a pooling feature, called session pooling, optimized for improving connectivity performance in large Web
database applications. Session pooling preserves connection security and other properties. A pooled connection is only
reused if matching requests are made from both sides of the connection. By default, the OLE DB providers for Microsoft
SQL server support session pooling. This means that you do not have to configure your application, server, or database to
use session pooling. However, if your provider does not support session pooling by default, you need to create a registry
setting to enable session pooling. For more information about session pooling, see the OLE DB 2.0 Software Development
Kit (SDK).

ODBC Connection Pooling


If you want your ODBC driver to participate in connection pooling you must configure your specific database driver and
then set the driver's CPTimeout property in the Windows registry. The CPTimeout property determines the length of time
that a connection remains in the connection pool. If the connection remains in the pool longer than the duration set by
CPTimeout, the connection is closed and removed from the pool. The default value for CPTimeout is 60 seconds.

You can selectively set the CPTimeout property to enable connection pooling for a specific ODBC database driver by
creating a registry key with the following settings:

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\driver-name\CPTimeout = timeout
(REG_SZ, units are in seconds)

For example, the following key sets the connection pool timeout to 180 seconds (3 minutes) for the SQL Server driver.

\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\SQL Server\CPTimeout = 180

Note:

By default, your Web server activates connection pooling for SQL Server by setting CPTimeout to 60 seconds.

Using Connections Across Multiple Pages


Although you can reuse a connection across multiple pages by storing the connection in ASP's Application object, doing
so may unnecessarily keep open a connection open, defeating the advantages of using connection pooling. If you have
many users that need to connect to the same ASP database application, a better approach is to reuse a database
connection string across several Web pages by placing the string in ASP's Application object. For example, you can specify
a connection string in the Global.asa file's Application_OnStart event procedure, as in the following script:

Application("ConnectionString") = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data


\Inventory.mdb"

Then in each ASP file that accesses the database, you can write

<OBJECT RUNAT=SERVER ID=cnn PROGID="ADODB.Connection"></OBJECT>

to create an instance of the connection object for the page, and use the script

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Accessing Data with ADO

cnn.Open Application("ConnectionString")

to open the connection. At the end of the page, you close the connection with

cnn.Close

In the case of an individual user who needs to reuse a connection across multiple Web pages, you may find it more
advantageous to use the Session object rather than the Application object for storing the connection string.

Closing Connections
To make the best use of connection pooling, explicitly close database connections as soon as possible. By default, a
connection terminates after your script finishes execution. However, by explicitly closing a connection in your script after it
is no longer needed, you reduce demand on the database server and make the connection available to other users.

You can use Connection object's Close method to explicitly terminate a connection between the Connection object and
the database. The following script opens and closes a connection:

<%
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data
\Inventory.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
cnn.Close
%>

2016 Microsoft

https://msdn.microsoft.com/en-us/library/ms524771(d=printer,v=vs.85).aspx 14/12/2016 8:41 p. m.


Recordset Object

Recordset Object
Represents the entire set of records from a base table or the results of an executed command. At any time, the Recordset
object refers to only a single record within the set as the current record.

Remarks
You use Recordset objects to manipulate data from a provider. When you use ADO, you manipulate data almost entirely
using Recordset objects. All Recordset objects consist of records (rows) and fields (columns). Depending on the functionality
supported by the provider, some Recordset methods or properties may not be available.

ADODB.Recordset is the ProgID that should be used to create a Recordset object. Existing applications that reference the
outdated ADOR.Recordset ProgID will continue to work without recompiling, but new development should reference
ADODB.Recordset.

There are four different cursor types defined in ADO:

Dynamic cursor allows you to view additions, changes, and deletions by other users; allows all types of movement
through the Recordset that doesn't rely on bookmarks; and allows bookmarks if the provider supports them.
Keyset cursor behaves like a dynamic cursor, except that it prevents you from seeing records that other users add,
and prevents access to records that other users delete. Data changes by other users will still be visible. It always
supports bookmarks and therefore allows all types of movement through the Recordset.
Static cursor provides a static copy of a set of records for you to use to find data or generate reports; always allows
bookmarks and therefore allows all types of movement through the Recordset. Additions, changes, or deletions by
other users will not be visible. This is the only type of cursor allowed when you open a client-side Recordset object.
Forward-only cursor allows you to only scroll forward through the Recordset. Additions, changes, or deletions by
other users will not be visible. This improves performance in situations where you need to make only a single pass
through a Recordset.

Set the CursorType property prior to opening the Recordset to choose the cursor type, or pass a CursorType argument with
the Open method. Some providers don't support all cursor types. Check the documentation for the provider. If you don't
specify a cursor type, ADO opens a forward-only cursor by default.

If the CursorLocation property is set to adUseClient to open a Recordset, the UnderlyingValue property on Field objects is
not available in the returned Recordset object. When used with some providers (such as the Microsoft ODBC Provider for
OLE DB in conjunction with Microsoft SQL Server), you can create Recordset objects independently of a previously defined
Connection object by passing a connection string with the Open method. ADO still creates a Connection object, but it
doesn't assign that object to an object variable. However, if you are opening multiple Recordset objects over the same
connection, you should explicitly create and open a Connection object; this assigns the Connection object to an object
variable. If you do not use this object variable when opening your Recordset objects, ADO creates a new Connection object
for each new Recordset, even if you pass the same connection string.

You can create as many Recordset objects as needed.

When you open a Recordset, the current record is positioned to the first record (if any) and the BOF and EOF properties are

https://msdn.microsoft.com/en-us/library/ms808775(d=printer).aspx 14/12/2016 8:42 p. m.


Recordset Object

set to False. If there are no records, the BOF and EOF property settings are True.

You can use the MoveFirst, MoveLast, MoveNext, and MovePrevious methods; the Move method; and the AbsolutePosition,
AbsolutePage, and Filter properties to reposition the current record, assuming the provider supports the relevant
functionality. Forward-only Recordset objects support only the MoveNext method. When you use the Move methods to visit
each record (or enumerate the Recordset), you can use the BOF and EOF properties to determine if you've moved beyond
the beginning or end of the Recordset.

Before using any functionality of a Recordset object, you must call the Supports method on the object to verify that the
functionality is supported or available. You must not use the functionality when the Supports method returns false. For
example, you can use the MovePrevious method only if Recordset.Supports(adMovePrevious) returns true.
Otherwise, you will get an error, because the Recordset object might have been closed and the functionality rendered
unavailable on the instance. If a feature you are interested in is not supported, Supports will return false as well. In this case,
you should avoid calling the corresponding property or method on the Recrodset object.

Recordset objects can support two types of updating: immediate and batched. In immediate updating, all changes to data
are written immediately to the underlying data source once you call the Update method. You can also pass arrays of values as
parameters with the AddNew and Update methods and simultaneously update several fields in a record.

If a provider supports batch updating, you can have the provider cache changes to more than one record and then transmit
them in a single call to the database with the UpdateBatch method. This applies to changes made with the AddNew, Update,
and Delete methods. After you call the UpdateBatch method, you can use the Status property to check for any data conflicts
in order to resolve them.

NoteTo execute a query without using a Command object, pass a query string to the Open method of a
Recordset object. However, a Command object is required when you want to persist the command text and
re-execute it, or use query parameters.

The Mode property governs access permissions.

The Fields collection is the default member of the Recordset object. As a result, the following two code statements are
equivalent.

Debug.Print objRs.Fields.Item(0) ' Both statements print


Debug.Print objRs(0) ' the Value of Item(0).

When a Recordset object is passed across processes, only the rowset values are marshalled, and the properties of the
Recordset object are ignored. During unmarshalling, the rowset is unpacked into a newly created Recordset object, which
also sets its properties to the default values.

The Recordset object is safe for scripting.

This section contains the following topic.

Recordset Object Properties, Methods, and Events

See Also
Connection Object | Fields Collection | Properties Collection | Appendix A: Providers

2016 Microsoft

https://msdn.microsoft.com/en-us/library/ms808775(d=printer).aspx 14/12/2016 8:42 p. m.

You might also like