我有一个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/
有没有摆脱这个问题?
答案 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互操作,没有不安全的本机调用等...)因此它比其他选项更容易部署 - 特别是在服务器场景中。
免责声明:我拥有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;
}
我知道这很乏味,但没有找到任何可行的解决方案。任何其他建议都是受欢迎的。