You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:MS Access 365中提取StaticDIB类型OLE图像数据的方法

提取MS Access中StaticDIB类型OLE数据为图像文件的解决方案

StaticDIB是设备无关位图的静态OLE封装,Access的Unbound Object Frame没有直接导出为图像文件的内置方法,需要通过VBA结合Windows API解析内存中的DIB结构并写入文件。以下是具体实现方案:

实现步骤与代码

1. 模块中声明Windows API与辅助函数

在Access的标准模块中添加以下代码(适配64位Access 365):

Option Explicit

#If VBA7 Then
    Declare PtrSafe Function GetObject Lib "user32.dll" Alias "GetObjectA" (ByVal hObject As LongPtr, ByVal nCount As Long, lpObject As Any) As Long
    Declare PtrSafe Function GlobalLock Lib "kernel32.dll" (ByVal hMem As LongPtr) As LongPtr
    Declare PtrSafe Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As LongPtr) As Long
    Declare PtrSafe Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr
    Declare PtrSafe Function WriteFile Lib "kernel32.dll" (ByVal hFile As LongPtr, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
    Declare PtrSafe Function CloseHandle Lib "kernel32.dll" (ByVal hObject As LongPtr) As Long
    
    Type BITMAP
        bmType As Long
        bmWidth As Long
        bmHeight As Long
        bmWidthBytes As Long
        bmPlanes As Integer
        bmBitsPixel As Integer
        bmBits As LongPtr
    End Type
    
    Type BITMAPFILEHEADER
        bfType As Integer
        bfSize As Long
        bfReserved1 As Integer
        bfReserved2 As Integer
        bfOffBits As Long
    End Type
    
    Type BITMAPINFOHEADER
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
    End Type
#Else
    ' 兼容32位Access的API声明
    Declare Function GetObject Lib "user32.dll" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    Declare Function GlobalLock Lib "kernel32.dll" (ByVal hMem As Long) As Long
    Declare Function GlobalUnlock Lib "kernel32.dll" (ByVal hMem As Long) As Long
    Declare Function CreateFile Lib "kernel32.dll" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    Declare Function WriteFile Lib "kernel32.dll" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, lpOverlapped As Any) As Long
    Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
    
    Type BITMAP
        bmType As Long
        bmWidth As Long
        bmHeight As Long
        bmWidthBytes As Long
        bmPlanes As Integer
        bmBitsPixel As Integer
        bmBits As Long
    End Type
    
    Type BITMAPFILEHEADER
        bfType As Integer
        bfSize As Long
        bfReserved1 As Integer
        bfReserved2 As Integer
        bfOffBits As Long
    End Type
    
    Type BITMAPINFOHEADER
        biSize As Long
        biWidth As Long
        biHeight As Long
        biPlanes As Integer
        biBitCount As Integer
        biCompression As Long
        biSizeImage As Long
        biXPelsPerMeter As Long
        biYPelsPerMeter As Long
        biClrUsed As Long
        biClrImportant As Long
    End Type
#End If

Const GENERIC_WRITE = &H40000000
Const FILE_SHARE_READ = &H1
Const CREATE_ALWAYS = 2
Const FILE_ATTRIBUTE_NORMAL = &H80

Function ExportStaticDIBToBMP(ctlOLE As Object, savePath As String) As Boolean
    Dim stdPic As StdPicture
    Dim bmp As BITMAP
    Dim bmpFileHeader As BITMAPFILEHEADER
    Dim bmpInfoHeader As BITMAPINFOHEADER
    Dim hFile As LongPtr
    Dim bytesWritten As Long
    Dim dibData() As Byte
    Dim dibSize As Long
    
    On Error GoTo ErrorHandler
    
    ' 确认控件中是StaticDIB类型
    If ctlOLE.Class <> "StaticDIB" Then
        ExportStaticDIBToBMP = False
        Exit Function
    End If
    
    ' 获取StdPicture对象
    Set stdPic = ctlOLE.Object
    
    ' 获取位图信息
    GetObject stdPic.handle, Len(bmp), bmp
    
    ' 构建BITMAPINFOHEADER
    With bmpInfoHeader
        .biSize = Len(bmpInfoHeader)
        .biWidth = bmp.bmWidth
        .biHeight = bmp.bmHeight
        .biPlanes = bmp.bmPlanes
        .biBitCount = bmp.bmBitsPixel
        .biCompression = 0 ' BI_RGB
        .biSizeImage = bmp.bmWidthBytes * bmp.bmHeight
        .biXPelsPerMeter = 0
        .biYPelsPerMeter = 0
        .biClrUsed = 0
        .biClrImportant = 0
    End With
    
    ' 构建BITMAPFILEHEADER
    With bmpFileHeader
        .bfType = &H4D42 ' "BM"标识
        .bfOffBits = Len(bmpFileHeader) + Len(bmpInfoHeader) + IIf(bmp.bmBitsPixel <= 8, 2 ^ bmp.bmBitsPixel * 4, 0)
        .bfSize = .bfOffBits + bmpInfoHeader.biSizeImage
        .bfReserved1 = 0
        .bfReserved2 = 0
    End With
    
    ' 锁定DIB内存并读取像素数据
    Dim dibPtr As LongPtr
    dibPtr = GlobalLock(stdPic.handle)
    If dibPtr = 0 Then
        ExportStaticDIBToBMP = False
        Exit Function
    End If
    
    ReDim dibData(1 To bmpInfoHeader.biSizeImage)
    CopyMemory dibData(1), ByVal dibPtr + Len(bmpInfoHeader), bmpInfoHeader.biSizeImage
    GlobalUnlock stdPic.handle
    
    ' 创建并写入BMP文件
    hFile = CreateFile(savePath, GENERIC_WRITE, FILE_SHARE_READ, ByVal 0&, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
    If hFile = -1 Then
        ExportStaticDIBToBMP = False
        Exit Function
    End If
    
    ' 依次写入文件头、信息头、像素数据
    WriteFile hFile, bmpFileHeader, Len(bmpFileHeader), bytesWritten, ByVal 0&
    WriteFile hFile, bmpInfoHeader, Len(bmpInfoHeader), bytesWritten, ByVal 0&
    WriteFile hFile, dibData(1), UBound(dibData), bytesWritten, ByVal 0&
    
    CloseHandle hFile
    ExportStaticDIBToBMP = True
    
    Exit Function
    
ErrorHandler:
    ExportStaticDIBToBMP = False
    If hFile <> 0 Then CloseHandle hFile
End Function

2. 调用函数导出图像

在表单的代码模块中,比如按钮点击事件里调用:

Private Sub cmdExportImage_Click()
    Dim savePath As String
    savePath = "C:\Temp\exported_image.bmp" ' 替换为实际保存路径
    
    If ExportStaticDIBToBMP(Me.oleUnbound, savePath) Then
        MsgBox "图像保存成功"
    Else
        MsgBox "保存失败"
    End If
End Sub

注:oleUnbound是你的Unbound Object Frame控件名称,需替换为实际控件名。

注意事项

  • 确保Access已启用对VBA宏的信任(文件选项→信任中心→信任中心设置→宏设置)。
  • 代码适配64位Access 365,若使用32位版本,保留#Else块的API声明即可。
  • 保存路径需确保有写入权限,建议结合Application.FileDialog让用户选择保存路径。

内容的提问来源于stack exchange,提问作者BiigJiim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:14:54