Доступ к данным проекта Импорт файла CSV в VBA - PullRequest
4 голосов
/ 05 августа 2010

Время от времени я сталкиваюсь с проблемой старой системы, разработанной одним из моих коллег.У них, как правило, тысячи строк кода для выполнения простых задач, таких как импорт файла CSV.

В настоящее время процесс vba:

  • открыть приложение Excel
  • создать новый лист
  • заполнить файл CSV
  • вExcel добавить имена заголовков в файл
  • сохранить рабочий лист как новый файл Excel
  • импортирует файл в таблицу sql проекта доступа к данным.
  • Обработка данных

Что я хочу сделать с этим:

  • импортировать CSV в таблицу (как функция получения внешних данных)
  • обработка данных

У меня был быстрый поиск, и я не вижу каких-либо простых способов просто засунуть файл в таблицу.

Буду признателен за любую помощь.

Спасибо

Пол

Ответы [ 4 ]

10 голосов
/ 05 августа 2010

Во многих случаях проще всего импортировать CSV с помощью метода TransferText.

Подробнее см. По этой ссылке MSDN: Метод TransferText [Справочник по языку VBA для Access 2003]

Вот пример команды TransferText для импорта C: \ SomeFolder \ DataFile.csv в таблицу с именем tblImport. Последний параметр, HasFieldNames, имеет значение False, чтобы указать, что файл CSV не содержит имен полей.

DoCmd.TransferText acImportDelim, "YourCustomSpecificationName", _
    "tblImport", "C:\SomeFolder\DataFile.csv", False

Параметр SpecificationName является необязательным. Однако часто вы можете получить лучшие результаты, создав собственную спецификацию импорта и включив ее имя в команду TransferText. Спецификация позволяет определить, в какие поля таблицы загружать данные, настроить типы данных и целый ряд других параметров. Вы можете создать свою собственную спецификацию импорта, когда вы вручную импортируете свой файл данных ... выберите свои собственные параметры импорта и сохраните эти варианты как именованную спецификацию. (Найдите кнопку «Дополнительно» в диалоговом окне мастера импорта.)

9 голосов
/ 22 июня 2012

Я нашел изящный способ импортировать целые CSV-файлы в доступ. Мне было поручено импортировать три CSV-файла в три таблицы для одной базы данных. Это должно было быть сделано около 100 раз, и каждый CSV будет варьироваться от 200 МБ до 500 МБ. Поскольку три схемы таблиц были одинаковыми для каждой базы данных, я потратил некоторое время, пытаясь найти лучший способ создания сценария для импорта всего этого для меня. Я впервые использовал

DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel9, p1, _
Application.CurrentProject.Path & "\Page1\_8_lift_base_" & dbName & ".csv",_
True, sh.Name & "!"

В большинстве случаев это работало, за исключением случаев, когда при открытии CSV появлялось приглашение «только для чтения», и импорт останавливался до его закрытия. Кроме того, CSV 300 МБ займет около 8-10 минут. Для 100 БД это не приемлемо.

В итоге я создал собственную спецификацию экспорта-импорта XML.

