使用 VBA 在 Access 字段中保存 OLE 对象

Saving OLE Objects in Access field with VBA

我知道这个主题已被广泛涉及,但我无法找到解决我的特定问题的方法。

我有一个 table,其列 Attachments 的 OLE 对象数据类型。 table 的后端是 SQL Server table,Attachments 列的数据类型为 VARBINARY(MAX)。

如果我右键单击 Access 中的 附件 字段,会弹出一个菜单,其中包含 插入对象... 按照这个路径,我可以在字段中插入一个文件。

以这种方式插入的文件只需双击该字段即可打开进行查看和编辑。

现在。我需要使用 VBA 做同样的事情。我需要获取文件列表并将它们插入适当行的 Attachments 字段中。这应该不是一项艰巨的任务,因为众所周知如何使用 ADODB.Stream 在字段中插入文件。以下是尝试概念的简单代码:

Private Sub POC()

    Dim db As DAO.Database
    Dim rsa As DAO.Recordset
    Dim stream As ADODB.stream

    Set db = CurrentDb()
    Set rsa = db.OpenRecordset("ZipCodeAttachments", dbOpenDynaset, dbSeeChanges)

    rsa.MoveFirst
    rsa.MoveNext

    rsa.Edit

    Set stream = New ADODB.stream
    stream.Type = adTypeBinary
    stream.Open
    stream.LoadFromFile Application.CurrentProject.Path & "\Attachments7.zip"

    rsa.Fields("Attachments").value = stream.Read

    rsa.Update
    rsa.Close

    Set rsa = Nothing
    Set dba = Nothing
End Sub

代码在第二行的 Attachments 字段中插入一个文件。我可以验证该值已通过 SSMS 添加。但是,当我像之前对第一行所做的那样尝试打开字段进行查看和编辑时,这次我收到错误消息:

很明显,VBA保存文件的方式有问题。

我做错了什么?如何使用 VBA 获得与使用 Access 用户界面相同的结果?

如果您想将文件存储为 OLE 包 shell 对象,进行一些 GUI 编码(打开带有 OLE 对象的表单,然后使用它来存储文件)是目前唯一的方法据我所知。

创建一个名为 frmLoadOLEObj 的未绑定表单,其中包含一个名为 MyBoundOLEFrame 的绑定 OLE 对象。

在表单中,添加以下代码:

Public Sub SaveOLEObj(rs As DAO.Recordset, fldName As String, FileName As Variant)
    'Save the position of the recordset
    Dim bkmrk As Variant
    bkmrk = rs.Bookmark
    'Bind the form to the recordset
    Set Me.Recordset = rs
    'Move the form to the saved position
    Me.Bookmark = bkmrk
    'Bind the OLE frame to the field
    MyBoundOLEFrame.ControlSource = fldName
    MyBoundOLEFrame.Class = "Package"
    'Load the attachment into the OLE frame
    MyBoundOLEFrame.SourceDoc = FileName
    MyBoundOLEFrame.Action = acOLECreateEmbed
End Sub

然后,将文件添加到记录中:

Dim rsa As DAO.Recordset
Set rsa = CurrentDb.OpenRecordset("ZipCodeAttachments", dbOpenDynaset, dbSeeChanges)
Dim frmOLE As New Form_frmLoadOLEObj
frmOLE.SaveOLEObj rs, "Attachments", Application.CurrentProject.Path & "\Attachments7.zip"

如您所见,这是非常"hacky"的代码,因为它运行的是 GUI 操作,并且您在窗体上的代码不是窗体,而是真正的模块,但您需要一个窗体来放上控件,因为没有表单就无法获得控件。我宁愿每天都有一个 BLOB。