问题背景:
我有一个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数据库中拥有的表,该数据库与其他表有关系,并由数据库中的各种查询和表单使用。 CSV列已经以与访问表相同的方式命名和格式化。
我看过并尝试复制以下主题:
VBA procedure to import csv file into access
Access Data Project Importing CSV File In VBA
我找到的最接近的答案是:
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
但是这显然不会将数据写入表中,我无法理解作者在更改Select to Insert方面所说的内容。
我也发现:
DoCmd.TransferText acImportDelim, "YourCustomSpecificationName", _
"tblImport", "C:\SomeFolder\DataFile.csv", False
由于这些都来自2010年,我想知道在Access 2013中是否没有更好的方法来实现这一点。虽然我可以手动完成所有这些,但我想将其合并到我使用的VBA代码中告诉Powershell生成CSV,这样我就可以制作它,然后立即上传。
非常感谢任何帮助或建议。一般来说,我对Access,VBA和SQL语句仍然非常环保,所以这一直是一个“随时随地学习”的过程。
答案 0 :(得分:2)
我更喜欢使用SQL子句和查询来导入此类数据。细节取决于您的确切配置,但它往往看起来像这样:
SELECT *
INTO MyTable
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]
或者将信息附加到表格中:
INSERT INTO MyTable
(SiteCode, FacilityNumber, DocumentType, HyperlinkPath)
SELECT *
FROM [Text;FMT=CSVDelimited;HDR=No;DATABASE=C:\...\Output].[scanResults#csv]
这允许您在导入之前进行检查(使用WHERE
子句),仅导入特定值,并允许您自定义批次而不使用外部文件。
DATABASE=
之后是您的文件夹名称(如果有字符需要转义,请使用{}
),然后是.
替换为{{1}的文件名}}
您可以通过将其另存为查询或将其用作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
(请注意,代码很长,是几年前为项目开发的,并没有经过广泛测试。如果字段名称/类型不像导入前那样完全,那么恢复备份可能会失败,关系将永久丢失。
答案 1 :(得分:1)
所以一些高级架构师建议:替换数据与替换表
更换数据更容易 - 新的传入数据必须与现有表格完全相同(即相同的字段名称和新字段)。
非常简单。
如果必须,您可以替换表格 - 而且您已经走了这条路。您可以完全删除这些表关系。该表关系功能很有用 - 但不是强制性的。您可以在查询级别创建关系作为替代方案。本质上,表关系只是自动创建查询级别关系。如果删除表关系,则必须手动在查询级别创建表关系 - 它们不会自动显示。但请注意,如果依赖级联删除或参照完整性,那么删除表关系将撤消 - 因此您应该检查这些点。
删除表关系不会破坏任何现有查询。他们的表关系连接线将保持不变。