通过 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的主要内容,如果未能解决你的问题,请参考以下文章

C# OLEDB读取EXCEL的数据为空值

需要通过oledb连接从azure存储blob容器中读取excel文件

使用 OLEDB 数据提供程序读取 excel 文件

用于读取由其他用户独占打开的 Excel 文件的 OleDB 连接字符串

用OLEDB读取EXCEL时,单元格内容长度超过255被截断

关于oledb对Excel的读取(转)