.net 如何使用Windows窗体中的Access附件字段?

.net 如何使用Windows窗体中的Access附件字段?,.net,vb.net,visual-studio,winforms,ms-access,.net,Vb.net,Visual Studio,Winforms,Ms Access,在VisualStudio中,我从本地Access数据库文件设置了数据源。该数据库中的一个表具有多个不同的附件字段(利用Access的附件数据类型) 首先,Visual Studio将它们标记为字符串数据类型,这似乎不正确,但当我要更改它时,似乎没有适用的数据类型: 要选择的合适数据类型是什么 其次,什么控件适合在表单上表示此字段?很明显,文本框并不能解决这一问题,但我不知道让用户上传和下载这些附件的最佳方式是什么——我对winforms很陌生 如果编码是您答案的一部分,请注意我正在使用VB.

在VisualStudio中,我从本地Access数据库文件设置了数据源。该数据库中的一个表具有多个不同的附件字段(利用Access的附件数据类型)

首先,Visual Studio将它们标记为字符串数据类型,这似乎不正确,但当我要更改它时,似乎没有适用的数据类型:

要选择的合适数据类型是什么

其次,什么控件适合在表单上表示此字段?很明显,文本框并不能解决这一问题,但我不知道让用户上传和下载这些附件的最佳方式是什么——我对winforms很陌生


如果编码是您答案的一部分,请注意我正在使用VB.net(我知道,我知道)。Visual Studio版本是社区2019版16.7.1

一个非常有趣的问题

答案是肯定的,你可以很容易地提取附件数据

首先要认识到的是,附件表实际上是“幕后”一个普通的jane子表。请记住,该附件列(子表)可以附加1个或15个文件

破解这一魔法的诀窍是在Access中启动查询生成器,然后放入该表

你看到了吗

请注意每个附件(3列)如何存在一组列

现在,如果在查询中不包括这3列中的一列,您会这样做吗?然后,查询中的每一行对应一行

有了,上面,我们走吧

从tblAttach中选择*

我在这个表中有一行,但是你可以看到两个附件

现在是魔术:

如果包含任何子表列,那么数据引擎将在幕后执行此隐藏子表的左联接(事实上,它不再隐藏!!!)

因此,我们可以对查询执行以下操作:

SELECT ID, FirstName, LastName, 
MyBinFiles.FileName, 
MyBinFiles.FileType, 
MyBinFiles.FileData
FROM tblAttach;
因此,只要包含任何一个子列名,Access(ACE)就会进行左连接。(您不使用联接-只需显示3列中的任意一列,即可访问左联接)

因此,父列(id、FirstName、LastName)将“重复”附件表中的每个子行(该表隐藏在Access中-您无法获取名称,但使用此技巧,我们不在乎)

你现在明白了:

那个文件数据列呢?它是整个文件的bytes()数组

现在,让我们跳到.net

放入一个网格视图。我们有这个代码

然后按钮后面的按钮代码是:

   Dim con As New OleDb.OleDbConnection(My.Settings.Test44)

    Dim strSQL As String
    strSQL = "SELECT ID, FirstName, LastName, " &
             "MyBinFiles.FileName," &
             "MyBinFiles.FileType" &
             " FROM tblAttach"

    ' "tblAttach.MyBinFiles.FileData," &

    Dim oReader As New OleDb.OleDbDataAdapter(strSQL, con)
    Dim rstData As New DataTable
    oReader.Fill(rstData)

    Me.DataGridView1.DataSource = rstData

    Dim btn As New DataGridViewButtonColumn()
    DataGridView1.Columns.Add(btn)
    btn.HeaderText = "Export"
    btn.Text = "Export File"
    btn.Name = "btn"
    btn.UseColumnTextForButtonValue = True
好的,我们现在在.net中有了这个:

(再次注意-两行!!!-因此发生了魔术连接!!!)

现在,导出文件的按钮代码是什么

我们有:

Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick

    If e.ColumnIndex = 5 Then
        ' export data
        With DataGridView1.Rows(e.RowIndex)

            Call ExportFile(.Cells(0).Value, .Cells(3).Value, .Cells(4).Value)

        End With
    End If

End Sub
请注意,子表的PK列没有公开。实际上,主表的PK(id)加上文件名=整行的PK

是的,这意味着您不能将两个同名文件附加到给定的一行—这在Access中是不允许的—UI和引擎阻止了这一点

因此,在上面,我传递了ID和文件名。 我没有在显示网格查询中包含binary(byte())列-这会导致“讨厌”-但是如果附件是图片? 那么是的,从SQLServer(或Access/ACE)中提取/显示二进制图片的代码示例实际上可以工作

在我的示例中,您可以看到文件扩展名是pdf(因此类型列是原始文件扩展名-在大多数情况下!!!)。因此,pdf文件存储在这里

那么,现在的代码是将一个附件导出到一个标准windows文件吗

代码实际上与使用SQLServer和varbinary列执行此操作时的代码相同

我们得到这个:

Sub ExportFile(id As Integer, strFile As String, strType As String)

    Dim con As New OleDb.OleDbConnection(My.Settings.Test44)

    Dim strSQL As String
    strSQL = "SELECT ID, " &
             "MyBinFiles.FileName," &
             "MyBinFiles.FileType," &
             "MyBinFiles.FileData" &
             " FROM tblAttach " &
             " WHERE ID = " & id &
             " AND MyBinFiles.FileName = '" & strFile & "'"

    Dim oReader As New OleDb.OleDbDataAdapter(strSQL, con)
    Dim rstData As New DataTable
    oReader.Fill(rstData)

    Dim strSaveAsFile As String = "c:\test\Files\" & strFile & "." & strType
    Dim bytefile As Byte() = rstData.Rows(0).Item("MyBinFiles.FileData")
    File.WriteAllBytes(strSaveAsFile, bytefile)

End Sub
所以,请注意,这次我们确实包含了FileData,并注意我是如何将数据(byte())数组写入磁盘的


最终的结果将是可以打开的windows文件。在我的例子中是pdf,但它可能是一个图片,或者说是一个word文件。

内置的数据UI都不适合附件数据类型。您必须创建一个自定义控件来处理它可能包含的多个文件,并手动处理它们。这些帖子建议使用DAO对象模型。有一种方法可以查询隐藏的子表(access中的附件列是多值的-对于给定的列,您可以有1个或15个附件)在后台有一个常规的访问表。如果您使用下面的提示,那么您不必使用DAO文件保存/写入,而是可以像在sql server中使用varbinary一样进行写入。ACE查询处理器可以公开额外的列,并且通常在access中完成,而在.net中使用oleDB a也可以使用相同的方法s如下所示。应重新打开该问题,以便将此答案标记为答案。我以前尝试过类似的方法,但在Access压缩数据的文件中遇到了问题(例如,bmp、tiff、可以找到的列表)。您能检查一下您当前的方法是否适用于这些文件类型吗?@ErikA的进一步评论–PDF文件是一个特例。有关详细信息,请参阅。谢谢Gord。虽然我的代码确实有效,但看起来byte()数组必须由ACE进行反压缩才能真正有效。因此,我的示例适用于PDF文件,但这只是因为PDF是“更宽容”。我会在一段时间内,编辑和更新我的文章,使用工作代码。获取列和额外行的技巧对于多值列仍然很方便,但公平地说,对于附件,压缩问题就开始发挥作用了。(事实上,上面的代码似乎总是对文件进行反压缩,所以它可以工作。但是对于压缩格式,它失败了,因为它也进行了解压缩。)