导入 CSV 并强制所有字段为文本格式

问题描述 投票:0回答:2

我正在将一系列 CSV 文件导入 Access 表中。 我有以下行导入每个文件:

    DoCmd.TransferText acImportDelim, , FN, F.Path, True

此导入语句起作用并创建必要的表。 但是,它从数据创建字段类型,并且根据数据的前几行,它可能会创建一个应该是文本的数字字段 - 然后在文件中稍后遇到文本值时会导致错误。

如何强制输入文件中每个字段的字段类型为文本? 我以前使用过导入规范,但首先文件格式(由我无法控制的其他人提供)可能会不时更改,其次它是一个非常“宽”的文件,包含 200 多个列,所以这不是一个实际的答案.

ms-access vba
2个回答
0
投票

这不是一个很好的解决方法,但无论如何我都必须完成这个过程才能绕过表中 255 个字段的限制。 简而言之,我最终完成的导入步骤是

  1. 将文件的第一行作为输入流读取
  2. 拆分行获取字段名称,将其放入数据字典表中,然后手动标记我要导入的字段
  3. 使用 CREATE TABLE 创建一个新的数据表(仅限选定的字段),并将所有字段设置为 TEXT
  4. 将文件的每一行作为输入流读取
  5. 拆分行以获取每个字段的数据
  6. 使用 INSERT INTO 将选定的字段添加到数据表中

虽然很麻烦,但它解决了这两个问题 - 我不限于输入文件中的 255 个字段,而且我可以在创建字段时控制字段的数据类型。

如果有人关心的话,代码是

Function Layout()

Set db = CurrentDb()
Folder = DLookup("[data folder]", "folder")
Dim FSO As New FileSystemObject
Set flist = FSO.GetFolder(Folder).Files
db.Execute ("delete * from [data dictionary]")

For Each F In flist
    FN = Left(F.Name, InStr(F.Name, ".") - 1)
    FT = Mid(F.Name, InStr(F.Name, ".") + 1)
    If FT <> "csv" Then GoTo Skip

    If TestFile(F.path) = "ASCII" Then
        Set instream = FSO.OpenTextFile(F.path, ForReading, , 0)
        Else: Set instream = FSO.OpenTextFile(F.path, ForReading, , -1)
        End If

    header = instream.ReadLine
    Data = Split(header, ",")
    For i = LBound(Data) To UBound(Data)
        SQL = "insert into [data dictionary] ([table], [field], [index]) select "
        SQL = SQL & "'" & FN & "','" & Data(i) & "','" & i & "'"
        db.Execute SQL
        Next i
Skip: Next F

End Function

Function TestFile(ByVal path As String)
   Dim buffer As String
   Dim InFileNum As Integer
   Dim firstByte As Integer
   Dim secondByte As Integer
   Dim thirdByte As Integer

   buffer = String(100, " ")

   InFileNum = FreeFile

   Open path For Binary Access Read As InFileNum

   Get InFileNum, , buffer

   Close InFileNum

   firstByte = Asc(Mid(buffer, 1, 1))
   secondByte = Asc(Mid(buffer, 2, 1))
   thirdByte = Asc(Mid(buffer, 3, 1))

   If (firstByte = 255 And secondByte = 254) Then
       TestFile = "Unicode"
   ElseIf (firstByte = 254 And secondByte = 255) Then
       TestFile = "Unicode"
   ElseIf (firstByte = 239 And secondByte = 187 And thirdByte = 191) Then
       TestFile = "Unicode"
   Else
       TestFile = "ASCII"

   End If

End Function

Function import()

Folder = DLookup("[data folder]", "folder")
Set db = CurrentDb()
Dim FSO As New FileSystemObject

Set Tlist = db.OpenRecordset("select [table] from [data dictionary] where ([required]<>'') group by [table]")
Tlist.MoveFirst
Do While Not Tlist.EOF
    TN = Tlist.Fields("table").Value
    Delete_table (TN)
    Set flist = db.OpenRecordset("select * from [data dictionary] where [required]<>'' and [table]='" & TN & "'")
    flist.MoveFirst
    Text = ""
    Do While Not flist.EOF
        FN = flist.Fields("Field")
        Text = Text & "," & FN & " " & IIf(InStr(FN, "Date") > 0 Or InStr(FN, "_DT") > 0, "DATETIME", "TEXT")
        flist.MoveNext
        Loop
    SQL = "CREATE TABLE " & TN & "(" & Mid(Text, 2) & ")"
    db.Execute SQL

    path = Folder & "\" & TN & ".csv"
    If TestFile(path) = "ASCII" Then
        Set instream = FSO.OpenTextFile(path, ForReading, , 0)
        Else: Set instream = FSO.OpenTextFile(path, ForReading, , -1)
        End If

    header = instream.ReadLine
    Do While Not instream.AtEndOfStream
        Line = parser(instream.ReadLine)
        Data = Split(Line, ",")
        flist.MoveFirst
        Text = ""
        Do While Not flist.EOF
            n = flist.Fields("index").Value
            Text = Text & ",'" & Data(n) & "'"
            flist.MoveNext
            Loop
        SQL = "insert into [" & TN & "] values(" & Mid(Text, 2) & ")"
        db.Execute SQL
        Loop

    Tlist.MoveNext
    Loop
x = MultipleCodes()
MsgBox ("done")
End Function

Function parser(S)
parser = S
i = InStr(S, Chr(34))
If i = 0 Then
    parser = S
    Else
        j = InStr(i + 1, S, Chr(34))
        T = Mid(S, i + 1, j - i - 1)
        T = Replace(T, ",", ";")
        parser = Left(S, i - 1) & T & parser(Mid(S, j + 1))
    End If
End Function

0
投票

在MS Access中,您可以使用DoCmd.TransferText的第二个参数: 规格名称

作为导入或导出名称的字符串表达式 您已创建并保存在当前数据库中的规范。为一个 固定宽度的文本文件,您必须指定一个参数或使用 schema.ini 文件,该文件必须存储在与 导入、链接或导出的文本文件。

要创建架构文件,您可以使用文本导入/导出向导 创建文件。对于分隔文本文件和 Microsoft Word 邮件 合并数据文件,您可以将此参数留空以选择 默认导入/导出规格。

因此,您可以使用导入向导保存规范,然后您可以 在SpecificationName 参数中提供该规范的名称。

© www.soinside.com 2019 - 2024. All rights reserved.