none
VB.NET, DataTable con campo tipo DATO ADJUNTO de access 2010 RRS feed

  • Pregunta

  • Hola!! tengo un tabla de Access 2010 con los campos: Codigo, Titulo e Imagen -> este ultimo es tipo dato adjunto.

    Cree una consulta (en Access) que muestra: Codigo, Titulo, Imagen.FileData, Imagen.FileName, Imagen.FileType

    Desde VB.Net, llene un DataTable con la consulta.

    Pero no se como hacer para MOSTRAR el contenido del campo dato adjunto (que es una imagen .jpg para cada registro)

    ¿Alguien me pueden ayudar? GRACIASSSSSSSS

    martes, 3 de noviembre de 2015 19:56

Respuestas

  • "tantrix" escribió:

    > tengo un tabla de Access 2010 con los campos: Codigo, Titulo e Imagen -> este ultimo es tipo dato adjunto.
    >
    > Cree una consulta (en Access) que muestra: Codigo, Titulo, Imagen.FileData, Imagen.FileName, Imagen.FileType
    >
    > Desde VB.Net, llene un DataTable con la consulta.
    >
    > Pero no se como hacer para MOSTRAR el contenido del campo dato adjunto
    > (que es una imagen .jpg para cada registro)
    >

    Hola:

    El problema que yo observo es que el contenido de la matriz de bytes que existe en el campo FileData de la columna Imagen (que según comentas es del tipo Datos adjuntos), no se puede convertir para obtener un objeto del tipo System.Drawing.Image, por motivos que en este momento ignoro por completo a qué se puede deber, por tanto, salvo que haya algo por ahí que indique cómo se puede recuperar un objeto DataTable con los datos de una columna del tipo Datos adjuntos de Access, la solución que yo te voy a explicar pasar por utilizar los objetos de la biblioteca DAO de Microsoft Access, en concreto el método SaveToFile de un objeto Dao.Fields2.

    Si deseas hacer la prueba, referencia en tu proyecto de Visual Basic .NET el ensamblado Microsoft.Office.Interop.Access.Dao.dll. Para ello, selecciona el menú Proyecto --> Agregar referencia..., y en la pestaña Extensiones busca la referencia Microsoft.Office.Interop.Access.Dao que se corresponda con la versión de Microsoft Access que tengas instalada en tu equipo, y que será 12.0 (Access 2007), 14.0 (Access 2010) y 15.0 (Access 2013 y superior).

    Inserta en tu proyecto el siguiente procedimiento:

    Imports Microsoft.Office.Interop.Access
    
        Friend Shared Sub WriteAttachmentData(id As Integer, fileName As String, destinyFileName As String)
    
            ' Verificar el valor de los parámetros
            '
            If (String.IsNullOrEmpty(destinyFileName)) Then
                Throw New ArgumentException("No se ha especificado el archivo de destino.")
            End If
    
            If (String.IsNullOrEmpty(fileName)) Then
                Throw New ArgumentException("No se ha especificado el nombre del archivo que contiene los datos adjuntos.")
            End If
    
            ' Abrimos la base de datos de Access 2007 o superior.
            '
            Dim dbe As New Dao.DBEngine()
    
            ' C:\Carpeta\Database1.accdb
            Dim db As Dao.Database = dbe.OpenDatabase(Ruta completa de la base de datos Access 2007 o superior)
    
            ' Declaramos un objeto Dao.Recordset2.
            Dim rstParent As Dao.Recordset2 = Nothing
    
            ' Especificamos la consulta SQL que deseamos ejecutar.
            '
            Dim sql As String = String.Format(
                "SELECT Imagen.FileData " &
                "FROM NombreTabla " &
                "WHERE Codigo={0} AND Imagen.FileName='{1}'", id, fileName)
    
            Dim data As Byte() = Nothing
    
            Try
                ' Abrimos el objeto Recordset.
                rstParent = DirectCast(db.OpenRecordset(sql), Dao.Recordset2)
    
                ' Referenciamos el único campo que se supone existe en el objeto Recordset abierto.
                Dim fld As Dao.Field2 = DirectCast(rstParent.Fields(0), Dao.Field2)
    
                ' Guardamos en el archivo temporal los datos adjuntos existentes en el campo.
                fld.SaveToFile(destinyFileName)
    
            Finally
                ' Cerramos el objeto Recordset.
                '
                If (Not rstParent Is Nothing) Then
                    rstParent.Close()
                    rstParent = Nothing
                End If
    
                ' Cerramos la base de datos.
                '
                db.Close()
                db = Nothing
    
                dbe = Nothing
    
            End Try
    
        End Sub
    

    Fíjate que en la consulta SQL de selección especificamos el valor del campo Imagen.FileName, porque como bien sabes el campo de Datos adjuntos de un registro o fila cualquiera de la tabla puede contener uno o varios archivos, de ahí que indiquemos qué archivo deseamos recuperar.

    Que no se te olvide especificar la ruta completa de la base de datos de Access en la llamada al método OpenDatabase. Si tu base de datos de Access está protegida con una contraseña, entonces deberás de llamar al método OpenDatabase de un objeto DAO.Workspace:

            ' Abrimos la base de datos de Access 2007 o superior.
            '
            Dim dbe As New Dao.DBEngine()
            Dim ws As Dao.Workspace = dbe.Workspaces(0)
            Dim db As Dao.Database = ws.OpenDatabase("C:\Carpeta\Database1.accdb", False, False, ";pwd=contraseña")

    Y al final del bloque Finally tienes que cerrar el objeto Workspace:

            Finally
                ' Cerramos el objeto Recordset.
                '
                If (Not rstParent Is Nothing) Then
                    rstParent.Close()
                    rstParent = Nothing
                End If

                ' Cerramos la base de datos.
                '
                db.Close()
                db = Nothing

                If (Not ws Is Nothing) Then
                    ws.Close()
                    ws = Nothing
                End If

                dbe = Nothing

            End Try

    Cuando desees recuperar una imagen existente en el campo de Datos adjuntos, llamarías al procedimiento WriteAttachmentData como indico a continuación:

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            If (Not PictureBox1.Image Is Nothing) Then
                ' Destruimos el contenido del control PictureBox.
                PictureBox1.Image.Dispose()
            End If
    
            Try
                ' Nombre del archivo de destino.
                '
                Dim destinyFileName As String = "C:\Temporal\Archivo.jpg"
    
                ' Si existe lo eliminamos.
                '
                ' Comprobamos si existe el archivo especificado.
                '
                If (IO.File.Exists(destinyFileName)) Then
    
                    If (MessageBox.Show("Ya existe un archivo con el mismo nombre. " &
                        "¿Desea sobrescribirlo?",
                        "Grabar archivo",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information) = DialogResult.No) Then
    
                        ' Abandonamos el procedimiento.
                        Return
                    End If
    
                    ' Eliminamos el archivo.
                    IO.File.Delete(destinyFileName)
                End If
    
                ' Obtenemos los datos adjuntos correspondientes al identificador
                ' número 283 con el nombre de archivo Archivo.jpg.
                '
                WriteAttachmentData(283, "Archivo.jpg", destinyFileName)
    
                ' Mostramos la imagen en un control PictureBox.
                '
                PictureBox1.Image = Image.FromFile(destinyFileName)
    
            Catch ex As Exception
                ' Se ha producido un error.
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub
    

    Si todo ha ido bien, se habrá mostrado la imagen en el control PictureBox. ;-)

    Un saludo


    Enrique Martínez Montejo
            [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    miércoles, 4 de noviembre de 2015 20:07
    Moderador

Todas las respuestas

  • Hola tantrix:

    Valida por favor en los siguiente links:

    foros  

    How To Read and Write BLOBs

    Saludos cordiales,


    Camilo Villa

    martes, 3 de noviembre de 2015 22:46
  • Hola Camilo, el primer link lo habia leido, lo probe pero no me funciono, y el segundo mucho no lo entiendo... pense que era mas simple mostrar la imagen guardada como un dato adjunto en un registro!

    Gracias igual x contestar, quizas alguien tenga una manera mas sencilla, seguire buscando...

    Saludos

    miércoles, 4 de noviembre de 2015 1:45
  • "tantrix" escribió:

    > tengo un tabla de Access 2010 con los campos: Codigo, Titulo e Imagen -> este ultimo es tipo dato adjunto.
    >
    > Cree una consulta (en Access) que muestra: Codigo, Titulo, Imagen.FileData, Imagen.FileName, Imagen.FileType
    >
    > Desde VB.Net, llene un DataTable con la consulta.
    >
    > Pero no se como hacer para MOSTRAR el contenido del campo dato adjunto
    > (que es una imagen .jpg para cada registro)
    >

    Hola:

    El problema que yo observo es que el contenido de la matriz de bytes que existe en el campo FileData de la columna Imagen (que según comentas es del tipo Datos adjuntos), no se puede convertir para obtener un objeto del tipo System.Drawing.Image, por motivos que en este momento ignoro por completo a qué se puede deber, por tanto, salvo que haya algo por ahí que indique cómo se puede recuperar un objeto DataTable con los datos de una columna del tipo Datos adjuntos de Access, la solución que yo te voy a explicar pasar por utilizar los objetos de la biblioteca DAO de Microsoft Access, en concreto el método SaveToFile de un objeto Dao.Fields2.

    Si deseas hacer la prueba, referencia en tu proyecto de Visual Basic .NET el ensamblado Microsoft.Office.Interop.Access.Dao.dll. Para ello, selecciona el menú Proyecto --> Agregar referencia..., y en la pestaña Extensiones busca la referencia Microsoft.Office.Interop.Access.Dao que se corresponda con la versión de Microsoft Access que tengas instalada en tu equipo, y que será 12.0 (Access 2007), 14.0 (Access 2010) y 15.0 (Access 2013 y superior).

    Inserta en tu proyecto el siguiente procedimiento:

    Imports Microsoft.Office.Interop.Access
    
        Friend Shared Sub WriteAttachmentData(id As Integer, fileName As String, destinyFileName As String)
    
            ' Verificar el valor de los parámetros
            '
            If (String.IsNullOrEmpty(destinyFileName)) Then
                Throw New ArgumentException("No se ha especificado el archivo de destino.")
            End If
    
            If (String.IsNullOrEmpty(fileName)) Then
                Throw New ArgumentException("No se ha especificado el nombre del archivo que contiene los datos adjuntos.")
            End If
    
            ' Abrimos la base de datos de Access 2007 o superior.
            '
            Dim dbe As New Dao.DBEngine()
    
            ' C:\Carpeta\Database1.accdb
            Dim db As Dao.Database = dbe.OpenDatabase(Ruta completa de la base de datos Access 2007 o superior)
    
            ' Declaramos un objeto Dao.Recordset2.
            Dim rstParent As Dao.Recordset2 = Nothing
    
            ' Especificamos la consulta SQL que deseamos ejecutar.
            '
            Dim sql As String = String.Format(
                "SELECT Imagen.FileData " &
                "FROM NombreTabla " &
                "WHERE Codigo={0} AND Imagen.FileName='{1}'", id, fileName)
    
            Dim data As Byte() = Nothing
    
            Try
                ' Abrimos el objeto Recordset.
                rstParent = DirectCast(db.OpenRecordset(sql), Dao.Recordset2)
    
                ' Referenciamos el único campo que se supone existe en el objeto Recordset abierto.
                Dim fld As Dao.Field2 = DirectCast(rstParent.Fields(0), Dao.Field2)
    
                ' Guardamos en el archivo temporal los datos adjuntos existentes en el campo.
                fld.SaveToFile(destinyFileName)
    
            Finally
                ' Cerramos el objeto Recordset.
                '
                If (Not rstParent Is Nothing) Then
                    rstParent.Close()
                    rstParent = Nothing
                End If
    
                ' Cerramos la base de datos.
                '
                db.Close()
                db = Nothing
    
                dbe = Nothing
    
            End Try
    
        End Sub
    

    Fíjate que en la consulta SQL de selección especificamos el valor del campo Imagen.FileName, porque como bien sabes el campo de Datos adjuntos de un registro o fila cualquiera de la tabla puede contener uno o varios archivos, de ahí que indiquemos qué archivo deseamos recuperar.

    Que no se te olvide especificar la ruta completa de la base de datos de Access en la llamada al método OpenDatabase. Si tu base de datos de Access está protegida con una contraseña, entonces deberás de llamar al método OpenDatabase de un objeto DAO.Workspace:

            ' Abrimos la base de datos de Access 2007 o superior.
            '
            Dim dbe As New Dao.DBEngine()
            Dim ws As Dao.Workspace = dbe.Workspaces(0)
            Dim db As Dao.Database = ws.OpenDatabase("C:\Carpeta\Database1.accdb", False, False, ";pwd=contraseña")

    Y al final del bloque Finally tienes que cerrar el objeto Workspace:

            Finally
                ' Cerramos el objeto Recordset.
                '
                If (Not rstParent Is Nothing) Then
                    rstParent.Close()
                    rstParent = Nothing
                End If

                ' Cerramos la base de datos.
                '
                db.Close()
                db = Nothing

                If (Not ws Is Nothing) Then
                    ws.Close()
                    ws = Nothing
                End If

                dbe = Nothing

            End Try

    Cuando desees recuperar una imagen existente en el campo de Datos adjuntos, llamarías al procedimiento WriteAttachmentData como indico a continuación:

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            If (Not PictureBox1.Image Is Nothing) Then
                ' Destruimos el contenido del control PictureBox.
                PictureBox1.Image.Dispose()
            End If
    
            Try
                ' Nombre del archivo de destino.
                '
                Dim destinyFileName As String = "C:\Temporal\Archivo.jpg"
    
                ' Si existe lo eliminamos.
                '
                ' Comprobamos si existe el archivo especificado.
                '
                If (IO.File.Exists(destinyFileName)) Then
    
                    If (MessageBox.Show("Ya existe un archivo con el mismo nombre. " &
                        "¿Desea sobrescribirlo?",
                        "Grabar archivo",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information) = DialogResult.No) Then
    
                        ' Abandonamos el procedimiento.
                        Return
                    End If
    
                    ' Eliminamos el archivo.
                    IO.File.Delete(destinyFileName)
                End If
    
                ' Obtenemos los datos adjuntos correspondientes al identificador
                ' número 283 con el nombre de archivo Archivo.jpg.
                '
                WriteAttachmentData(283, "Archivo.jpg", destinyFileName)
    
                ' Mostramos la imagen en un control PictureBox.
                '
                PictureBox1.Image = Image.FromFile(destinyFileName)
    
            Catch ex As Exception
                ' Se ha producido un error.
                MessageBox.Show(ex.Message)
    
            End Try
    
        End Sub
    

    Si todo ha ido bien, se habrá mostrado la imagen en el control PictureBox. ;-)

    Un saludo


    Enrique Martínez Montejo
            [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    miércoles, 4 de noviembre de 2015 20:07
    Moderador