Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Is There Any Way to Retrieve an Embedded Picture on an Access Report?

Status
Not open for further replies.

txdave35

Technical User
Nov 20, 2008
122
US
Hey guys,

We've are in a bit of a pickle here at work. We have an Access report that allows users to reprint 1099 forms. Well, the form changed this year, and I've been tasked with editing the report. The problem is the report itself is actually an embedded image file of the 1099 with table fields placed on top of it. I need to be able to open the file and somehow edit it.


Unfortunately, when I got to report problems, and click the elipse button for the picture, it only takes me to my local machine. We can't find the original image file. It looks like we are totally screwed here, but I am hoping maybe someone can offer a suggestion. How does Access retrieve the image if the physical image file no longer exists anyways? Much appreciated.

 
I do not believe there is a way to retrieve it. Why not just scan this years form and embed that?
 
Can you back up the report, open in design view, remove the table fields, then copy and paste the image into a new blank report?
Or paste into a Word doc and save that?

Beir bua agus beannacht!
 
Of course you can ...

An embedded image has PictureData associated with it, which is in fact just the binary representation of the bitmap. So all we need to do is get that into a convenient format for VBA, such as an OLE Picture. We can do this using code slightly adapted from something I put together for the VB6 about 11 years ago (thread222-708828); there are other variants created by others around on the internet.

Code:
[blue]Option Explicit

Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, pclsid As Any) As Long
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long
Private Declare Function OleLoadPicture Lib "olepro32" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj As Any) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Const GMEM_MOVEABLE = &H2

Private Function PictureFromRawBits(bytes() As Byte) As IPicture
    Dim cbMem As Long, hMem As Long, IPic(15) As Byte, istm As Object
    [green]' data length
    [/green]cbMem = (UBound(bytes)) - LBound(bytes) + 1
    [green]' allocate global memory block
    [/green]hMem = GlobalAlloc(GMEM_MOVEABLE, cbMem)
    [green]' copy picture data to global memory block
    [/green]CopyMemory ByVal GlobalLock(hMem), bytes(LBound(bytes)), cbMem
    [green]' reset lock count
    [/green]GlobalUnlock hMem
    [green]' create stream object from global memory
    [/green]CreateStreamOnHGlobal hMem, 1, istm
    [green]' fill the Guid of IPicture interface from its CLSID
    [/green]CLSIDFromString StrPtr("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"), IPic(0)
    [green]' create picture from stream object
    [/green]OleLoadPicture ByVal ObjPtr(istm), 0, 0, IPic(0), PictureFromRawBits
    [green]' free global memory
    [/green]GlobalFree hMem
End Function

Private Function PictureFromPictureData(myPictureData As Variant) As IPicture
    Dim rawbits() As Byte
    rawbits = myPictureData
    Set PictureFromPictureData = PictureFromRawBits(rawbits())
End Function

Public Sub example()
    Dim RecoveredPicture As StdPicture
    Set RecoveredPicture = PictureFromPictureData(Reports.Item(0).Controls(0).PictureData) [green]' or wherever your embedded image is[/green]
    SavePicture RecoveredPicture, "<yourfilename.bmp>"
End Sub[/blue]
 
Here is a slightly easier version. The two functions depend if it is embedded in a control or embedded in a form. It saves the image to the current folder.
Code:
Private Sub Command0_Click()
  'savePictinForm Me.Form
  savePictInControl Me.Image1
End Sub

Public Function savePictInForm(frm As Access.Form)
    Dim fname As String 'The name of the file to save the picture to
    Dim pngImage As String 'Stores the image data as a string
    Dim iFileNum As Double
    
    fname = CurrentProject.Path & "\Temp.png"
   
    iFileNum = FreeFile 'The next free file from the file systemc
    pngImage = StrConv(frm.PictureData, vbUnicode) 'Convert the byte array to a string
    MsgBox "Saved to: " & fname
    'Writes the string to the file
    Open fname For Binary Access Write As iFileNum
        Put #iFileNum, , pngImage
    Close #iFileNum
End Function

Public Function savePictInControl(ctrl As Access.Control)
    Dim fname As String 'The name of the file to save the picture to
    Dim pngImage As String 'Stores the image data as a string
    Dim iFileNum As Double
    
    fname = CurrentProject.Path & "\Temp.png"
   
    iFileNum = FreeFile 'The next free file from the file systemc
    pngImage = StrConv(ctrl.PictureData, vbUnicode) 'Convert the byte array to a string
    MsgBox "Saved to: " & fname
    'Writes the string to the file
    Open fname For Binary Access Write As iFileNum
        Put #iFileNum, , pngImage
    Close #iFileNum
End Function
 
Er ... why png?
I guess you could write a lot of code to figure out the real format from the header.
But in trutch you can basically pick any common extension and will still open. I put in a JPG image and tried the code with .emf, .bmp, .png and it still opened. However, the easiest way to get the real extension is to just use the original file name. That is in the .picture property

Code:
Public Function savePictInControl(ctrl As Access.Control)
    Dim filename As String 'The name of the file to save the picture to
    Dim strImage As String 'Stores the image data as a string
    Dim iFileNum As Double
    Dim realName As String 'The name of the original embedded file
    
    realName = ctrl.Picture
    filename = CurrentProject.Path & "\" & realName
    iFileNum = FreeFile 'The next free file from the file systemc
    strImage = StrConv(ctrl.PictureData, vbUnicode) 'Convert the byte array to a string
    Debug.Print pngImage
    MsgBox "Saved to: " & filename
    'Writes the string to the file
    Open filename For Binary Access Write As iFileNum
        Put #iFileNum, , strImage
    Close #iFileNum
End Function
 
The format held in PictureData is always bmp, no matter what the format (or extension) of the original image file.
 
The format held in PictureData is always bmp, no matter what the format (or extension) of the original image file
No, that is incorrect. It is held in its native format. If you have something that supports otherwise, please provide.
Just to verify I did the following. I ran the above code using an embedded GIF, JPG, BMP, and PNG. However I did not save with any file extensions.
I then ran the four files without extensions through "Analyze It!". It identified all in their correct formats.
 
Interesting. My comment was based on out-of-date info, and I stand corrected.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top