Está en la página 1de 14

Gestionar Imagenes con ADO

Gestionando Imgenes con ADO


El Cdigo ADO para Gestionar Imgenes en una Base de Datos con Visual Basic
Por Harvey Triana, Octubre 2001 Existen ciertos detalles para implementar una interfaz Visual Basic que permita gestionar imgenes en una Base de datos que no estn documentados explcitamente. Este articulo describe la forma de almacenar y recuperar imgenes en una base de datos usando la tecnologa de acceso a datos ADO. Ciertamente las tcnicas usadas con DAO son aplicables a la tecnologa ADO, salvo algunos pequeos cambios. No obstante las clases de reconocimiento de datos de Visual Basic 6.0 suministran un medio ms eficaz para recuperar las imgenes desde cdigo plano, lo que con versiones anteriores de Visual Basic era algo disfrazado e injustificado (necesariamente usamos un control Data en el mejor de los casos).

Tipo de Dato de la Imagen


Necesariamente las imgenes se almacenan en campos binarios en una Base de Datos, sea FoxPro, Oracle, Access, etc. La naturaleza de los formatos de imgenes debe ser interpretada por las capacidades gestoras de herramienta que manipula los datos. Dentro de una base de datos las imgenes son simples stream binarios. El objeto stdPicture de Visual Basic recupera los formatos ms comunes de imagen, sea GIF, JPG, BMP, sin quejarse, no obstante, Visual Basic no suministra un mtodo para archivar una imagen en un formato especifico, solo se limita a mapas de bits de Windows (salvo software de terceras partes). Aun sigo esperando la mejora de la instruccin SavePicture con un parmetro que permita especificar el formato de la imagen con el que se archivar. Normalmente ser deseable archivar las imgenes en las bases de datos en formatos GIF o JPG. La naturaleza comprimida de estos formatos los hace supremamente atractivos para preservar el espacio ocupado por los datos, mientras que un BMP con la misma calidad (digamos 24 bits de profundidad en color), ocupara muchas veces ms espacio, dilatando aun ms el problema cuando se trata con imgenes de gran tamao. Asi pues, en este articulo suministrare el cdigo suficiente para archivar y recuperar en el formato deseado. Este articulo cubre dos aspectos bsicos, (1) Guardar Imgenes un una Base de Datos, y (2) Recuperar Imgenes desde una Bases de Datos.

Guardar Imgenes un una Base de Datos


Partimos en que la fuente de imgenes sern archivos, sin embargo tambin es viable guardar imgenes generadas a partir de mtodos grficos. Inicialmente definimos el mecanismo por el cual daremos la oportunidad al usuario de enviar un archivo de imagen a la base de datos. Yo prefiero usar la capacidad de arrastrar y soltar de Windows, ya que es supremamente fcil y cmodo para el usuario. Aunque si lo prefiere, puede usar un control CommonDialog para que el usuario examine los archivos de una manera ms estndar. Guardar una imagen en una base de datos, bsicamente requiere del procedimiento: PutImageInField para imgenes relativamente pequeas (menos de 100k como regla aproximada) o PutLargeImageInField para imgenes muy grandes. Si almacena GIF o JPG probablemente nunca va a necesitar de PutLargeImageInField. La diferencia bsica de estos procedimientos en que PutLargeImageInField lee el archivo de imagen por lotes, esto con el objetivo de optimizar el uso de memoria. Ambos procedimientos los he colocado en la clase cls_ADOServices que publico a continuacin:

http://vexpert.mvps.org/articles/adoImages.htm (1 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

' ' ' '

CLASS DESCRIPTION AUTHOR LAST REVIEW

: : : :

cls_ADODBServices Some key functions Harvey T. 08/08/99

