【问题标题】:Access Data Project Importing CSV File In VBA访问数据项目在 VBA 中导入 CSV 文件
【发布时间】:2011-03-25 17:34:42
【问题描述】:

我时不时地遇到我的一位同事开发的旧系统的问题。他们往往有数千行代码来做一个简单的事情,比如导入一个 csv 文件。

目前vba进程是:

  • 打开excel应用程序
  • 创建新工作表
  • 填充 csv 文件
  • 在excel中添加文件头名称
  • 将工作表另存为新的 Excel 文件
  • 将文件导入到访问数据项目sql表中。
  • 处理数据

我想用它做的是:

  • 将 csv 导入表格(如获取外部数据功能)
  • 处理数据

我进行了快速搜索,但看不到任何简单的方法可以将文件吸进表格中。

任何帮助将不胜感激。

谢谢

保罗

【问题讨论】:

  • 我已经重新格式化了你的第一个任务列表,因为它看起来很乱。有些地方不清楚,所以如果我搞砸了,你应该编辑它以纠正我的错误。

标签: ms-access vba csv import


【解决方案1】:

在许多情况下,导入 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 命令中来获得更好的结果。该规范允许您确定将数据加载到哪些表字段、调整数据类型以及大量其他选项。当您手动导入数据文件时,您可以创建自己的导入规范...选择您的自定义导入选项,并将这些选择保存为命名规范。 (在“导入向导”对话框中查找“高级”按钮。)

【讨论】:

    【解决方案2】:

    我找到了一种将整个 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 的文件,并且能够确保每一列都有适当的数据类型和正确的索引(无需额外步骤)。因此,通过这种方法,我能够实现 7 到 9 倍的速度提升,并且很容易知道数据是正确的。

    *注意:对于这个函数,我提供了 CSV 文件路径(包括 name.csv)、所需的表名和 pagenum,它是表引用。 (我用它来区分表。在 xml 字符串中,我有一个基于该 pageNum 的 if 语句,其中如果 pageNum 为 1;将这些列添加到字符串中)。

    只要 csv 文件不包含“.”,这将非常适合您的所有 CSV 导入需求。 (句点)在名称中[除了扩展名]。为此,您需要使用 Scripting FileSystemObject 来获取文件,并在导入之前将其名称更改为使用下划线而不是句点。

    我知道这可能有点啰嗦,但在该领域中可靠且有用的资源很少。我花了将近一天的时间来减少选项并整理 VBA 混乱。我希望这可以帮助那些遇到和我一样麻烦的人。

    【讨论】:

    • +1 我不知道ImportExportSpecifications 可以提供如此令人印象深刻的速度提升。顺便说一句,我认为ImportExportSpecifications 是在 Access 2007 中引入的,因此在早期版本中不可用。
    • 谢谢!好点,很高兴知道这可能不适用于早期版本的 Access
    【解决方案3】:

    有一种更简单的方法可以导入 CSV!您可以使用 Microsoft Text Odbc 驱动程序。

    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) where X=some char

    FirstRowHasNames:0,1

    字符集:OEM、ANSI

    【讨论】:

    • 您认为这种方法优于仅使用 DoCmd.TransferText 有什么原因吗?它肯定会降低效率,你不觉得吗?您实际上也没有导入任何内容,只是在即时窗口中打印出数据。
    • 如果您再次阅读我的帖子,您会发现我写的关于将 Select 更改为 Insert into 的句子。而TransferText也可以,只要结构完全一样。这样做,它可以在写入db之前进行一些转换。
    【解决方案4】:

    BULK INSERT 通常更快,并且可以在 X64 机器上工作。上面提到的文本驱动程序可能无法在某些 X64 环境中工作。

    我建议不要使用格式文件,没有它会简单得多。

    http://msdn.microsoft.com/en-us/library/ms188365.aspx

    大容量插入 AdventureWorks2008R2.Sales.SalesOrderDetail FROM 'f:\orders\lineitem.tbl' 和 ( FIELDTERMINATOR ='|', ROWTERMINATOR =' |\n' )

    【讨论】:

    • 我不明白为什么这被否决了。 BULK INSERT 是最快的方法。
    • BULK INSERT 在 SQL Server 中效果很好,不管你确定什么版本。
    • 他正在使用需要 SQL SERVER 的“访问数据项目”。什么版本都没有关系。
    • +1,好主意。一开始我也有ADP的标题,一开始以为你的提议是错误的。
    • BULK INSERT 的唯一最终缺点是文件必须驻留在服务器而不是客户端可以访问的文件夹中。
    猜你喜欢
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多