如何从给定行开始从 Excel 读取数据并获得正确的类型推断
How to read data from Excel starting from given row and getting proper type inference
我正在使用这些连接字符串从 .xls 和 .xlsx 文件导入数据
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\file.xls;Extended Properties="Excel 8.0;HDR=YES;IMEX=0;MaxScanRows=16;Empty Text Mode=NullAsEmpty;"
或
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=0;MaxScanRows=16;Empty Text Mode=NullAsEmpty;"
我在数据表中加载数据。
Using connection As New OleDbConnection(connString)
connection.Open()
wsName = "myWorksheet$"
Dim SQL As [String] = String.Format("SELECT {1} FROM [{0}]", wsName, "*")
Dim da As New OleDbDataAdapter(SQL, connection)
Dim ds As New DataSet
da.Fill(ds)
dtb = ds.Tables(0)
End Using
如果数据从 excel 文件的第一行开始,我会得到正确键入的字段。不幸的是,一些 excel 文件(xls 和 xlsx 格式)在实际数据之前可能有几行 headers 和其他烦恼。这可能会破坏 Jet 的采样,这些字段以文本形式结尾,而这些字段本应是数字。
看来强制jet从X行开始读取是不可能的。
我还尝试使用 DataReader 前进到数据的开头,然后创建 DataTable
dtb.Load(reader)
但问题是一样的,字段类型是基于第一个实际行。
因此,我寻求有关如何获取数据表的建议,该数据表的字段类型与从 Excel 文件的第 x 行开始的数据相应地键入。
这是一条你踏上的黑暗之路。我最近一直在努力,在尝试了几种选择之后,我最终选择了 ExcelDataReader。这是一个不错的 .NET 库,可以很好地从 .xls 和 .xlsx 文件导入数据。基本导入如下:
IExcelDataReader excelReader = default(IExcelDataReader);
using (System.IO.FileStream excelStream = new System.IO.FileStream(fileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.ReadWrite)) {
if (System.IO.Path.GetExtension(fileName).ToLower() == ".xls") {
excelReader = ExcelReaderFactory.CreateBinaryReader(excelStream);
} else {
excelReader = ExcelReaderFactory.CreateOpenXmlReader(excelStream);
}
excelReader.IsFirstRowAsColumnNames = true;
}
// Library doesn't throw proper exceptions, create our own
if (excelReader.ExceptionMessage != string.Empty) {
throw new ExcelReaderException(excelReader.ExceptionMessage, fileName);
}
DataSet excelPages = excelReader.AsDataSet();
我正在使用遗留代码,所以我仍然必须将导入转换为数据集。但是,如果有机会,您可以使用 Sheet、Page 和 Cell 对象。到目前为止,我遇到的一个问题是我还没有找到 nice 解决方法,有时图书馆会从电子表格中导入空白行(几次,数以千计)。我们目前的解决方法是在导入后修剪那些。
对于 OLEDB:我相信您可以执行注册表更新来设置 OLEDB 使用的预读行数以确定列应设置为的数据类型。这是一个糟糕的选择,因为它必须在每台客户端机器上完成。此外,使用基于 Excel 的 OLEDB 导入时,您很可能会遇到其他问题。我记不住全部,但足以让我们完全放弃它。
我正在使用这些连接字符串从 .xls 和 .xlsx 文件导入数据
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\file.xls;Extended Properties="Excel 8.0;HDR=YES;IMEX=0;MaxScanRows=16;Empty Text Mode=NullAsEmpty;"
或
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=0;MaxScanRows=16;Empty Text Mode=NullAsEmpty;"
我在数据表中加载数据。
Using connection As New OleDbConnection(connString)
connection.Open()
wsName = "myWorksheet$"
Dim SQL As [String] = String.Format("SELECT {1} FROM [{0}]", wsName, "*")
Dim da As New OleDbDataAdapter(SQL, connection)
Dim ds As New DataSet
da.Fill(ds)
dtb = ds.Tables(0)
End Using
如果数据从 excel 文件的第一行开始,我会得到正确键入的字段。不幸的是,一些 excel 文件(xls 和 xlsx 格式)在实际数据之前可能有几行 headers 和其他烦恼。这可能会破坏 Jet 的采样,这些字段以文本形式结尾,而这些字段本应是数字。
看来强制jet从X行开始读取是不可能的。
我还尝试使用 DataReader 前进到数据的开头,然后创建 DataTable
dtb.Load(reader)
但问题是一样的,字段类型是基于第一个实际行。
因此,我寻求有关如何获取数据表的建议,该数据表的字段类型与从 Excel 文件的第 x 行开始的数据相应地键入。
这是一条你踏上的黑暗之路。我最近一直在努力,在尝试了几种选择之后,我最终选择了 ExcelDataReader。这是一个不错的 .NET 库,可以很好地从 .xls 和 .xlsx 文件导入数据。基本导入如下:
IExcelDataReader excelReader = default(IExcelDataReader);
using (System.IO.FileStream excelStream = new System.IO.FileStream(fileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.ReadWrite)) {
if (System.IO.Path.GetExtension(fileName).ToLower() == ".xls") {
excelReader = ExcelReaderFactory.CreateBinaryReader(excelStream);
} else {
excelReader = ExcelReaderFactory.CreateOpenXmlReader(excelStream);
}
excelReader.IsFirstRowAsColumnNames = true;
}
// Library doesn't throw proper exceptions, create our own
if (excelReader.ExceptionMessage != string.Empty) {
throw new ExcelReaderException(excelReader.ExceptionMessage, fileName);
}
DataSet excelPages = excelReader.AsDataSet();
我正在使用遗留代码,所以我仍然必须将导入转换为数据集。但是,如果有机会,您可以使用 Sheet、Page 和 Cell 对象。到目前为止,我遇到的一个问题是我还没有找到 nice 解决方法,有时图书馆会从电子表格中导入空白行(几次,数以千计)。我们目前的解决方法是在导入后修剪那些。
对于 OLEDB:我相信您可以执行注册表更新来设置 OLEDB 使用的预读行数以确定列应设置为的数据类型。这是一个糟糕的选择,因为它必须在每台客户端机器上完成。此外,使用基于 Excel 的 OLEDB 导入时,您很可能会遇到其他问题。我记不住全部,但足以让我们完全放弃它。