Option Explicit '//For retrive or store large pictures Private Const nBUFFER As Long = 1024 '//NORMAL IMAGES Public Sub PutImageInField( _ f As ADODB.Field, _ File As String _ ) Dim b() As Byte Dim ff As Long Dim n As Long On Error GoTo ErrHandler ff = FreeFile Open File For Binary Access Read As ff n = LOF(ff) If n Then ReDim b(1 To n) As Byte Get ff, , b() End If Close ff f.Value = b() Exit Sub ErrHandler: MsgBox "ERROR: " & Err.Description End Sub Public Function GetImageFromField( _ f As ADODB.Field _ ) As StdPicture Dim b() As Byte Dim ff As Long Dim File As String On Error GoTo ErrHandler Call GetRandomFileName(File) ff = FreeFile Open File For Binary Access Write As ff b() = f.Value Put ff, , b() Close ff Erase b Set GetImageFromField = LoadPicture(File) Kill File Exit Function ErrHandler: MsgBox "ERROR: " & Err.Description End Function '//LARGE IMAGES Public Sub PutLargeImageInField( _

http://vexpert.mvps.org/articles/adoImages.htm (2 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

f As ADODB.Field, _ File As String _ ) Dim b() As Byte Dim ff As Long Dim i As Long Dim FileLen As Long Dim Blocks As Long Dim LeftOver As Long On Error GoTo ErrHandler ff = FreeFile Open File For Binary Access Read As ff FileLen = LOF(ff) Blocks = Int(FileLen / nBUFFER) LeftOver = FileLen Mod nBUFFER ReDim b(LeftOver) Get ff, , b() f.AppendChunk b() ReDim b(nBUFFER) For i = 1 To Blocks Get ff, , b() f.AppendChunk b() Next Close ff Exit Sub ErrHandler: MsgBox "ERROR: " & Err.Description End Sub Public Function GetLargeImageFromField( _ f As ADODB.Field _ ) As StdPicture Dim Dim Dim Dim Dim Dim Dim b() ff File i FileLen Blocks LeftOver As As As As As As As Byte Long String Long Long Long Long

On Error GoTo ErrHandler Call GetRandomFileName(File) ff = FreeFile Open File For Binary Access Write As ff Blocks = Int(f.ActualSize / nBUFFER) LeftOver = f.ActualSize Mod nBUFFER b() = f.GetChunk(LeftOver) Put ff, , b() For i = 1 To Blocks b() = f.GetChunk(nBUFFER) Put ff, , b() Next Close ff Erase b Set GetLargeImageFromField = LoadPicture(File)

http://vexpert.mvps.org/articles/adoImages.htm (3 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Kill File Exit Function ErrHandler: MsgBox "ERROR: " & Err.Description End Function Public Function RecordLocation( _ adoRs As ADODB.Recordset, _ Optional Title As String = vbNullString _ ) On Error GoTo ErrHandler With adoRs If Not (.EOF Or .BOF) Then RecordLocation = Title & .AbsolutePosition & _ " de " & .RecordCount Else RecordLocation = vbNullString End If End With Exit Function ErrHandler: RecordLocation = "VOID" End Function Public Sub PutPictureInField( _ f As ADODB.Field, _ pic As StdPicture _ ) Dim File As String On Error GoTo ErrHandler Call GetRandomFileName(File) Call SavePicture(pic, File) Call PutImageInField(f, File) Exit Sub ErrHandler: MsgBox "ERROR: " & Err.Description End Sub Private Sub GetRandomFileName(ByRef File As String) Randomize Timer File = App.Path & IIf(Right$(App.Path, 1) = "\", "", "\") & _ Format(Rnd() * 1000000, "00000000") & ".tmp" End Sub Esta clase incluye los procedimientos GetImageFromField, GetLargeImageFromField y RecordLocation. La ultima es solo un detalle de presentacin, mientras que las dos anteriores se usan para recuperar datos de imagen en casos especiales. El procedimiento PutPictureInField se usa cuando se desea archivar en la base de datos una imagen generada por mtodos grficos, o simplemente el valor Picture de un control. Para el primer caso sera: Call adoSrv.PutPictureInField(rs.Fields("My Photo"), picX.Image).

Ejemplo para Almacenar Imgenes en una Base de Datos


