将 jpg BLOB 从 Access 365 查询传递到 VBA 函数的问题

Posted

技术标签:

【中文标题】将 jpg BLOB 从 Access 365 查询传递到 VBA 函数的问题【英文标题】:Problems Passing a jpg BLOB from an Access 365 Query to a VBA function 【发布时间】:2019-09-05 11:54:17 【问题描述】:

我在 ESRI SDE/MS SQL 表中有 BLOB jpeg,我在 MS Access 数据库中链接到该表。我想我已经编写了一个 VBA 函数(如下),它将(我认为)将它们卸载到我的 Temp 目录。使用包含嵌入式 DAO SQL 查询(此处未共享)的此代码的变体,我可以成功卸载照片。

我不想编写 3 个不同的函数来解释点、线和多边形,而是想在 Access 查询中调用该函数,将两个不同的整数值和 BLOB 字段内容传递给它。

在构建 Access 查询时,我将三个参数传递给函数,但它从未真正调用过该函数。在同一个查询中,我成功调用了一个不同的函数来传递数据。我很困惑为什么在我的 Access 查询中调用这个函数:

PicFileLoc: Blob2File([Landfill_InspectionPoint_Attach_vw].[ATTACHMENTID],[Landfill_InspectionPoint_Attach_vw].[DATA],[Landfill_InspectionPoint_evw].[ItemNo])

不调用此函数。我错过了什么明显的东西? BLOB 不能传递给用户定义的函数吗?如果我将 blbData 的数据类型从 Byte 更改为 String,代码开始运行,但它显然会失败,因为 BLOB 不是字符串。

Public Function Blob2File(ByVal intAttID As Integer, ByVal blbData As Byte, ByVal intItemNo As Integer) As String
    On Error GoTo Blob2FileError
    Dim strFile As String
    Dim nFileNum As Integer
    Dim abytData As Byte
    abytData = blbData
    Blob2File = Null

    strFile = Environ$("USERPROFILE") & "\Local Settings\Temp\" & intItemNo & "_Pic_" & intAttID & ".jpg" 'placed in the users temp directory on the local c drive.
    nFileNum = FreeFile
    Open strFile For Binary Access Write As nFileNum
    Put #nFileNum, , abytData
    Blob2File = strFile

Blob2FileExit:
    If nFileNum > 0 Then Close nFileNum
    Exit Function

Blob2FileError:
    MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
           "Error writing file in Blob2File"
    Blob2File = Null
    Resume Blob2FileExit

End Function

谢谢,

戴尔

【问题讨论】:

正如 Erik 所写,查询并不是一个好方法。请改用 Recordset 循环。 【参考方案1】:

你允许你的 blob 数据只有一个字节,而它是一个字节数组。

通过在声明中的名称和函数调用中的类型加上 () 将其更改为字节数组:

Public Function Blob2File(ByVal intAttID As Integer, ByVal blbData As Byte(), ByVal intItemNo As Integer) As String
    On Error GoTo Blob2FileError
    Dim strFile As String
    Dim nFileNum As Integer
    Dim abytData() As Byte
    abytData = blbData
    Blob2File = Null

    strFile = Environ$("USERPROFILE") & "\Local Settings\Temp\" & intItemNo & "_Pic_" & intAttID & ".jpg" 'placed in the users temp directory on the local c drive.
    nFileNum = FreeFile
    Open strFile For Binary Access Write As nFileNum
    Put #nFileNum, , abytData
    Blob2File = strFile

Blob2FileExit:
    If nFileNum > 0 Then Close nFileNum
    Exit Function

Blob2FileError:
    MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
           "Error writing file in Blob2File"
    Blob2File = Null
    Resume Blob2FileExit

End Function

请注意,我强烈建议不要在查询中写入文件。数据库引擎可能会根据各种条件多次调用该函数,或者如果它决定只显示部分记录直到全部显示,则根本不调用该函数。

【讨论】:

