使用 CSV 文件自动更新访问 Table

Updating an Access Table with a CSV File Automatically

问题背景:

我有一个 Powershell 脚本,我可以从我的 Microsoft Access 表单执行该脚本,该脚本扫描包含不同设施信息的文件夹,并生成类似于以下内容的 CSV:

SiteCode    FacilityNumber  DocumentType    HyperlinkPath
DKFZ        10              DD1400          C:\FACILITIES DATABASE\path
DKFZ        10              FLRPLN          C:\FACILITIES DATABASE\path
SMQL        17              P1              C:\FACILITIES DATABASE\path
SMQL        17              P2              C:\FACILITIES DATABASE\path

这样,每次将新文件添加到这些文件夹时,我都可以 运行 这个脚本并生成我拥有的所有内容的更新列表:

C:\...\Output\scanResults.csv

我现在需要的是获取该 CSV 文件并更新(甚至覆盖)我在 Access 数据库中拥有的 Table,它与其他 table 有关系并被使用通过数据库中的各种查询和表单。 CSV 列的命名和格式设置与 Access Table.

相同

我查看并尝试复制以下线程:

VBA procedure to import csv file into access

Access Data Project Importing CSV File In VBA

VBA Import CSV file

我找到的最接近的答案是:

Sub Import()
   Dim conn as new ADODB.Connection
   Dim rs as new ADODB.Recordset
   Dim f as ADODB.field

   conn.Open "DRIVER={Microsoft Text Driver (*.txt; *.csv)};DBQ=c:\temp;"
   rs.Open "SELECT * FROM [test.txt]", conn, adOpenStatic, adLockReadOnly, adCmdText

   While Not rs.EOF
      For Each f In rs.Fields
         Debug.Print f.name & "=" & f.Value
      Next
   Wend
End Sub

但这显然不会将数据写入table,我无法理解作者将Select更改为Insert的意思。

我还发现:

DoCmd.TransferText acImportDelim, "YourCustomSpecificationName", _
    "tblImport", "C:\SomeFolder\DataFile.csv", False

因为这两个都是 2010 年的,我想知道在 Access 2013 中是否有更好的方法来完成这个。虽然我可以手动完成这一切,但我想将它合并到 VBA 我用来告诉 Powershell 生成 CSV 的代码,这样我就可以生成 CSV,然后立即上传。

非常感谢任何帮助或建议。总的来说,我对 Access、VBA 和 SQL 语句还是很陌生,所以这是一个非常 "learning as I go" 的过程。

我更喜欢使用 SQL 子句和查询来导入此类数据。详细信息取决于您的确切配置,但它往往看起来像这样:

SELECT *
INTO MyTable
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]

或将信息附加到 table:

INSERT INTO MyTable
(SiteCode,    FacilityNumber,  DocumentType,    HyperlinkPath)
SELECT *
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]

这允许您在导入前进行检查(使用 WHERE 子句),仅导入特定值,并允许您在不使用外部文件的情况下进行大量自定义。

DATABASE= 后跟您的文件夹名称(如果其中有需要转义的字符,请使用 {}),然后是您的文件名,其中 . 替换为 #.

您可以通过将其保存为查询或将其用作 VBA 或宏中的字符串来执行它。请注意,我很少推荐宏,但您可以使用计划任务执行它们并在导入后关闭 Access。

要备份和恢复更新前后的关系,您可以使用以下功能:

Public Function DeleteRelationsGiveBackup(strTablename As String) As Collection
    Dim ReturnCollection As Collection
    Set ReturnCollection = New Collection
    Dim i As Integer
    Dim o As Integer
    Do While i <= (CurrentDb.Relations.Count - 1)
        Select Case strTablename 
            Case Is = CurrentDb.Relations(i).Table
                ReturnCollection.Add DuplicateRelation(CurrentDb.Relations(i))
                o = o + 1
                CurrentDb.Relations.Delete CurrentDb.Relations(i).NAME
            Case Is = CurrentDb.Relations(i).ForeignTable
                ReturnCollection.Add DuplicateRelation(CurrentDb.Relations(i))
                o = o + 1
                CurrentDb.Relations.Delete CurrentDb.Relations(i).NAME
            Case Else
                i = i + 1
        End Select
    Loop
    Set DeleteRelationsGiveBackup = ReturnCollection
End Function

Public Sub RestoreRelationBackup(collRelationBackup As Collection)
    Dim relBackup As Variant
    If collRelationBackup.Count = 0 Then Exit Sub
    For Each relBackup In collRelationBackup
        CurrentDb.Relations.Append relBackup
    Next relBackup
End Sub

Public Function DuplicateRelation(SourceRelation As Relation) As Relation
    Set DuplicateRelation = CurrentDb.CreateRelation(SourceRelation.NAME, SourceRelation.Table, SourceRelation.ForeignTable)
    DuplicateRelation.Attributes = SourceRelation.Attributes
    Dim i As Integer
    Dim fldLoop As Field
    Do While i < SourceRelation.Fields.Count
        Set fldLoop = DuplicateRelation.CreateField(SourceRelation.Fields(i).NAME)
        fldLoop.ForeignName = SourceRelation.Fields(i).ForeignName
        DuplicateRelation.Fields.Append fldLoop
        i = i + 1
    Loop
End Function

然后,在导入时:

Dim colRelBackup As Collection
Set colRelBackup = DeleteRelationsGiveBackup("MyTable")
'Delete MyTable
'Import new version
RestoreRelationBackup colRelBackup 

(请注意,代码很长,是几年前为一个项目开发的,并没有经过广泛测试。如果字段 name/type 不 完全 就像在导入前,备份还原可能会失败,关系将永久丢失。

一些高级架构师建议:替换数据与替换 table

替换数据更容易 - 新传入数据的结构必须与现有 table 完全相同(即相同的字段名称且没有新字段)。

    • 只需对现有的 table 执行删除查询即可清除所有记录
    • 然后向链接的 CSV 文件发送追加查询,将所有这些记录写入现有 table

真的很简单。

如果需要,您可以替换 tables - 而且您已经沿着这条路走下去了。您可以完全删除这些 table 关系。 table 关系功能很有用 - 但不是强制性的。作为替代,您可以在查询级别创建关系。本质上 table 关系只是自动创建查询级别的关系。如果您删除 table 关系,则必须简单地在查询级别手动创建 table 关系——它们不会自动出现。但是请注意,如果依赖级联删除或参照完整性,则删除 table 关系将撤消这些 - 因此您应该检查这些要点。

删除Table 关系不会破坏任何现有查询。他们的 table 关系连接线将保持不变。