El siguiente ejemplo muestra la forma de usar la clase cls_ADOServices y un modo bien tratado de manejar el Recordset de ADO. Todos los ejemplos a continuacin debe tener estas tres referencias: (1) Microsoft ActiveX Data Object 2.1 Library (aplica tambin a la versin 2.0), (2) Microsoft Data Binding Collection, y (3) Microsoft Data Formatting Object Library.
http://vexpert.mvps.org/articles/adoImages.htm (4 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

La siguiente es una imagen del formulario que sigue el ejemplo:

A modo de laboratorio, cre una base de datos nueva en Access con la siguiente estructura: Campo Id Photo Photo Note Tipo Entero Largo Objeto OLE Texto (254) Descripcin Establece la clave principal. Contiene imgenes Alguna descripcin

Le di el nombre PhotosSample.mdb a la base de datos, y la archiv en el mismo directorio de la aplicacin. Use un DataEnvironment (Entorno de Datos) para conectar la base de datos, el cual tiene la siguiente configuracin:

No explico como crear el Entorno de Datos. Si desea informacin, busque Interactuar con datos de una base de datos Microsoft Jet o Microsoft Access en la documentacin MSDN, el cual le guiar paso a paso el modo de crear y usar un DataEnvironment. El nombre del objeto DataEnvironment es datenvPhotos, el cual tiene una nica conexin: cnnPhotosSample, y un solo objeto Command: PhotosQuery, el cual usa la siguiente consulta: SELECT Photos.[Id Photo], Photos.Photo, Photos.Note FROM Photos ORDER BY Photos.[Id Photo]; Finalmente, he habilitado la conexin a la base de datos para que no sea de solo lectura (cuando se crean de forma predeterminada las conexiones son de solo lectura). No necesariamente tiene que crear un DataEnvironment para usar los procedimientos de este articulo, puede recrear el ejemplo usando otro mecanismo de conexin como un ADO.Recordset simple o un Control ADODC (realmente prefiero evitar el control ADODC, que por dems es incompatible con ADO 2.1).
http://vexpert.mvps.org/articles/adoImages.htm (5 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Los controles y disposicin de este ejemplo se muestran el la imagen de formulario, y siguen esta configuracin: Control PictureBox Label Label TextBox CommandButton (array de 0 a 3) CommandButton CommandButton CommandButton Nombre picPhoto lblImageFieldSize lblIdPhoto txtNote cmdMoveRecord cmdAdd cmdDelete cmdClose Captions: Fisrt, Previous, Next, Last Caption: Add Caption: Delete Caption: Close Otras propiedades OLEDropMode=1 BorderStyle=1 BorderStyle=1 Note DataField Photo Id Photo

Los Controles con DataField definido tienen: DataSource = datenvPhotos y DataMember = PhotosQuery Use el siguiente cdigo en el mdulo del formulario: ' ' ' ' ' FORM : frmPhotosSample DESCRIPTION : Muestra de almacenar/recuperar formatos grficos en una base de datos AUTHOR : Harvey T. LAST REVIEW : 08/08/99

Option Explicit Private WithEvents rs As ADODB.Recordset '//Referencia al Recordset del '//DataEnvironment Private adoSrv As cls_ADODBServices '//Servicios de funciones Private Sub cmdAdd_Click() On Error GoTo ErrHandler '//Crea un registro y lo actualiza automticamente rs.AddNew rs("Id Photo") = Int(100000 * Rnd) '//Clave falsa rs("Note") = "Void Note" '//imagen predeterminada Call adoSrv.PutImageInField(rs.Fields("Photo"), _ App.Path + "\i_doc.gif") rs.Update ActiveControls True rs.MoveLast Exit Sub ErrHandler: MsgBox "ERROR: " & Err.Description End Sub Private Sub cmdClose_Click() Unload Me End Sub Private Sub cmdDelete_Click() rs.Delete adAffectCurrent

http://vexpert.mvps.org/articles/adoImages.htm (6 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