感谢 Erik 和 Andre 的帮助。您对将函数声明更改为: ``ByVal blbData() as Byte ```` 帮助它的修订是正确的。代码运行并写入一个不是 jpg 的文件。但是,我见过的该函数的所有其他示例都将 blbData 作为对象引入。当我进行更改时,该函数永远不会被调用。 我认为 Object 是 VBA 的基本元素,不需要添加任何引用。顺便说一句,这将是许多不同表的反复出现的问题,这就是我传递 Recordsets 并选择这条路线的原因。我的表有不同的字段。 另外,它写入的 jpg 文件大小是 SQL 表中报告的大小的两倍。 如果是字节数组,将 BLOB 作为对象引入是完全错误的。首先缩小问题范围:传递给函数的数据是否与 JPEG 数据相同?写入文件的数据是否与传递给函数的数据相同?最后一个条件可以通过写入数据后读回来检查,第一个可以通过直接查看SQL server表或创建一个易于识别的数据的测试记录来检查。 所以,我不确定它是否真的是一个字节数组。我一直在尝试从这里调整 FileToBlob 代码:link 这是我试图将其作为对象引入的地方。在 SQL 表中,它是一个 varbinary(MAX) 字段。这是一个 jpg 文件,当我完成整个记录集过程时,我可以取出照片,但我试图避免为每个有照片的表创建 VBA 函数。相反,我希望创建一个可以从我当时需要的任何查询(用于报告)中调用的函数。谢谢。【参考方案2】:

所以,为了结束循环,我已经让函数按我的意愿工作了。需要明确的是,由于可以在最不期望的时候调用代码,因此使用 RecordSet 是一种理想的方法,但是由于我的时间有限并且它有效,所以我按原样使用它,我将在下面分享它。

当我与 VBA 斗争并试图了解应该发生什么时,我将 Byte 数组更改为字符串,然后很方便地忘记了这一点。所以一旦 Erik 提供了 Byte Array 的信息,我应该已经准备好了,但是我忘记了我已经对我传递的内容进行了更改。

我正在使用手机拍摄需要修复的垃圾填埋场现场状况的 jpeg 图片。在 ESRI 的 ArcGIS Collector 中,它将照片存储在一个相关的表中,它们被困在 ESRI 的生态系统中。我将此功能用作生成显示照片和说明的 Access 报告的步骤之一。

这是来自 Access 查询的函数调用:

PicFileLoc: Blob2File([ATTACHMENTID],[DATA],[ItemNo])

这就是函数:

Public Function Blob2File(ByVal intAttID As Integer, ByRef blbData() As Byte, ByVal intItemNo As Integer) As String
    On Error GoTo Blob2FileError
    'This function is based off of this link: http://www.ammara.com/access_image_faq/read_write_blob.html
    'and modified for my needs.  Dale R. Bridgford 2019-09-06
    Dim strFile As String
    strFile = Environ$("USERPROFILE") & "\Local Settings\Temp\" & intItemNo & "_Pic_" & intAttID & ".jpg" 'placed in the users temp directory on the local c drive.
    Dim nFileNum As Integer
    Dim abytData() As Byte
    Blob2File = ""
    nFileNum = FreeFile
    abytData = blbData
    Open strFile For Binary Access Write As nFileNum
    Put #nFileNum, , abytData

    Blob2File = strFile 'passes back the path and filename of photo.

Blob2FileExit:
    If nFileNum > 0 Then Close nFileNum
    Exit Function

Blob2FileError:
    MsgBox "Error " & Err.Number & ": " & Err.Description, vbCritical, _
           "Error writing file in Blob2File"
    Blob2File = ""
    Resume Blob2FileExit

End Function

感谢所有帮助过我的人。

戴尔

【讨论】:

以上是关于将 jpg BLOB 从 Access 365 查询传递到 VBA 函数的问题的主要内容,如果未能解决你的问题,请参考以下文章

将数据从 Azure DWH 复制到 Azure 中的 Dynamics 365

MS Access 365 - 创建包含链接文件的子表单

Access 2007,VBA:将 BLOB 插入链接表时出现奇怪的错误

使用 Visual Basic 将 BLOB(图像)文件存储到 MS Access

将 access mde 从 32 位转换为 64 位

如何在oracle中的blob字段下读取jpg格式文件保存