从文本导入未知字段顺序

时间:2013-12-19 22:46:52

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

我被分配了将大约180个csv文件导入访问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

1 个答案:

答案 0 :(得分: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语句。