我偶尔会遇到一个我的同事已经开发出来的旧系统的问题。他们倾向于拥有数千行代码来执行简单的操作,例如导入csv文件。
目前vba流程是:
我想用它做的是:
我有一个快速搜索,看不到任何简单的方法只是将文件吸入表中。
任何帮助都将不胜感激。
谢谢
保
答案 0 :(得分:10)
在许多情况下,导入CSV的最简单方法是使用TransferText方法。
有关详细信息,请参阅此MSDN链接:TransferText Method [Access 2003 VBA Language Reference]
下面是一个示例TransferText命令,用于将C:\ SomeFolder \ DataFile.csv导入名为tblImport的表中。最后一个参数HasFieldNames为False,表示CSV文件不包含字段名称。
DoCmd.TransferText acImportDelim, "YourCustomSpecificationName", _
"tblImport", "C:\SomeFolder\DataFile.csv", False
SpecificationName 参数是可选的。但是,通过创建自己的导入规范并在TransferText命令中包含其名称,通常可以获得更好的结果。该规范允许您识别要将数据加载到哪些表字段,调整数据类型以及许多其他选项。手动导入数据文件时,可以创建自己的导入规范...选择自定义导入选项,并将这些选项保存为命名规范。 (在“导入向导”对话框中查找“高级”按钮。)
答案 1 :(得分:9)
我找到了一种将整个CSV导入访问权限的简便方法。 我的任务是将三个CSV导入到一个数据库的三个表中。这必须完成大约100次,每个CSV的范围从200MB到500MB。由于每个数据库的三个表模式相同,我花了一些时间试图找到创建脚本的最佳方法来为我导入所有这些。 我第一次使用
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, p1, _
Application.CurrentProject.Path & "\Page1\_8_lift_base_" & dbName & ".csv",_
True, sh.Name & "!"
这适用于大多数情况,除了偶尔打开CSV时会出现“只读”提示,并在导入关闭之前暂停导入。此外,300MB CSV需要大约8到10分钟。对于100个DB,这是不可接受的。
我最终做的是创建自己的XML导入导出规范。
Sub make_import_spec(filePath As String, tableName As String, pageNum As Long)
'By Ryan Griffin
Dim name_of_spec As String
name_of_spec = "imspec" & tableName
Dim xml As String
'This xml string contains the specifications the use for that table
xml = ""
xml = xml & "<?xml version=""1.0"" encoding=""utf-8"" ?>" & vbCrLf
xml = xml & "<ImportExportSpecification Path=" & Chr(34) & filePath & 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
xml = xml & " <Column Name=""Col1"" FieldName=""field1"" Indexed=""YESDUPLICATES"" SkipColumn=""false"" DataType=""Text"" Width=""12"" />" & vbCrLf
xml = xml & " <Column Name=""Col2"" FieldName=""field2"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" Width=""16"" />" & vbCrLf
xml = xml & " <Column Name=""Col3"" FieldName=""field3"" Indexed=""YESDUPLICATES"" SkipColumn=""false"" DataType=""Text"" Width=""24"" />" & vbCrLf
xml = xml & " <Column Name=""Col4"" FieldName=""field4"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" Width=""16"" />" & vbCrLf
xml = xml & " </Columns>" & vbCrLf
xml = xml & " </ImportText>" & vbCrLf
xml = xml & "</ImportExportSpecification>"
'By Ryan Griffin
'Now you can add the specification to the project
CurrentProject.ImportExportSpecifications.Add name_of_spec, xml
' This will run your specification and import you csv file
DoCmd.RunSavedImportExport name_of_spec
End Sub
使用此设置运行代码后,我能够在一分钟内(约62秒)导入300MB文件,并且能够确保每列都具有相应的dataType和正确的索引(无需额外步骤)。因此,通过这种方法,我可以实现速度提高7到9倍的速度,并且可以轻松了解数据是否正确。
*注意:对于此功能,我提供CSV文件路径(包括name.csv),所需的表名和pagenum,它是表引用。 (我用它来区分表。在xml字符串中,我有一个基于该pageNum的if语句,如果pageNum为1,则将这些列添加到字符串中。)
只要csv文件不包含“。”,这对于您的所有CSV导入需求都能很好地工作。 (期间)名称[除了扩展名]。为此,您需要使用Scripting FileSystemObject来获取文件,并在导入之前将其名称更改为使用下划线而不是句点。
我知道它可能有点啰嗦,但是在这方面很少有可靠和有用的资源。花了我差不多一天来减少选项并理清VBA的混乱局面。我希望这可以帮助那些遇到同样麻烦的人。
答案 2 :(得分:4)
有一种更简单的方法可以导入CSV!您可以使用Microsoft Text Odbc Driver。
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更改为INSERT INTO并与SELECT结合使用。
您可以在注册表中的某些设置中使用密钥\\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text
:
格式:TabDelimited,CSVDelimited,Delimited(X)其中X = some char
FirstRowHasNames:0,1
CharacterSet:OEM,ANSI
答案 3 :(得分:3)
BULK INSERT通常更快,它可以在X64机器上运行。上面提到的文本驱动程序可能在某些X64环境中不起作用。
我建议不要使用格式文件,没有它就会更简单。
http://msdn.microsoft.com/en-us/library/ms188365.aspx
BULK INSERT AdventureWorks2008R2.Sales.SalesOrderDetail FROM'f:\ orders \ lineitem.tbl' WITH ( FIELDTERMINATOR ='|', ROWTERMINATOR ='| \ n' )