If rs.RecordCount Then rs.MoveLast Else ActiveControls False, "cmdAdd" End If End Sub Private Sub cmdMoveRecord_Click(Index As Integer) picPhoto.SetFocus With rs Select Case Index Case 0 '//First If .AbsolutePosition > 1 Then .MoveFirst End If Case 1 '//Previous If .AbsolutePosition > 1 Then .MovePrevious End If Case 2 '//Next If .AbsolutePosition < .RecordCount Then .MoveNext End If Case 3 '//Last If .AbsolutePosition < .RecordCount Then .MoveLast End If End Select End With End Sub Private Sub Form_Load() Set adoSrv = New cls_ADODBServices Set rs = datenvPhotos.rsPhotosQuery If rs.RecordCount = 0 Then ActiveControls False, "cmdAdd" Else Call MoveComplete End If End Sub Private Sub Form_Unload(Cancel As Integer) Set rs = Nothing Set adoSrv = Nothing End Sub Private Sub ActiveControls( _ Action As Boolean, _ ParamArray Exeptions() As Variant _ ) Dim v As Variant Dim ctlName As String Dim Use As Boolean Dim ctl As Control On Error Resume Next For Each ctl In Controls ctlName = ctl.Name Use = True

http://vexpert.mvps.org/articles/adoImages.htm (7 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

For Each v In Exeptions If ctlName = v Then Use = False Exit For End If Next If Use Then If Not ctl.Enabled = Action Then ctl.Enabled = Action End If End If Next End Sub Private Sub picPhoto_OLEDragDrop( _ Data As DataObject, _ Effect As Long, _ Button As Integer, _ Shift As Integer, _ x As Single, Y As Single _ ) '//Filtra If InStr(".bmp.gif.jpg", LCase$(Right$(Data.Files(1), 4))) Then '//Guarda en la base de datos Call adoSrv.PutImageInField(rs.Fields("Photo"), Data.Files(1)) rs.Update End If '//NOTA. Para imagenes grandes usar: 'Call adoSrv.PutLargeImageInField(rs.Fields("Photo"), Data.Files(1)) 'rs.Update 'rs.Move 0 '//Muestra la imagen End Sub Private Sub rs_MoveComplete( _ ByVal adReason As ADODB.EventReasonEnum, _ ByVal pError As ADODB.Error, _ adStatus As ADODB.EventStatusEnum, _ ByVal pRecordset As ADODB.Recordset _ ) Call MoveComplete End Sub Private Sub MoveComplete() If Not (rs.EOF Or rs.BOF) Then Caption = adoSrv.RecordLocation(rs, "Photo: ") lblImageFieldSize = "Bytes stored = " & _ rs.Fields("Photo").ActualSize End If End Sub Estimado lector, si es un programador relativamente nuevo en ADO, el anlisis del cdigo del modulo anterior, frmPhotosSample, le mostrar muchos detalles. Este cdigo es slido y muestra el modo correcto de manejar un objeto Recordset de ADO con cdigo. Note que el procedimiento de adicionar un registro, en el evento clic del Control cmdAdd, crea el registro fsicamente, es decir, no deja en modo de cache el nuevo registro. Esto da seguridad y estabilidad a la base de datos. Note tambin, que se dan valores predeterminados a los Campos de la base de datos, en particular, se enva una imagen pequea a la base de datos (por favor indique un archivo de imgen cualquiera en su disco), esto con el propsito de asegurar que eventualmente no queden el Campo de la imagen vaco (lo que posiblemente traera problemas subsecuentes al usar la bases de datos). Se busca estabilidad.

http://vexpert.mvps.org/articles/adoImages.htm (8 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Recuperar Imgenes desde una Bases de Datos


