Проблема с использованием OleDbDataAdapter для извлечения данных из листа Excel

Во-первых, я хочу сказать, что я здесь глубоко в воде, так как я просто делаю некоторые изменения в коде, который написан кем-то еще в компании, используя OleDbDataAdapter для «общения» с Excel, и я не знаком с этим. Там есть одна ошибка, которую я просто не могу понять.

Я пытаюсь использовать OleDbDataAdapter для чтения в файле excel примерно с 450 строками.

В коде это сделано так:

connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source='" + path + "';" + "Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1;\"");
connection.Open();
OleDbDataAdapter objAdapter = new OleDbDataAdapter(objCommand.CommandText, connection);
objAdapter.Fill(objDataSet, "Excel");

foreach (DataColumn dataColumn in objTable.Columns) {
  if (dataColumn.Ordinal > objDataSet.Tables[0].Columns.Count - 1) {
    objDataSet.Tables[0].Columns.Add();
  }
  objDataSet.Tables[0].Columns[dataColumn.Ordinal].ColumnName = dataColumn.ColumnName;
  objImport.Columns.Add(dataColumn.ColumnName);
}

foreach (DataRow dataRow in objDataSet.Tables[0].Rows) {
   ...
}

Кажется, все работает нормально, кроме одного. Второй столбец заполнен в основном четырехзначными числами, такими как 6739, 3920 и т. д., но первые строки имеют буквенно-цифровые значения, такие как 8201NO и 8205NO. Сообщается, что эти пять ячеек имеют пустое содержимое вместо их буквенно-цифрового содержимого. Я проверил в Excel, и все ячейки в этих столбцах помечены как текст.

Кстати, это файл xls, а не xlsx.

Кто-нибудь знает, почему эти ячейки отображаются как пустые в DataRow, но числовые отображаются нормально? Есть и другие столбцы с буквенно-цифровым содержимым, которые отображаются нормально.


person Øyvind Bråthen    schedule 28.09.2010    source источник
comment
Спасибо всем за помощь в этом вопросе. Вы заставили меня понять, почему это произошло, чтобы я мог найти правильное решение. Я до сих пор думаю, что то, как это работает, довольно ужасно, но это уже другая история :)   -  person Øyvind Bråthen    schedule 29.09.2010


Ответы (3)


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

Проблема возникает, когда вы пытаетесь запросить эту таблицу с помощью jet. Когда он думает, что имеет дело с числовым столбцом, и находит значение varchar, он спокойно ничего не возвращает. Нет даже загадочного сообщения об ошибке.

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

Взгляните на эту статью< /а>. В нем более подробно рассматривается этот вопрос. в нем также говорится о возможном обходном пути, который:

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

person Abe Miessler    schedule 28.09.2010
comment
Я проверил это сейчас, и действительно, если я поставлю первую строку буквенно-цифровой, то она будет работать, как и ожидалось. Моя проблема в том, что я не могу сделать это общим правилом, так как клиенты будут читать в своих собственных листах. Однако мое решение состояло в том, чтобы обмануть, поэтому я изменил HDR= No в строке подключения, чтобы убедиться, что буквенно-цифровой заголовок читается, чтобы сделать столбец буквенно-цифровым, а затем я вырезал первую строку результирующего DataTable. Это довольно противно, но я не вижу здесь других вариантов. Большое спасибо за вашу помощь, направляя меня в правильном направлении. - person Øyvind Bråthen; 29.09.2010

IMEX=1 означает «Читать смешанные данные как текст».

Однако есть некоторые ошибки. Jet будет использовать только несколько строк, чтобы определить, смешаны ли данные, и если это произойдет, все эти строки будут числовыми, вы получите такое поведение.

Подробнее см. на connectionstrings.com:

Проверьте [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel] расположенный реестр REG_DWORD "TypeGuessRows". Это ключ к тому, чтобы не позволить Excel использовать только первые 8 строк для угадывания типа данных столбцов. Установите это значение равным 0, чтобы сканировать все строки. Это может повредить производительности. Также обратите внимание, что добавление параметра IMEX=1 может привести к тому, что функция IMEX будет установлена ​​уже после 8 строк. Вместо этого используйте IMEX=0, чтобы обязательно заставить реестр TypeGuessRows=0 (сканировать все строки) работать.

person GSerg    schedule 28.09.2010
comment
Я не знаю, как Jet отображается в Excel, но в Access вы можете изменять подобные вещи во время выполнения в вашем текущем экземпляре механизма Jet db без необходимости изменять реестр и перезапускать Access. - person David-W-Fenton; 29.09.2010
comment
Спасибо за эту информацию. Это работало, но было на удивление медленно, поэтому вместо этого мне пришлось использовать трюк с заголовком read and dispose. - person Øyvind Bråthen; 29.09.2010

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

Вы можете попробовать это решение с открытым исходным кодом: http://exceldatareader.codeplex.com/.

person MarkPflug    schedule 28.09.2010
comment
Я полностью согласен с вами, Марк. Я думаю, что это довольно ужасно, но в данном случае у меня нет никаких вариантов, так как мне поручили исправить эту ошибку в существующей программе, и у меня не было выделено время для проведения каких-либо крупных рефакторингов. Я буду иметь в виду вашу ссылку, если мне нужно будет сделать это с нуля позже. - person Øyvind Bråthen; 29.09.2010