Jet.OLEDB.4.0 Съкращаващ низ при импортиране от CSV

Имам приложение за Windows form, което приема CSV/Excel файлове, позволява на потребителите да ги импортират в SQL DB.

Наскоро имах странен бъг, при който потребителите качват CSV файл и той съкращава текста в колона.

Ето изходния файл:

Изходен файл

Ето DatagridView в моето приложение, показващ същите данни, след като се преобразува в таблица с данни:

След преобразуване

Забележете, че някои стойности са напълно празни и маркирани в червено, докато други изглеждат съкратени. Това обаче се случва само с CSV файлове, не и с excel. Това ме кара да вярвам, че може да е проблем с драйвера.

Ето кода, който преобразува данните от плоския файл в таблица с данни:

Private Function ConvertCSVToDataTable(ByVal path As String) As DataTable
    Using con As OleDb.OleDbConnection = New OleDb.OleDbConnection()
        Try
            If System.IO.Path.GetExtension(path) = ".csv" Then
                con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Text;HDR=YES;FMT=Delimited""", "Microsoft.Jet.OLEDB.4.0", IO.Path.GetDirectoryName(path))
                Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [" & IO.Path.GetFileName(path) & "]", con)
                    Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
                        con.Open()
                        da.Fill(dt)
                        con.Close()
                    End Using
                End Using
            ElseIf System.IO.Path.GetExtension(path) = ".xlsx" Then
                con.ConnectionString = String.Format("Provider={0};Data Source={1};Extended Properties=""Excel 12.0 Xml;HDR=Yes;IMEX=1""", "Microsoft.ACE.OLEDB.12.0", path)
                con.Open()
                Dim dbSchema As DataTable = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
                Dim firstSheetname As String = dbSchema.Rows(0)("TABLE_NAME").ToString
                Using cmd As OleDb.OleDbCommand = New OleDb.OleDbCommand("SELECT * FROM [" & firstSheetname & "]", con)
                    Using da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(cmd)
                        'con.Open()
                        da.Fill(dt)
                        con.Close()
                    End Using
                End Using
            End If

        Catch ex As Exception
            MessageBox.Show(ex.ToString(), "Conversion Error", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
        Finally
            If con IsNot Nothing AndAlso con.State = ConnectionState.Open Then
                con.Close()
            End If
        End Try
    End Using
    Return dt
End Function

Някаква идея на какво се дължи това? Трябва също да отбележа, че някои от моите потребители могат да импортират само CSV, а не Excel. Разбрах, че потребителите с 32-битов драйвер за достъп могат да импортират excel файлове, докато 64-битовите потребители не могат. Накарах ги да изтеглят драйвера тук:

https://www.microsoft.com/en-us/download/details.aspx?id=23734

Сега тези потребители могат да импортират Excel, но все още имат проблем с съкращаването на низовете. Което ме кара да вярвам, че все още може да е проблем с драйвера.

Данни от теста:

Sales Order #  
US00123  
US00123  
US00123  
SG0000123 
SG0000123 
S00123
S00123
S00123
S00123  
S00123  

person AlanPear    schedule 05.03.2018    source източник
comment
Тези клетки с данни не са близо до 255 знака   -  person AlanPear    schedule 06.03.2018
comment
Оттеглих дублираното гласуване, но това е единственият случай, който знам, когато низовете се съкращават. Споменавате 64 бита, но кодът ви показва използването на доставчика Jet. Jet съществува само като 32 битов доставчик. Доставчикът на ACE може да бъде 32-битов или 64-битов, но само с една инсталирана версия (да, виждал съм хакове, които твърдят, че позволяват инсталирането на 32 и 64 бита). Има ли шанс да предоставите извадка от данните, които се съкращават? т.е. осигурете възпроизводим пример.   -  person TnTinMn    schedule 06.03.2018
comment
Актуализирах го, за да включва тестовите данни, които се съкращават. Така че трябва ли и двете да са 32 бита? Също така се опитах да компилирам програмата си като 32-битово приложение, но това не проработи.   -  person AlanPear    schedule 14.03.2018


Отговори (1)


Успях да възпроизведа вашия проблем.

Проблемът е, че по някаква причина драйверът за текстов файл, използван от доставчика на Jet, интерпретира/анализира "S00123" като числова стойност. Трябваше да конфигурирам регистъра с MaxScanRows=0 и ImportMixedTypes="Majority Type".

Не знам защо се случва това, но просто го отдавам на друга радост от използването на лошо документирана технология. Изглежда, че всяко поле, което започва с "S", последвано от цифри, се интерпретира като число.

Ако настоявате да използвате тази технология, за да изпълните задача, за която има много по-добри възможности, тогава трябва да живеете с многото й недостатъци и странности.

Решение 1:

Конфигурирайте доставчика да импортира със стойност на регистъра ImportMixedTypes, зададена на „Текст“. Сега, ако направите тази промяна, за да позволите на вашата програма да работи, вие също ще носите отговорност за нарушаването на всеки друг код, който зависи от съществуващата конфигурация.

Местоположение на стойностите в системния регистър на 64-битова операционна система.

За доставчик на Jet:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet\4.0\Engines\Text

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Jet\4.0\Engines\Excel

За доставчик на ACE:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Text

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Excel

Решение 2:

Използвайте [Schema.ini]файл https://docs.microsoft.com/en-us/sql/odbc/microsoft/schema-ini-file-text-file-driver), за да определите как текстовият файл да се интерпретира с дефинирани колони.

Това е предпочитаният метод за използване на тази технология. Имайте предвид, че кодирането на файла е много важно; трябва да е в .Net кодирането System.Text.Encoding.ASCII или System.Text.Encoding.Unicode. Ако използвате друго кодиране като UTF-8, файлът няма да бъде прочетен и ще се използват настройките в системния регистър.

person TnTinMn    schedule 15.03.2018
comment
Уау, благодаря ти за този отговор. Кои са по-добрите опции, ако не използвам това? - person AlanPear; 15.03.2018
comment
@AlanPear, За CSV можете да използвате (клас TextFieldParser) (msdn.microsoft.com/en-us/library/). За Excel файлове, използващи файловия формат 2007+, има различни опции: Open XML SDK (този има стръмна крива на обучение), ClosedXML и различни търговски продукти. За по-старите Excel файлове във формат xls вероятно ще ви трябва търговски продукт. - person TnTinMn; 15.03.2018