Si es usuario de alguna versin anterior a Visual Basic 6.0 y desea leer las imgenes desde cdigo, tiene la alternativa de emplear los procedimientos GetImageFromField y GetLargeImageFromField de la clase cls_ADOServices. Estas funciones devuelven un objeto stdPicture; por ejemplo para cargar una imagen en un control PictureBox usara: Set pic.Picture = GetImageFromField(rsX. Fields("Mi Imagen")). Necesariamente estas funciones no tienen gran rendimiento dado que leen el valor del campo de la base de datos, crean una archivo y vierten el contenido de bytes, para finalmente recuperarlo con LoadPicture. Esta estrategia no es atractiva si debe a leer muchas imgenes al tiempo. Una alternativa es usar una conexin Recordset en un formulario no visible con un control Image enlazado al campo fuente de las imgenes. Luego empaquetamos este formulario en una clase y le damos la capacidad de leer y suministrar las imgenes a travs de procedimientos en una interfaz de propiedades. Realmente esta tcnica no es cdigo elegante tal y como le espera un programador de clases. Francamente esta es la mejor alternativa con Visual Basic 5.0. Visual Basic 6.0 resuelve este problema eficazmente dadas las capacidades del objeto Recordset de ADO junto a un objeto BindingsCollection y, para usar sin interfaz de usuario, una clase de reconocimiento de datos. Francamente, los procedimientos GetImageFromField y GetLargeImageFromField pasan a ser pieza histrica de coleccin, pues ya no se necesitaran ms. Por dems, las clases de reconocimiento de datos suministran un contexto ms avanzado para un diseo Cliente-Servidor con una arquitectura multicapa. Inicialmente dar un bosquejo de como luce un cliente que lee imgenes con un simple Recordset y un ObjetoBindingCollection. Luego sugiero como escribir una clase de receptora de datos y la forma de usarla en el cliente Leyendo Imgenes con un Simple Recordset Mostrar las imgenes y otros datos en un Formulario bsicamente requiere de lo siguiente: Crear un objeto Recordset, un objeto BindingCollection, y enlazar los controles. Una alternativa ms simple es usar un DataEnvironmet, tal y como se presento en la primera parte de este articulo. Para los siguientes ejemplos cree un formulario con dos controles: Un Image con nombre imgPhoto, y un Label con nombre lblNote. El siguiente mdulo es para el formulario, muestra la arquitectura ms simple de usar un Recordset de ADO, y vincular algunos Controles a Campos del mismo: ' ' ' ' ' FORM : frmTestRecordset DESCRIPTION : La forma de accesar imagenes desde un Recordset de ADO y vincular los Campos a Controles AUTHOR : Harvey T. LAST MODIFY : -

Option Explicit Private WithEvents rs As ADODB.Recordset Private bcl As BindingCollection Private Sub Form_Load() Call InitRecordset Call DoBindings End Sub Private Function InitRecordset() Dim cnn As Connection Dim cmd As Command Set cnn = New Connection Set cmd = New Command Set rs = New Recordset '//Database command connection cnn.Open "Provider=Microsoft.Jet.OLEDB.3.51;" & _ "Data Source=PhotosSample.mdb;" With cmd

