【问题标题】:Import Unknown Field Order From Text从文本导入未知字段顺序
【发布时间】:2014-01-08 16:48:43
【问题描述】:

我被分配了将大约 180 个 csv 文件导入 access 2007 数据库的任务。这些文件多年来一直放在一起,将被放入 3 个文件夹中的 1 个。我没有对这些表设置任何数据检查或限制(例如主键、验证规则或关系)。这将在数​​据导入后完成。这些文件中包含的数据来自多年来发生变化的调查。此更改导致字段更改。它们的顺序发生了变化,或者有时有一个字段,有时没有。我确实有一个所有可能字段的列表,以及每个 csv 文件应该导入到哪个表,并且知道所有这些字段都可以是文本。

这是我的问题:不知道列的顺序或列是否存在,是否可以运行一个函数,通过将文本文件中的每一列映射到其相关联来将这些文本文件导入到它们的相关表中访问表中的列?

每个文本文件都有标题,这有助于查看它们实际上是什么,但是没有文本限定符,这在处理完全由数字组成的 id 代码时会非常烦人。以下是我到目前为止所尝试的。它从其他地方的函数中获取文件位置,将该位置中的每个文件名添加到集合中,然后对于该集合中的每个文件,它会尝试将其导入到它的相关字段中。

    'Get file names from the folder and store them in a collection
temp = Dir(location & "\*.*")
Do While temp <> ""
    fileNames.Add temp
    temp = Dir
Loop

'Go through each file in the collection and preccess it as needed
For Each temp2 In fileNames
    If (temp2 Like "trip*") Then 'Import trip files
        'Gets the data from a query 'DoCmd.RunSQL "SELECT * FROM [Text;FMT=Delimited;HDR=YES;IMEX=2;CharacterSet=437;DATABASE=" & location & "].[" & temp2 & "] As csv;"
        DoCmd.TransferText acImportDelim, "Trips_Import", "tbl_Trips", location & "\" & temp2, -1
    End If

    If (temp2 Like "catch*") Then 'Import catch files
        DoCmd.TransferText acImportDelim, "Catch_Import", "tbl_Catch", location & "\" & temp2, -1
    End If

    If (temp2 Like "size*") Then 'Import size files
        DoCmd.TransferText acImportDelim, "Size_Import", "tbl_Size", location & "\" & temp2, -1
    End If
Next temp2

【问题讨论】:

    标签: ms-access csv import ms-access-2007


    【解决方案1】:

    您可以为每个 CSV 文件创建一个SELECT * 查询并将查询作为记录集打开。为目标表打开另一个记录集。

    然后对于 CSV 记录集中的每一行,将一行添加到目标记录集中,循环遍历 CSV Fields 集合,并将每个 CSV 字段值添加到具有相同名称的目标字段。

    此方法与字段在 CSV 文件中出现的顺序无关。 CSV 文件是否仅包含目标表中存在的字段的子集也无关紧要。只要每个 CSV 字段也存在于表中,它就应该可以工作(假设兼容的数据类型、值满足验证规则/约束等)。

    Dim db As DAO.Database
    Dim fld As DAO.Field
    Dim rsDest As DAO.Recordset
    Dim rsSrc As DAO.Recordset
    Dim strSelect As String
    Dim strTableName As String
    
    Set db = CurrentDb
    
    'Go through each file in the collection and preccess it as needed
    For Each temp2 In fileNames
        Select Case Left(temp2, 4)
        Case "trip"
            strTableName = "tbl_Trips"
        Case "catc"
            strTableName = "tbl_Catch"
        Case "size"
            strTableName = "tbl_Size"
        Case Else
            ' what should happen here?
            ' this will trigger an error at OpenRecordset(strTableName) ...
            strTableName = vbNullString
            ' figure out a better alternative
        End Select
        strSelect = "SELECT csv.* FROM " & _
            "[Text;FMT=Delimited;HDR=YES;IMEX=2;CharacterSet=437;DATABASE=" & _
            Location & "].[" & temp2 & "] As csv;"
        Debug.Print strSelect
        Set rsSrc = db.OpenRecordset(strSelect, dbOpenSnapshot)
        Set rsDest = db.OpenRecordset(strTableName, dbOpenTable, dbAppendOnly)
        With rsSrc
            Do While Not .EOF
                rsDest.AddNew
                For Each fld In .Fields
                    rsDest.Fields(fld.Name).value = fld.value
                Next
                rsDest.Update
                .MoveNext
            Loop
            .Close
        End With
        rsDest.Close
    Next temp2
    

    注意:这是一种 RBAR(逐行逐行)方法,因此性能将不那么出色。但是,我假设您只会执行一次此操作,因此性能影响不会破坏交易。如果您需要更快的基于集合的方法,您可以为每个 CSV 文件构建并执行“附加查询”。为此,您首先需要获取 CSV 字段名称,然后构建适当的 INSERT INTO 语句。

    【讨论】:

    • 非常感谢您的快速回复。我尝试过这样的事情。这实际上是您所说的追加查询方法。这样做的问题是它不会将文本保留为文本(即 15 位 ID 代码)。我尝试将:rsDest.Fields(fld.Name).value = fld.value 更改为:rsDest.Fields(fld.Name).Value = CStr(fld.Value) 但我认为在查询 csv 文件时会出现问题。还要感谢您对可能的文件名进行额外的错误检查。不敢相信我错过了!
    • 那么CStr(fld.Value) 发生了什么?它会抛出错误吗?
    • 不抛出错误。它似乎没有多大作用。无论是否使用转换,所有大数字(应该是文本)都以科学计数法输出。似乎 access 在 SELECT 查询中读取了它假定为数字的任何内容。有没有办法在访问中覆盖它?
    • 刚刚尝试过,没有运气。我也试过:If (IsNumeric(fld.Value)) Then rsDest.Fields(fld.Name).Value = FormatNumber(fld.Value, 0, -1, 0, 0) Else rsDest.Fields(fld.Name)。 Value = fld.Value End If 但这会降低数字的精确度并截断许多有价值的信息。感谢您的帮助!
    • 唯一的建议是创建一个包含 db 文件和麻烦的 CSV 文件的 Zip 存档。将 Zip 文件上传到文件共享网站,给我们一个链接,我会看看我是否能弄清楚如何修复代码。
    猜你喜欢
    • 2016-09-15
    • 2013-12-18
    • 2018-03-06
    • 2020-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多