Ms access 从CSV导入Access时字段顺序错误

Ms access 从CSV导入Access时字段顺序错误,ms-access,import,vba,ms-access-2010,Ms Access,Import,Vba,Ms Access 2010,我在我的应用程序中提供了一个导入工具,允许用户用基本的起始数据填充它。我无法控制他们如何创建导入的数据,也无法控制他们是否真正遵循我提供的导入规范(到目前为止的beta测试经验充分证明了这一点)。我还了解到,他们导入的数据集比我预期的要大得多(到目前为止最大的是750000条记录),因此导入需要执行良好 将有五到六组不同的数据需要导入,从4列到24列不等,我正试图找到一种方法,从最简单的数据集开始,我可以用于所有这些数据集 这个最简单的导入文件将是一个csv文件,有4列,没有标题,并且应该在一个

我在我的应用程序中提供了一个导入工具,允许用户用基本的起始数据填充它。我无法控制他们如何创建导入的数据,也无法控制他们是否真正遵循我提供的导入规范(到目前为止的beta测试经验充分证明了这一点)。我还了解到,他们导入的数据集比我预期的要大得多(到目前为止最大的是750000条记录),因此导入需要执行良好

将有五到六组不同的数据需要导入,从4列到24列不等,我正试图找到一种方法,从最简单的数据集开始,我可以用于所有这些数据集

这个最简单的导入文件将是一个csv文件,有4列,没有标题,并且应该在一个临时访问表中结束,其中包含如下字段

GenID: text (up to 255 chars) 

Surname: text (up to 255 chars)

GivenNames: text (up to 255 chars)

OtherInfo: multi-line memo (as long as they want)
数据应该导入到一个临时表中,在将其附加到最终主页中的现有数据之前,将在临时表中执行验证

我第一次尝试将docmd.transfertext与保存的导入规范一起使用——这很有效,但对于最小的导入文件以外的任何文件来说都非常缓慢。(我不能保证它不会出现与下面第二种方法相同的缺陷,因为我没有对它进行详尽的测试)

我尝试的下一种方法是基于的方法,尽管我很难找到关于使用Xml导入规范执行导入时应该预期的确切行为的文档,或者关于应该使用的Xml语法的文档

我在VBA中创建并执行导入规范。strFilePath标识要导入的csv文件,strTableName标识要用于导入的临时表

Dim strXML As String

strXML = ""
strXML = strXML & "<?xml version=""1.0"" encoding=""utf-8"" ?>" & vbCrLf
strXML = strXML & "<ImportExportSpecification Path=" & Chr(34) & strFilePath & Chr(34) & " xmlns=""urn:www.microsoft.com/office/access/imexspec"">" & vbCrLf
strXML = strXML & "   <ImportText TextFormat=""Delimited"" FirstRowHasNames=""false"" FieldDelimiter="","" CodePage=""437"" Destination=" & Chr(34) & strTableName & Chr(34) & " >" & vbCrLf
strXML = strXML & "      <DateFormat DateOrder=""DMY"" DateDelimiter=""/"" TimeDelimiter="":"" FourYearDates=""true"" DatesLeadingZeros=""false"" />" & vbCrLf
strXML = strXML & "      <NumberFormat DecimalSymbol=""."" />" & vbCrLf
strXML = strXML & "           <Columns PrimaryKey=""{none}"">" & vbCrLf
strXML = strXML & "                    <Column Name=""Col1"" FieldName=""GenID"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" />" & vbCrLf
strXML = strXML & "                    <Column Name=""Col2"" FieldName=""Surname"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" />" & vbCrLf
strXML = strXML & "                    <Column Name=""Col3"" FieldName=""GivenNames"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" />" & vbCrLf
strXML = strXML & "                    <Column Name=""Col4"" FieldName=""OtherInfo"" Indexed=""NO"" SkipColumn=""false"" DataType=""Memo"" />" & vbCrLf
strXML = strXML & "         </Columns>" & vbCrLf
strXML = strXML & "     </ImportText>" & vbCrLf
strXML = strXML & "</ImportExportSpecification>"

CurrentProject.ImportExportSpecifications.Add "MyImportSpec", strXML 'Add it to the project
DoCmd.RunSavedImportExport "MyImportSpec"'Run it
如果我更改导入文件中列的顺序,使它们按字母顺序(GenID、GivenNames、OtherInfo、姓氏)排列,则导入工作正常,但这种顺序对用户来说没有意义,也不便于生成,因此他们很可能会错误地填充导入文件。(另外,由于我将要描述的缺陷,它也将失败)

如果我将临时表中创建的字段的名称更改为XA、XB、XC、XD(计划在导入后更改字段名称,一旦数据被验证并添加到作为其最终主字段的表中),则正确的数据将进入“right”字段,但只要导入文件中正好有4列。如果存在第五个字段,我将获得以下字段:

GenID -- in the right place

GivenNames  -- in the Other Info (memo) field

OtherInfo -- in the Surname (text) field

Surname -- in the Given Names (field).
Field5 -- contains GenID data

XA -- contains Surname

XB -- contains GivenNames

XC -- contains OtherInfo

XD -- contains the data that was in the 5th column in the import file
如果我将导入的数据附加到具有正确结构的现有(空)表中,而不允许导入创建新表,则会出现相同的问题

对于如何实现这一点,或者对于在大型导入csv数据集中处理文本和多行备注字段的快速导入的其他方法,有什么建议吗?在这些数据集中,用户无法保证不会在末尾包含无关的列?我没有任何编辑导入csv的能力——所有数据更改都需要在Access中,并且csv文件必须在整个过程中保持不变

这个由美国教育部提供的更新非常明显:


如果我将导入的字段命名为“Field1”、“Field2”等,那么任何额外的字段都应该按顺序排列在这些字段之后,所以额外的字段不是问题。我仍然希望导入正确的字段名。

考虑使用查询来导入CSV数据。此查询从我的CSV文件中选择前4列:

SELECT csv.F1, csv.F2, csv.F3, csv.F4
FROM [Text;FMT=Delimited;HDR=NO;IMEX=2;CharacterSet=437;DATABASE=C:\Users\hans\Documents].[no_field_names.csv] As csv;
该CSV文件不包含字段名,因此Access将其指定为F1到F4。实际上,CSV包含超过4列,但我只想要前4列(我认为这与您的情况相对应)

如果您在查询设计器中构建并测试类似的查询,请注意它可能会将
FROM
子句更改为类似以下内容

FROM (Text;FMT=Delimited;HDR=NO;IMEX=2;CharacterSet=437;DATABASE=C:\Users\hans\Documents) no_field_names.csv As csv;
。。。那是行不通的。因此,每次Access进行无效更改时,您都必须再次检查并更正它

一旦得到返回所需内容的
SELECT
查询,就可以将其转换为
INSERT
查询

INSERT INTO YourTable (GenID, Surname, GivenNames, OtherInfo)
SELECT csv.F1, csv.F2, csv.F3, csv.F4
FROM [Text;FMT=Delimited;HDR=NO;IMEX=2;CharacterSet=437;DATABASE=C:\Users\hans\Documents].[no_field_names.csv] As csv;

但是,我不确定数据源中的备注字段会发生什么情况。如果它不能阻止查询正常工作,至少这种方法应该允许您提取正确的字段并将它们存储在正确的目标字段中

在初步测试中,将memo字段设置为rich text并导入到预定义的表中,这是可行的。附录:导入会将memo字段中的多个段落连接起来,但docmd.transfertext与保存的importexport规范也会连接起来。但是,如果文件扩展名为txt而不是csv,则会保留换行符