проблемы чтения двойников из CSV - VBA - PullRequest
0 голосов
/ 14 января 2019

Я хочу прочитать CSV-файл из vba-excel, но у меня проблема с двойными значениями, например, это значение в CSV: 125,5 читается без точки. Итак, я получаю 1255. Мой код:

Dim rs As New ADODB.Recordset
strCon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & myDir & ";" & "Extended Properties=""text;HDR=Yes;FMT=Delimited()"";"
strSQL = "SELECT * FROM " & myFileName
rs.Open strSQL, strCon, 3, 3
IBH = rs("IBH")

Как я могу решить?

Обновление: Я пробовал решение @Siddharth Rout, но у меня все та же проблема. мой код сейчас:

Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim myDate, myTime, IBH, IBL
Dim myDir As String, myFileName As String
Dim strSQL As String

myDir = Trim(shParams.Range("fp_path"))
myFileName = Trim(shParams.Range("fp_filename"))

With conn
 .Provider = "Microsoft.ACE.OLEDB.12.0"
 .ConnectionString = "Data Source=" & myDir & ";Extended Properties='text'"
 .Open
End With

strSQL = "SELECT * FROM " & myFileName
rs.Open strSQL, conn, 3, 3
rs.MoveLast

myDate = rs("Date")
myTime = rs("Time")
IBH = rs("IBH")
IBL = rs("IBL")

Debug.Print myDate, myTime, IBH, IBL

rs.Close
Set rs = Nothing

это результат:

enter image description here это мой CSV:

enter image description here

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Эта проблема связана с тем, как механизм ACE определяет тип поля ADODB. Драйвер просканирует определенное количество строк, чтобы определить, какой тип должен быть для всего столбца.

Изменение строки подключения


Одна быстрая вещь, которую вы можете попробовать, это изменить MaxScanRows на 0 в строке подключения. Установка этого значения в 0 будет сканировать все строки, чтобы определить тип, имейте в виду, что это может повлиять на производительность в зависимости от размера вашего набора данных.

";Extended Properties='text;MaxScanRows=0;IMEX=0'"

Это не всегда даст вам желаемый результат. Скажем, у нас есть такой набор данных:

+--------------------------+
|       DoubleField        |
+--------------------------+
| 1                        |
| 2                        |
| 3                        |
| ...(996 more records...) |
| 1000.01                  |
+--------------------------+

Драйвер будет смотреть и видеть 999 записей, которые выглядят как целое число, и 1 запись, которая выглядит как двойное число. Это поле будет определяться на основе MajorityType, это целое число, а не двойное число. Если честно, я не совсем уверен , как это определение типа выполнено точно, но это что-то в этом роде. Я также видел случаи, когда сработала бы простая замена верхней записи на нужный вам тип. Э.Г.

+--------------------------+
|       DoubleField        |
+--------------------------+
| 1.00                     |
| 2                        |
| 3                        |
| ...(996 more records...) |
| 1000.01                  |
+--------------------------+

Таким образом, другой подход может заключаться в том, чтобы отформатировать исходный файл, чтобы включить десятичные разряды заранее. Это должно быть достаточно легко сделать, если вы управляете исходным файлом, но это не всегда так.

Использовать INI-файл схемы


Если повышение MaxScanRows не работает, то для получения ожидаемого типа для каждого столбца необходимо использовать файл Schema.ini, как указано Comintern .

Вот ссылка , которая проходит через это.

Суть, создать файл, который явно определяет каждый тип для каждого столбца. Для нашей надуманной таблицы выше это становится:

[MyFileNameGoesHere.csv]
ColNameHeader = True
Format = CSVDelimited
Col1=DoubleField Double

Затем вы сохраните этот файл как Schema.Ini и поместите его в тот же каталог, где находится файл, который вы хотите импортировать. Хорошая особенность этого подхода в том, что он просто создает текстовый файл, вы даже можете сделать это в VBA без особых проблем. Недостатком этого подхода является то, что если у вас есть много файлов для импорта, может быть сложно управлять всеми файлами Schema.ini.

Подход чисто VBA


Вы можете создать таблицу в памяти в ADODB и заполнить ее данными из файла csv. Вот небольшой пример кода, с которого можно начать.

Option Explicit

Private Function getTypedRS() As ADODB.Recordset
    Set getTypedRS = New ADODB.Recordset

    With getTypedRS
        'Add your other fields here
        .Fields.Append "DoubleField", adDouble
    End With
End Function

Public Sub CSVToADODB()
    Dim myTimer         As Double
    Dim FileNumber      As Long
    Dim FilePath        As String
    Dim FileData        As String
    Dim CSVArray        As Variant
    Dim i               As Long
    Dim rs              As ADODB.Recordset

    myTimer = Timer
    Set rs = getTypedRS()
    FilePath = "C:\Users\Ryan\Desktop\Example.csv"

    'Get the CSV
    FileNumber = FreeFile()
    Open FilePath For Binary Access Read As FileNumber
    FileData = Space$(LOF(FileNumber)) 'Create a buffer first, then assign
    Get FileNumber, , FileData
    Close FileNumber

    'My CSV is just a list of Doubles, should be relatively easy to swap out to process with ','
    CSVArray = Split(FileData, vbCrLf)

    'Add data
    rs.Open
    For i = LBound(CSVArray) + 1 To UBound(CSVArray) '+1 to skip header
        rs.AddNew
        rs.Fields("DoubleField").Value = CSVArray(i)
    Next
    rs.UpdateBatch
    rs.MoveLast

    Debug.Print rs.Fields("DoubleField").Value, "Processed 1000 records in: " & Timer - myTimer
End Sub

Хорошая сторона этого подхода в том, что он все еще довольно быстр. Мне удалось загрузить 1000 дублей за ~ 0,03 секунды, поскольку большинство действий, выполняемых здесь, выполняются в памяти. Это также устраняет необходимость в файле Schema.ini, однако есть больше кода для поддержки, так что это компромисс.

Рекомендация


Я бы попробовал изменить MaxScanRows, если это не сработает, создайте файл Schema.ini.

0 голосов
/ 14 января 2019

Попробуйте это

Sub Sample()
    Dim conn As New ADODB.Connection
    Dim RS As New ADODB.Recordset

    Dim FilePath As String, SheetName As String

    '~~> Replace this with relevant values
    FilePath = "C:\Users\routs\Desktop"
    Filename = "Sample.Csv"

    With conn
       .Provider = "Microsoft.ACE.OLEDB.12.0"
       .ConnectionString = "Data Source=" & FilePath & ";Extended Properties='text'"
       .Open
    End With

    strSQL = "select * from " & Filename

    RS.Open strSQL, conn

    '~~> Replace this with relevant field
    Debug.Print RS("Sale")
End Sub

enter image description here

...