在ASP.NET中读取Excel:如果列具有不同的数据格式,则不会读取数据

时间:2009-11-09 06:59:54

标签: c# asp.net excel oledbconnection

我有一个asp.net C#应用程序,我正在使用OLEDBConnection读取电子表格的内容。我使用以下代码行从excel电子表格中读取。

 OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fullFilePath + ";Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'");

我的一个专栏中有各种格式的数据,如各种行中的字符串,数字,日期等。运行时,当数据格式不同时,它不会从excel文件中读取该值。我在网上搜索了很多,发现我们需要在连接字符串中提到IMEX proprety。我补充说,但没有积极的回应!。

经过大量研究后,如果任何内置的Excel驱动程序将查询工作表的前8行,然后(无需您的许可或知识)确定它是什么类型的列,从而忽略任何在工作表的后面不符合此数据类型。

http://www.mattjwilson.com/blog/2009/02/13/microsoft-excel-drivers-and-imex/

有没有摆脱这个问题?

4 个答案:

答案 0 :(得分:2)

您正在遇到JET引擎的众多有趣功能之一。这个基本上会对单个列中每行的所有数据进行采样,并尝试猜测数据格式。如果您希望您的代码“正常工作”,那么有一个注册表设置将有助于此。但是,请注意,此注册表设置将影响JET如何与系统上的所有导入一起使用,而不仅仅是您的特定导入。

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel]
"ImportMixedTypes"="Text"
"TypeGuessRows"=dword:00000000

此注册表设置将告诉JET在猜测格式之前检查列中每行的格式。如果找到混合内容,则会将该行作为文本导入。

默认情况下 类型猜测时,JET测试前25行。

或者你可以将TypeGuessRows更改为1,JET只会在类型猜测时检查第一行。这意味着如果第一行是数字而第二行是字符串,JET将假定所有行都是数字,并且您将无法使用ADO.NET读取它们

另一个警告:确保在编辑注册表时要小心。如果不小心,可以快速抽取系统。

答案 1 :(得分:1)

更新:似乎Microsoft真的does not recommend在服务器上使用Excel COM服务。尽管如此,许多开发人员都会使用非.NET(我的雇主)和.NET(参见here)环境,因为替代方案成本很高。所有问题都是可解决的(除了大批量应用程序中的潜在可伸缩性和性能问题,以及某些情况下的许可证问题)。昂贵的替代方案正在使用第三方解决方案,如this

如果在一列中包含不同数据类型的数据,则不应使用OleDbConnection。您可以尝试使用Excel COM / OLE API从Excel中读取(例如,从here编译,可能包含错误):

在项目中包含以下参考:

Microsoft Excel 10.0对象库

Microsoft Office 10.0对象库

包括名称空间Excel。

  using Excel;
  ...
      Excel.ApplicationClass xl = new Excel.Application();
      xl.Visible = false;
      xl.UserControl = false;
      Excel.Workbook theWorkbook = xl.Workbooks.Open(
         fileName, 0, true, 5,
          "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false,
          0, true); 
     Excel.Sheets sheets = theWorkbook.Worksheets;
     Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);
     System.Array myvalues;
     Excel.Range range = worksheet.get_Range("A1", "E1".ToString());
     myvalues = (System.Array)range.Cells.Value;

重要!您应该释放使用的资源。来自here

// Need all following code to clean up and extingush all references!!!
theWorkbook.Close(null,null,null);
xl.Workbooks.Close();
xl.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject (range);
System.Runtime.InteropServices.Marshal.ReleaseComObject (sheets);
System.Runtime.InteropServices.Marshal.ReleaseComObject (xl);
System.Runtime.InteropServices.Marshal.ReleaseComObject (worksheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject (theWorkbook);
worksheet=null;
sheets=null;
theWorkbook=null;
xl = null;
GC.Collect(); // force final cleanup!

答案 2 :(得分:0)

SpreadsheetGear for .NET可以读取,写入,计算等... Excel工作簿,允许您使用API​​访问任何单元格的基础数据(数字,文本,逻辑,错误)或任何单元格的格式化文本例如IWorksheet.Cells [rowIndex,colIndex] .Value或IWorksheet.Cells [rowIndex,colIndex] .Text。基于每个列/单元格中的数据类型没有限制。 SpreadsheetGear是100%安全的.NET代码(没有COM互操作,没有不安全的本机调用等...)因此它比其他选项更容易部署 - 特别是在服务器场景中。

您可以查看实时样本here并下载免费试用here

免责声明:我拥有SpreadsheetGear LLC

答案 3 :(得分:0)

当其他一切都失败时,这就是我所做的......从excel导入时,我在连接字符串中指定了HDR = NO。这会将标头导入为第一行,从而使所有列数据类型都为文本。之后是一个简单的函数,提到数据表的列名。像下面的代码......

private DataTable NameHeaderRows(DataTable dt)
{
    for (int i = 0; i < dt.Columns.Count; i++)
    {
        dt.Columns[i].ColumnName = dt.Rows[0][i].ToString();

    }
    dt.Rows.RemoveAt(0);
    return dt;
}

我知道这很乏味,但没有找到任何可行的解决方案。任何其他建议都是受欢迎的。