我在我的应用程序中提供了一个导入工具,允许用户使用基本的起始数据填充它。我无法控制他们如何创建他们导入的数据,或者他们是否真的遵循我提供的导入规范(正如迄今为止的beta测试经验所充分证明的那样)。我还了解到他们导入的数据集大小超出了我的预期(迄今为止最大的是750,000条记录),因此导入需要表现良好。
要导入五到六组不同的数据,范围从4列到24列,我正在尝试提出一种可以用于所有这些数据的方法,从最简单的数据集开始。
这个最简单的导入文件将是一个包含4列没有标题的csv文件,最终应该放在一个临时的Access表中,其字段如下所示。
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 - 这有效,但除了最小的导入文件之外,其他任何操作都非常慢。 (我不能发誓它没有表现出我在下面用第二种方法讨论的一些相同的缺陷,因为我没有详尽地测试它。)
我尝试的下一个方法是基于https://stackoverflow.com/a/11147920/1943174的方法,虽然我很难找到关于使用Xml Import Spec执行导入时应该期望的确切行为的任何文档,或者我应该使用的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
导入非常快,我正在使用的测试输入数据是正确形成的,但结果是具有正确结构的Access表,但导入到错误字段的数据:
GenID -- in the right place
GivenNames -- in the Other Info (memo) field
OtherInfo -- in the Surname (text) field
Surname -- in the Given Names (field).
如果我更改导入文件中列的顺序,使它们按字母顺序排列(GenID,GivenNames,OtherInfo,Surname),那么导入工作正常,但该顺序对用户没有意义或生成简单,因此他们可能最终错误地填充他们的导入文件。 (此外,由于我将要描述的缺陷,它也将失败。)
如果我将临时表中创建的字段的名称更改为XA,XB,XC,XD(计划在导入后更改字段名称,一旦数据被验证并且正在附加表格,这将是最终的home)正确的数据进入'right'字段,但只要导入文件中只有4列。如果存在第五个,我会得到以下字段:
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数据集中的文本和多行备忘录字段的快速导入,其中无法保证用户不包含无关列结束?我没有能力编辑import csv - 所有数据更改都需要在Access中,并且csv文件必须保持不变。
这个更新由盲人明显的部门带来:
如果我将导入的字段命名为“Field1”,“Field2”等,那么任何额外的字段应按顺序插入,因此额外的字段不是问题。我仍然希望导入正确的字段名称。
答案 0 :(得分:2)
考虑使用查询导入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;
但是,我不确定数据源中的备注字段会发生什么。如果它不能阻止查询正常工作,至少这种方法应该允许您提取正确的字段并将它们存储在正确的目标字段中。