Причудливый выбор из файла Excel с помощью метода OleDbDataAdapter (C #)

У меня есть файл Excel в таком виде:

Column 1    Column 2    Column 3  
 data1        data2    
 data1        data2  
 data1        data2  
 data1        data2  
 data1        data2       data3  

То есть весь столбец 3 пуст, за исключением последней строки. Я получаю доступ к файлу Excel через OleDbDataAdapter, возвращая DataTable: вот код.

query = "SELECT * FROM [" + query + "]";
objDT = new DataTable();
objCmdSQL = this.GetCommand();
objCmdSQL.CommandText = query;
objSQLDad = new OleDbDataAdapter(objCmdSQL);
objSQLDad.Fill(objDT);
return objDT;

Дело в том, что в этом сценарии мой код возвращает DataTable только с столбцом 1 и столбцом 2.
Я предполагаю, что механизм JET пытается определить тип столбца по типу самой первой ячейки в каждом столбце; будучи первым значением null, весь столбец игнорируется.
Я попытался ввести нули, и этот код фактически возвращает все три столбца; очевидно, что это наименее предпочтительное решение, поскольку мне приходится обрабатывать большое количество небольших файлов.
Инвертирование диапазона выбора (от, например, «A1: C5» до «C5: A1») тоже не работает. Я ищу что-то более элегантное.
Я уже нашел пару сообщений, в которых обсуждались несоответствия типов (ячейки varchar в столбцах int и наоборот), но на самом деле не нашел ничего, связанного с этим.
Спасибо за чтение!

редактировать

Опять странное поведение. Мне приходится работать в основном с файлами .xls Excel 2003, но, поскольку на этот вопрос был дан ответ, я подумал, что могу протестировать свой код на файлах .xslx Excel 2007. Строка подключения следующая:

string strConn = @"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + _fileName.Trim() + @";Extended Properties=""Excel 12.0;HDR=No;IMEX=1;""";

Я получаю исключение «Внешняя таблица не в ожидаемом формате», которое, как я считаю, является стандартным исключением, когда существует несоответствие версий между ACE / JET и открываемым файлом.

Струна

Provider=Microsoft.ACE.OLEDB.12.0 

означает, что я использую самую последнюю версию OLEDB, я быстро посмотрел вокруг, и эта версия используется везде, где требуется подключение к файлам .xlsx.
Я пробовал использовать только ванильный провайдер (только Excel 12.0, без IMEX и HDR), но я получаю то же исключение.
Я использую .NET 2.0.50727 SP2, может, пора обновить?


person SimoneF    schedule 01.12.2010    source источник
comment
Значит, в Excel нет заголовков в столбцах? А переключатель IMEX на соединении пробовали?   -  person Sorax    schedule 01.12.2010
comment
Заголовки есть, но я выбираю ту часть таблицы, которая содержит только данные, избегая горизонтальных и вертикальных заголовков.   -  person SimoneF    schedule 02.12.2010


Ответы (1)


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

string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\MyExcel.xls;Extended Properties=""Excel 8.0;HDR=No;IMEX=1"";";
DataTable dt = new DataTable();
OleDbConnection conn = new OleDbConnection(connString);
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", conn);

adapter.Fill(dt);

Обратите внимание: я использовал Access Database Engine(ACE) провайдера, который пришел на смену старому Joint Engine Technology(JET) провайдеру, и мои результаты могут отражать разницу в поведении между ними. Конечно, если вы еще не используете его, я предлагаю использовать поставщика ACE, как я полагаю, Microsoft тоже. Также обратите внимание на Extended Properties соединения:

«HDR = Да;» указывает, что первая строка содержит имена столбцов, а не данные. "HDR = Нет;" указывает на обратное.

«IMEX = 1;» указывает драйверу всегда читать "смешанные" (числа, даты, строки и т. д.) столбцы данных как текст. Обратите внимание, что этот параметр может отрицательно повлиять на доступ к записи в Excel.

Позвольте мне знать, если это помогает.

person Sorax    schedule 01.12.2010
comment
IMEX = 1 полезен только до записи реестра для TypeGuessRows, обычно 6, я думаю (0 = все строки) - person Fionnuala; 01.12.2010
comment
Это работает! Теперь метод может возвращать DataSet со всеми тремя столбцами и заполняет NULL там, где нет данных. Спасибо за понимание, Соракс. - person SimoneF; 02.12.2010