http://vexpert.mvps.org/articles/adoImages.htm (9 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Set .ActiveConnection = cnn .CommandType = adCmdText .CommandText = "SELECT [Id Photo], Photo, Note FROM Photos;" End With With rs .CursorLocation = adUseClient .Open cmd, , adOpenForwardOnly, adLockReadOnly Set cmd.ActiveConnection = Nothing Set cmd = Nothing Set .ActiveConnection = Nothing End With cnn.Close Set cnn = Nothing End Function Private Sub Form_Unload(Cancel As Integer) If Not rs Is Nothing Then rs.Close End If End Sub Public Sub DoBindings() Dim df As StdDataFormat Set bcl = New BindingCollection Set df = New StdDataFormat Set bcl.DataSource = rs bcl.Add lblNote, "Caption", "Note" df.Type = fmtPicture bcl.Add imgData, "Picture", "Photo", df Set df = Nothing End Sub Private Sub lblNote_Click() '//only as sample If rs.AbsolutePosition < rs.RecordCount Then rs.MoveNext End If End Sub Cuando se da clic en el Label, el registro se mueve al siguiente. Esto es solo para muestra. La parte ms relevante del cdigo anterior, en lo que concierne a este articulo, es la forma en que se debe enlazar la propiedad Picture del control al campo de la base de datos. Note que requerimos de una instancia del objeto stdDataFormat en el mtodo Add del objeto BindingCollection. Este diseo simple muestra que para leer la imagen necesita un enlace a un control que suministre una propiedad del tipo stdPicture, tal como PictureBox o Image (si el Recordset es de solo lectura, es recomendado usar un control Image, ya que este es ms liviano y por tanto entrega mejor rendimiento que PictureBox). Bien, qu tal si desea leer las imgenes para usar en otro contexto que no sea mostrar la foto?. La respuesta es usar una clase de reconocimiento de datos que reciba los datos a travs de una propiedad del tipo stdPicture. Usando una Clase Receptora de Datos Usaremos una clase receptora de datos cuando no necesitamos desplegar las imgenes en un control, es decir sin interfaz de usuario. Aunque como muestra el siguiente ejemplo, leo las imgenes con una clase receptora de datos y las muestro en un control
http://vexpert.mvps.org/articles/adoImages.htm (10 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Image, con el propsito de demostrar que se estn leyendo correctamente los datos. La clase simple Receptora de Datos se construye empezando por fijar la propiedad (en tiempo de diseo) DataBindingBehavior = 1 (vbSimpleBound). El cdigo de la clase luce de la siguiente manera: ' ' ' ' ' ' CLASS : cls_PictureConsumer DESCRIPTION : Una clase receptora de datos, de los cuales una columna son imagenes AUTHOR : Harvey T. LAST MODIFY : NOTE : DataBindingBehavior = 1 (vbSimpleBound)

Option Explicit '//Data fields Private m_Picture As StdPicture Private m_Note As String Public Property Get Picture() As StdPicture Set Picture = m_Picture End Property Public Property Set Picture(v As StdPicture) Set m_Picture = v End Property Public Property Get Note() As Variant Note = m_Note End Property Public Property Let Note(v As Variant) m_Note = v End Property Note que se crean propiedades para suministrara los datos del Recordset. Estas propiedades tambin suelen servir de enlaces a Controles con esta capacidad (DataBound), los que es comn en soluciones para Web. El cliente de la clase receptora puede seguir este modelo, segn el ejemplo: ' ' ' ' ' FORM : frmTestClass DESCRIPTION : La forma de accesar imagenes desde un Recordset de ADO y vincular a una clase lectora de datos AUTHOR : Harvey T. LAST MODIFY : -

Option Explicit Private rs As ADODB.Recordset '//Source Private bcl As BindingCollection '//Data Binding Private dc As cls_PictureConsumer '//Consumer Private Sub Form_Load() Call InitRecordset Call DoBindings Call ShowData End Sub Private Sub ShowData() '//Procedimiento solo para mostrar los datos Set imgData.Picture = dc.Picture

http://vexpert.mvps.org/articles/adoImages.htm (11 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

lblNote.Caption = dc.Note End Sub Private Function InitRecordset() Dim cnn As Connection Dim cmd As Command Set cnn = New Connection Set cmd = New Command Set rs = New Recordset '//Database command connection cnn.Open "Provider=Microsoft.Jet.OLEDB.3.51;" & _ "Data Source=PhotosSample.mdb;" With cmd Set .ActiveConnection = cnn .CommandType = adCmdText .CommandText = "SELECT [Id Photo], Photo, Note FROM Photos;" End With With rs .CursorLocation = adUseClient .Open cmd, , adOpenForwardOnly, adLockReadOnly Set cmd.ActiveConnection = Nothing Set cmd = Nothing Set .ActiveConnection = Nothing End With cnn.Close Set cnn = Nothing End Function Private Sub Form_Unload(Cancel As Integer) Set dc = Nothing If Not rs Is Nothing Then rs.Close End If End Sub Public Sub DoBindings() Dim df As StdDataFormat Set dc = New cls_PictureConsumer Set bcl = New BindingCollection Set df = New StdDataFormat Set bcl.DataSource = rs bcl.Add dc, "Note", "Note" df.Type = fmtPicture bcl.Add dc, "Picture", "Photo", df Set df = Nothing End Sub Private Sub lblNote_Click() '//Procedimiento solo para mostrar los datos If rs.AbsolutePosition < rs.RecordCount Then rs.MoveNext ShowData End If End Sub

