在ASP.NET中读取Excel:如果列具有不同的数据格式,则不会读取数据
我有一个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'");
我的一个列有不同格式的数据,如string,数字,date等等,在运行这个时候,当数据格式不同时,它不会从excel文件读取这个值。 我在网上search了很多,发现我们需要在连接string中提到IMEX proprety。我补充说,但没有正面的回应!
如果有任何内置的Excel驱动程序会查询表单的前8行,然后做出决定(没有您的许可或知识),它是什么types的列,从而忽略任何不在表中稍后讨论这种数据types。
http://www.mattjwilson.com/blog/2009/02/13/microsoft-excel-drivers-and-imex/
有没有办法摆脱这个问题?
您正在遇到JET引擎的许多有趣function之一。 这一个将基本上采样每行的所有数据为单个列,它会尝试猜测数据格式。 如果你想要你的代码“只是工作”,那么有一个registry设置,将有助于这一点。 但是,应该预先告知,这个registry设置将影响JET如何与系统上的所有import配合使用,而不仅仅是您的特定import。
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel] "ImportMixedTypes"="Text" "TypeGuessRows"=dword:00000000
这个registry设置将告诉JET在猜测格式之前检查列中每一行的格式。 如果find混合内容,则会将该行作为文本导入。
在默认情况下,JET在猜测时testing前25行。
或者,您可以将TypeGuessRows更改为1,JET将仅在猜测types时才检查第一行。 这意味着如果第一行是一个数字,第二行是一个stringJET将假定所有的行都是数字,你将无法使用ADO.NET读取它们
另一个警告:确保编辑registry时要小心。 如果您不小心,可以非常快速地减less系统的数量。
更新:似乎微软真的不build议在服务器上使用Excel COM服务。 尽pipe如此,许多开发人员在非.NET(如我的雇主)和.NET(请参见这里 )环境中都做这些,因为替代方法是昂贵的。 所有问题都是可以解决的(除了潜在的可扩展性和大容量应用程序的性能问题以及某些情况下的许可问题)。 昂贵的替代品正在使用这样的第三方解决scheme。
如果在一列中有不同数据types的数据,则不应使用OleDbConnection。 您可以尝试使用Excel从Excel读取COM / OLE API,例如(从这里编译,可能包含错误):
在项目中包含以下参考资料:
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;
重要! 你应该释放所使用的资源。 从这里 :
// 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!
用于.NET的SpreadsheetGear可以读取,写入,计算等… Excel工作簿,并允许您使用API(如IWorksheet)访问任何单元格的基础数据(数字,文本,逻辑,错误)或任何单元格的格式化文本。单元格[rowIndex,colIndex] .Value或IWorksheet.Cells [rowIndex,colIndex] .Text。 基于每个列/单元格中的数据types没有限制。 SpreadsheetGear是100%安全的.NET代码(没有COM互操作性,没有不安全的本地调用等),所以比其他选项更容易部署 – 特别是在服务器场景中。
你可以在这里看到活的样品,并在这里下载免费试用。
免责声明:我自己的SpreadsheetGear LLC
当一切都失败了,这就是我所做的…从Excel导入时,我指定HDR = NO
在连接string。 这导入头作为第一行,从而使所有的列数据types作为文本。 之后,提供一个简单的函数来提及datatable的列名。 像下面的代码…
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; }
我知道这很乏味,但没有find任何可行的解决办法。 任何其他build议是一个欢迎。