Psy*_*ics -2 .net vb.net ms-access visual-studio winforms
在 Visual Studio 中,我从本地 Access 数据库文件设置了数据源。该数据库中的一个表有几个不同的附件字段(使用 Access 的附件数据类型)。
首先, Visual Studio 将它们标记为字符串数据类型,这似乎不正确,但是当我去更改它时,似乎没有适用的数据类型: Visual Studio 数据类型
要选择的适当数据类型是什么?
其次,什么控件适合在表单上表示该字段?显然 TextBox 不会削减它,但我不知道让用户上传和下载这些附件的最佳方式是什么 - 我对 winforms 很陌生。
如果编码是您答案的一部分,请注意我使用的是 VB.net(我知道,我知道)。Visual Studio 版本是 Community 2019 版 16.7.1
一个非常有趣的问题。
答案是肯定的,您可以相当轻松地提取该附件数据。
首先要意识到的是,附件表实际上是“幕后”一个普通的简子表。请记住,附件列(子表)可以附加 1 或 15 个文件。
破解这种魔法的诀窍是在 Access 中启动查询构建器,然后放入该表中。
你看到这个
请注意每个附件(3 列)如何存在“一组”列。
现在,如果在查询中不包含 3 列之一?然后您为查询中的每一行获得 1 行。
有了,上面,让我们走
从 tblAttach 中选择 *。
我在这个表中有一行,但你可以看到两个附件!!
现在是魔术:
如果您包含任何子表列,那么在幕后数据引擎将对这个隐藏的子表进行 LEFT JOIN(实际上,它不再隐藏了!!!)。
因此,我们可以对查询执行此操作:
SELECT ID, FirstName, LastName,
MyBinFiles.FileName,
MyBinFiles.FileType,
MyBinFiles.FileData
FROM tblAttach;
Run Code Online (Sandbox Code Playgroud)
因此,仅包含任何一个子列名称都会导致 Access(ACE) 执行左连接。(您不使用连接 - 只是出现的 3 列中的任何列的 ACT 将导致访问左连接)。
因此,父列(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
Run Code Online (Sandbox Code Playgroud)
好的,我们现在在 .net 中有这个:
(再次注意 - 两行!!! - 这样就发生了 MAGIC 连接!!!)
现在,导出文件的按钮代码?
我们有这个:
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
Run Code Online (Sandbox Code Playgroud)
请注意,子表的 PK 列未公开。实际上主表的 PK (id) + 文件名 = 整行的 PK。
是的,这确实意味着您不能将两个同名文件附加到给定的单行 - Access 中不允许这样做 - UI 和引擎会阻止这种情况。
所以,在上面,我传递了 ID 和 FileName。而且我没有在显示网格查询中包含二进制 (byte()) 列 - 它会导致“讨厌” - 但如果附件是图片?那么是的,从 SQL 服务器(或 Access/ACE)中提取/显示二进制图片的代码示例实际上可以工作。
在我的示例中,您可以看到文件扩展名是 pdf(因此类型列是原始文件扩展名 - 在大多数情况下!!!)。所以,pdf文件被存储在这里。
那么,现在将那个附件导出到标准 Windows 文件的代码是什么?
代码实际上与使用 SQL 服务器和 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
Run Code Online (Sandbox Code Playgroud)
所以,请注意这次我们确实包含了 FileData。并注意我是如何将数据 (byte()) 数组写入磁盘的。
最终结果将是您可以打开的工作窗口文件。在我的例子中是 pdf,但它可能是一张图片,或者说一个 word 文件。
| 归档时间: |
|
| 查看次数: |
536 次 |
| 最近记录: |