http://vexpert.mvps.org/articles/adoImages.htm (12 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

Note que el cdigo es similar al caso de lectura desde un simple Recordset, salvo que fue cambiada la recepcin de datos, en este caso ya no son los controles enlazados imgData y lblNote, es la clase consumidora de datos que suministra dos propiedades: Picture y Note. En este caso el Cliente (el formulario) suministra la fuente de datos a travs de un Recordset de ADO. En un diseo ClienteServidor normalmente esta fuente de datos ser otra clase de reconocimiento de datos, ms exactamente una Clase Origen de Datos (Data Source). Realmente extendera bastante este escrito al colocar el cdigo completo de un ejemplo de estas caractersticas, pero las bases estn dadas en este escrito.

El problema de las Imgenes Capturadas con Controles OLE


La tecnologa OLE es un mecanismo para usar fuentes binarias heterogneas como origen de datos. Por ejemplo, las imgenes almacenadas en aplicaciones de Microsoft Access guardan los datos en un formato que solo entiende el Control OLE intrnseco de Visual Basic. No s porque razn este control aun no es compatible con ADO (es increble dado que la tecnologa de fondo es OLE DB). Consultar el articulo ID: Q191103 (BUG: ADO Bound OLE Control Does Not Display Bitmap) de MSDN para detalles. Realmente este es un problema incomodo. Un programador Visual Basic para leer las imgenes guardadas por aplicaciones de Access debe valerse de artificios para resolver el problema. El articulo Q191103 menciona que una solucin es usar los mtodos AppendChunk y GetChunk para recuperar y almacenar en forma binaria. Es decir, en teora la solucin que dan los procedimientos GetImageFromField y GetLargeImageFromField de la clase cls_ADOServices, no obstante lo intente y se producen errores de imagen no vlida. Aun espero una respuesta de a este extrao comportamiento. Necesariamente tendremos que usar DAO y el control OLE, pero esta no es una buena solucin para aplicaciones de carga exigente (por ejemplo una solucin para el Web). Asi pues, esperemos un Control OLE compatible con ADO. Por esto y otros aspectos, no recomiendo gestionar imgenes con controles OLE, el rendimiento (y en algunos casos la calidad) es mucho menor comparado con las tcnicas descritas en la primera parte de este articulo.

NOTA. 1. Los ejemplos expuestos anteriormente, no trabajan cuando la imagen tiene ms de 64kb. Esto es debido a un BUG con el proveedor OLE DB Jet 3.51. El problema se soluciona usando el proveedor Jet 4.0 (Access2000) o usando una conexin OBDC como se muestra a continuacin: Reemplazar: '//Database command connection cnn.Open "Provider=Microsoft.Jet.OLEDB.3.51;Data Source=PhotosSample.mdb;" Por: '//Database command connection gsMainConn = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=PhotosSample.mdb;" Ms detalles en: FIX: ADO: Unable To Update Memo Field > 64K In Access Database ( http://support.microsoft.com/support/kb/articles/q198/5/32.asp ) 2. El procedimiento PutLargeImageInField no es necesario, debe usar PutImageInField en todos los casos. Esto debido a que se emplean array de Bytes en vez de Strings para cargar los paquetes binarios.

DESCARGA: PhotosSample.zip (92 kb), contiene la bases de datos PhotosSample.mdb, y el primer ejemplo de este articulo.

http://vexpert.mvps.org/articles/adoImages.htm (13 de 14)05/12/2011 18:59:43

Gestionar Imagenes con ADO

NOTA. Desde la versin ADO 2.5 se incorpora el objeto Stream, el cual hace ms efectivo el manejo de la fuente binaria de la imagen en memoria, sin tener que crear un fichero pala la transferencia de datos.

http://vexpert.mvps.org/articles/adoImages.htm (14 de 14)05/12/2011 18:59:43

También podría gustarte