Sub make_import_spec(filePath As String, tableName As String, pageNum As Long)
'By Ryan Griffin
Dim name_of_spec As String
name_of_spec = "imspec" & tableName
Dim xml As String
'This xml string contains the specifications the use for that table
xml = ""
xml = xml & "<?xml version=""1.0"" encoding=""utf-8"" ?>" & vbCrLf
xml = xml & "<ImportExportSpecification Path=" & Chr(34) & filePath & Chr(34) & " xmlns=""urn:www.microsoft.com/office/access/imexspec"">" & vbCrLf
xml = xml & "   <ImportText TextFormat=""Delimited"" FirstRowHasNames=""true"" FieldDelimiter="","" CodePage=""437"" Destination=" & Chr(34) & tableName & Chr(34) & " >" & vbCrLf
xml = xml & "      <DateFormat DateOrder=""MDY"" DateDelimiter=""/"" TimeDelimiter="":"" FourYearDates=""true"" DatesLeadingZeros=""false"" />" & vbCrLf
xml = xml & "      <NumberFormat DecimalSymbol=""."" />" & vbCrLf
xml = xml & "           <Columns PrimaryKey=""{none}"">" & vbCrLf
xml = xml & "                    <Column Name=""Col1"" FieldName=""field1"" Indexed=""YESDUPLICATES"" SkipColumn=""false"" DataType=""Text"" Width=""12"" />" & vbCrLf
xml = xml & "                    <Column Name=""Col2"" FieldName=""field2"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" Width=""16"" />" & vbCrLf
xml = xml & "                    <Column Name=""Col3"" FieldName=""field3"" Indexed=""YESDUPLICATES"" SkipColumn=""false"" DataType=""Text"" Width=""24"" />" & vbCrLf
xml = xml & "                    <Column Name=""Col4"" FieldName=""field4"" Indexed=""NO"" SkipColumn=""false"" DataType=""Text"" Width=""16"" />" & vbCrLf
xml = xml & "         </Columns>" & vbCrLf
xml = xml & "     </ImportText>" & vbCrLf
xml = xml & "</ImportExportSpecification>"
'By Ryan Griffin
'Now you can add the specification to the project
CurrentProject.ImportExportSpecifications.Add name_of_spec, xml
' This will run your specification and import you csv file
DoCmd.RunSavedImportExport name_of_spec
End Sub

После запуска кода с этой настройкой я смог импортировать файл размером 300 МБ всего за минуту (~ 62 секунды) и смог убедиться, что каждый столбец имеет соответствующий тип данных и правильную индексацию (без дополнительного шага). Таким образом, с помощью этого метода мне удалось добиться некоторого увеличения скорости от 7 до 9 раз, с легкостью зная, что данные будут правильными.

* Примечание: для этой функции я предоставляю путь к файлу CSV (который включает в себя name.csv), желаемое имя таблицы и pagenum, который является ссылкой на таблицу. (Я использовал это для различения таблиц. В строке xml у меня был оператор if, основанный на этом pageNum, где if pageNum = 1; добавить эти столбцы в строку).

Это будет прекрасно работать для всех ваших пожеланий по импорту CSV, если в файлах csv нет «.» (точка) в имени [помимо расширения]. Для этого вам нужно будет использовать Scripting FileSystemObject, чтобы получить файл, и изменить его имя, чтобы использовать что-то вроде подчеркивания, а не точки, перед импортом.

Я знаю, что это может быть немного затянуто, но есть очень мало ресурсов, которые являются надежными и полезными в этой области. Мне потребовался почти целый день, чтобы свести на нет варианты и разобраться в беспорядке VBA. Я надеюсь, что это может помочь любому, кто испытывает те же проблемы, что и я.

4 голосов
/ 05 августа 2010

Существует более простой способ импортировать CSV!Вы можете использовать Microsoft Text Odbc Driver.

Sub Import()
   Dim conn as new ADODB.Connection
   Dim rs as new ADODB.Recordset
   Dim f as ADODB.field

   conn.Open "DRIVER={Microsoft Text Driver (*.txt; *.csv)};DBQ=c:\temp;"
   rs.Open "SELECT * FROM [test.txt]", conn, adOpenStatic, adLockReadOnly, adCmdText

   While Not rs.EOF
      For Each f In rs.Fields
         Debug.Print f.name & "=" & f.Value
      Next
   Wend
End Sub

Вы переходите от выбора к INSERT INTO в сочетании с SELECT, и вот вы здесь.

Есть некоторые настройки, которые вы можете сделать вреестр в ключе \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Text:

Формат: TabDelimited, CSVDelimited, Delimited (X), где X = некоторый символ

FirstRowHasNames: 0,1

CharacterSet:OEM, ANSI

3 голосов
/ 18 апреля 2011

BULK INSERT, как правило, быстрее, и он будет работать на компьютере X64. Вышеупомянутый текстовый драйвер, вероятно, не будет работать в некоторых средах X64.

Я бы рекомендовал НЕ использовать файл формата, без него намного проще.

http://msdn.microsoft.com/en-us/library/ms188365.aspx

BULK INSERT AdventureWorks2008R2.Sales.SalesOrderDetail FROM 'f: \ orders \ lineitem.tbl' С ( FIELDTERMINATOR = '|', ROWTERMINATOR = '| \ n' )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...