这是对我有用的解决方案;感谢 Ryan Griffin 对 Stack Overflow 上类似问题的回答。
重申要求:
1) 将 .csv 文件导入 MSAccess
2) 必须在具有它们的字段中保留所有前导零
3) .csv 文件是动态的;列的数量可以(并且通常会)随着每次导入而变化
4) 数据类型可以是所有列的文本
5) 给定列的数据长度永远不会> 255
6) .csv 文件的第一行将始终包含列名,并且列名中永远不会有逗号
7) 列可能有也可能没有引号分隔符;如果任何列包含逗号,则该列将用引号分隔;否则它可能是也可能不是。
这是一个示例 .csv 文件:
姓名、部门、分机
"ManyJohns, 约翰",02,0987
John Smallberries,“收购”,“32939”
“John Bigbootie”,0001,GIGO
系统设置:Windows 7 和 MSAccess 2007
几年前,我知道一个注册表设置有助于类似项目。Win7 路径为 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines\Text
将ImportMixedTypes的值从Majority Type更改为Text
第一次尝试:使用 TransferText 操作
变量:TableName 和 FilePathAndName
DoCmd.TransferText acImportDelim, , TableName, FilePathAndName, True
请注意,没有导入规范,因为如上所述,它每次都可能更改。结果:删除了前导零并删除了文本值
第二次尝试:将 .csv 文件作为 Access 对象打开
变量:表名、文件路径和文件名
SQLStatement = "INSERT INTO " & TableName & " SELECT * FROM [TEXT;FMT=Delimited;HDR=YES;IMEX=1;CharacterSet=437;DATABASE=" & FilePath & "].[" & FileName & "]"
DoCmd.RunSQL SQLStatement
结果:我以前从未见过这个;有点酷,我想。但是,它也删除了前导零并删除了文本值。
第三次尝试:动态创建导入/导出规范 这是 Ryan Griffin 的帖子,我根据我的目的调整了他的解决方案。谢谢你,先生; 我向你们致敬。
访问数据项目在 VBA 中导入 CSV 文件
而且,成功。
由于我的 .csv 文件的动态特性,这里是基于 Ryan 工作的最终代码。我在这里没有包含变量声明;如果有兴趣让我知道,我会把一些东西放在一起更精致。
Private Function CreateImportSpecification()
'based on solution from Ryan Griffin 21-JUN-2012
ImportSpecificationName = "ImportSpec_" & TableName
xml = ""
xml = xml & "<?xml version=""1.0"" encoding=""utf-8"" ?>" & vbCrLf
xml = xml & "<ImportExportSpecification Path=" & Chr(34) & FilePathAndName & Chr(34) & " xmlns=""urn:www.microsoft.com/office/access/imexspec"">" & vbCrLf
xml = xml & " <ImportText TextFormat=""Delimited"" FirstRowHasNames=""true"" FieldDelimiter="","" CodePage=""437"" Destination=" & Chr(34) & TableName & Chr(34) & " >" & vbCrLf
xml = xml & " <DateFormat DateOrder=""MDY"" DateDelimiter=""/"" TimeDelimiter="":"" FourYearDates=""true"" DatesLeadingZeros=""false"" />" & vbCrLf
xml = xml & " <NumberFormat DecimalSymbol=""."" />" & vbCrLf
xml = xml & " <Columns PrimaryKey=""{none}"">" & vbCrLf
' dynamically populate the 'FieldName' property of the <Column> attribute
For i = 0 To UBound(ColumnNames)
xml = xml & " <Column Name=""Col" & (i + 1) & """ FieldName=""" & ColumnNames(i) & """ Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" Width=""255"" />" & vbCrLf
Next i
xml = xml & " </Columns>" & vbCrLf
xml = xml & " </ImportText>" & vbCrLf
xml = xml & "</ImportExportSpecification>"
' if a specification already exists for this table, delete it
With CurrentProject.ImportExportSpecifications
For i = 0 To .Count - 1
If .Item(i).Name = ImportSpecificationName Then
.Item(i).Delete
Exit For
End If
Next i
' add the specification to the database
.Add ImportSpecificationName, xml
' could execute ImportSpecificationName right here
' but would need to loop through the ImportExportSpecifications again
' to make sure you had the right one
End With
DoCmd.RunSavedImportExport ImportSpecificationName
End Function
我唯一能想到的是 MSAccess 在导入 .csv 文件时会忽略注册表项(或者我修改了错误的注册表项)。最终,唯一对我有用的是动态创建导入/导出规范。欢迎任何其他输入。