2

我的目标是自动将 .csv 文件导入 Access 表,保留 csv 文件中的所有数据,特别是前导零。

csv 文件每次都会有不同数量的列,因此必须动态创建需要导入的表。此外,还决定将每一列定义为 text(255)。

这是该过程的相关代码,省略了用户导航到文件夹并选择 .csv 文件的部分。

变量注意事项:

FilePathAndName包含 .csv 文件的完整路径和文件名

TableName 包含我正在创建的 MSAccess 表的名称

HeaderRow 包含具有列名的 csv 文件的第一行。列名永远不会包含逗号。

ColumnNames() 是一个数组,用于保存列名本身。

SQLStatement 将持有一个 SQL DDL 语句来创建表

Open FilePathAndName For Input As #1

' read first row to get column names because that will change every time
Line Input #1, HeaderRow
Close #1
ColumnNames = Split(HeaderRow, ",")

' create MSAccess table via DDL commands
TableName = "GROUPS_TEST"
SQLStatement = "CREATE TABLE " & TableName & "("
For i = 0 To UBound(ColumnNames)
    SQLStatement = SQLStatement & "[" & ColumnNames(i) & "] text(255)"
    If i < UBound(ColumnNames) Then
        SQLStatement = SQLStatement & ", "
    End If
Next i
SQLStatement = SQLStatement & ")"
DoCmd.RunSQL SQLStatement

' load .csv file into the table that was just created
DoCmd.TransferText acImportDelim, , TableName, FilePathAndName, True

它完美地工作到并包括创建表的 DoCmd.RunSQL 语句。所有列都定义为 text(255),因为有些列必须保留前导零。它们不是数字;它们是字母数字值。然后麻烦就开始了。我执行 TransferText 操作并将数据从 .csv 文件导入到表中。 除了它从具有它们的值中去除前导零,即使我专门将所有列定义为 TEXT 列。

我已经在谷歌上搜索了几个小时,但没有任何结果。由于 .csv 文件的动态特性,我没有导入/导出规范。而且我不知道无论如何它会有所作为。

提到的一件事是在 MSAccess 中编辑文本文件的注册表设置,但我找不到细节。我正在使用 Access 2007。提出的另一个想法是使用 schema.ini 文件,但由于 csv 文件的动态特性,我不知道这是否可行。

任何帮助将不胜感激。提前致谢。

4

2 回答 2

1

不要使用导入文件中的字段名称,而是将导入表中的所有字段命名为 F1、F2、F3 等。将 HasFieldNames 参数设置为 false。那么第一行将永远是文本。您可以稍后删除该行。然后将字段名称更改为您想要的名称或将数据插入另一个表。无论如何,我总是使用这种方法,以便在将导入数据插入最终目标表之前对其进行清理。

于 2016-09-01T01:06:02.500 回答
0

这是对我有用的解决方案;感谢 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 文件时会忽略注册表项(或者我修改了错误的注册表项)。最终,唯一对我有用的是动态创建导入/导出规范。欢迎任何其他输入。

于 2016-09-21T16:40:48.740 回答