通过 OLEDB 读取 Excel 将字符串读取为 DBNull
Posted
技术标签:
【中文标题】通过 OLEDB 读取 Excel 将字符串读取为 DBNull【英文标题】:Reading Excel by OLEDB reads strings as DBNull 【发布时间】:2010-06-02 06:48:00 【问题描述】:我正在使用 Csharp 中的 OLEDB 读取 Excel 文件,我已经展示了我所拥有的示例 excel 数据
F1 F2 F3 F4
India 23 44 4
China 4 8 Month 6
USA 45 Neg 4
当我读取这些数据并检查我的数据表时,我得到“第 6 个月”和“否定”的 Null 值 我可以在哪里正确获取 F1 列...我的连接字符串如图所示
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=[XLSource];Extended Properties=Excel 12.0;
OleDbDataReader dr;
OleDbConnection conExcel = new OleDbConnection();
conExcel.ConnectionString = ConnectionString
conExcel.Open();
OleDbCommand cmdExcel = new OleDbCommand();
cmdExcel.Connection = conExcel;
cmdExcel.CommandText = "SELECT * FROM Sheet1$";
dr = cmdExcel.ExecuteReader();
DataTable dtExcel = new DataTable();
dtExcel.Load(dr);
【问题讨论】:
你能把你读入数据表的代码显示出来吗? 没有足够的信息来回答 【参考方案1】:尝试在您的连接字符串中使用 IMEX=1 参数(谷歌了解更多信息)。
我认为发生的事情是 Excel 从前几行推断每列的数据类型。当它遇到与推断的数据类型不匹配的值时,它会将其视为 null。
【讨论】:
但是当我使用它时它需要在系统中注册一些 DLL,它显示“找不到可安装的 ISAM。” 您的连接字符串的语法可能是错误的。谷歌搜索“Excel Oledb 找不到可安装的 ISAM”会找到一些帮助,包括以下线程:devnewsgroups.net/adonet/… 扩展属性必须放在引号中 Extended Properties=""Excel 8.0;HDR=NO"""【参考方案2】:我遇到了这个问题,但我没有设置 IMEX=1,而是将注册表设置 TypeGuessRows
设置为 0 而不是默认的 8,我读到某处需要 IMEX,但它似乎以任何一种方式获取此注册表更改.
但是,我使用的是 Jet 提供程序而不是 Ace,所以这可能会有所不同。
对我来说,我在以下位置找到了设置:Hkey_Local_Machine/Software/Microsoft/Jet/4.0/Engines/Excel/TypeGuessRows
【讨论】:
当我将此值更改为零时,阅读工作表的时间太长:( 嗯,据我所知,有效值为 0-16,其中 0 表示读取所有行(最多 65000 行或我认为的东西,所以它不适合大床单)来决定数据类型,而其他值意味着读取那么多行,所以我想你可以试试 16 看看是否有帮助。【参考方案3】:我回答了一个类似的问题here。为了您的方便,我在这里复制并粘贴了相同的答案:
我也遇到过同样的问题,但无需借助 Excel COM 接口或第 3 方软件即可解决。它涉及一些处理开销,但似乎对我有用。
-
先读入数据得到列名
然后使用这些列中的每一列创建一个新的 DataSet,将它们的每个 DataTypes 设置为字符串。
再次将数据读入这个新的
数据集。瞧——科学的
符号现在消失了,所有内容都作为字符串读入。
这里有一些代码可以说明这一点,作为额外的奖励,它甚至是 StyleCopped!
public void ImportSpreadsheet(string path)
string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1";
string connectionString = string.Format(
CultureInfo.CurrentCulture,
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=0;Extended Properties=\"1\"",
path,
extendedProperties);
using (OleDbConnection connection = new OleDbConnection(connectionString))
using (OleDbCommand command = connection.CreateCommand())
command.CommandText = "SELECT * FROM [Worksheet1$]";
connection.Open();
using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
using (DataSet columnDataSet = new DataSet())
using (DataSet dataSet = new DataSet())
columnDataSet.Locale = CultureInfo.CurrentCulture;
adapter.Fill(columnDataSet);
if (columnDataSet.Tables.Count == 1)
var worksheet = columnDataSet.Tables[0];
// Now that we have a valid worksheet read in, with column names, we can create a
// new DataSet with a table that has preset columns that are all of type string.
// This fixes a problem where the OLEDB provider is trying to guess the data types
// of the cells and strange data appears, such as scientific notation on some cells.
dataSet.Tables.Add("WorksheetData");
DataTable tempTable = dataSet.Tables[0];
foreach (DataColumn column in worksheet.Columns)
tempTable.Columns.Add(column.ColumnName, typeof(string));
adapter.Fill(dataSet, "WorksheetData");
if (dataSet.Tables.Count == 1)
worksheet = dataSet.Tables[0];
foreach (var row in worksheet.Rows)
// TODO: Consume some data.
【讨论】:
【参考方案4】:我回答another question 很像这个。
简而言之,控制 ACE 驱动程序行为的设置位于注册表中:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\14.0\Access Connectivity Engine\Engines\Excel
将ImportMixedTypes
设置为Text
并将TypeGuessRows
设置为0
(或像1000
这样的适当大的数字),您应该会得到您所期望的行为。
【讨论】:
以上是关于通过 OLEDB 读取 Excel 将字符串读取为 DBNull的主要内容,如果未能解决你的问题,请参考以下文章
需要通过oledb连接从azure存储blob容器中读取excel文件
用于读取由其他用户独占打开的 Excel 文件的 OleDB 连接字符串