当第一行是string时,GetValue()不读取十进制值
使用Microsoft.ACE.OLEDB.12.0提供者从Excel Sheet读取数据。 我使用OleDbDataReader
和他的GetValue()
获取数据。 第一行/行(可以多一个)是string标题,我不能跳过它。 接下来是设置为小数点后0位的数字数据,但是当我select其中的一个时,它会以正确的十进制格式显示在栏中。
我怎样才能读取像Excel中的酒吧一样的原始十进制格式的混合数据? 我无法更改Excel表单的设置。
这是我的代码:
using System.Data.OleDb; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { string query = "SELECT * FROM [List1$]"; string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Temp\Test.xls;Extended Properties=""Excel 12.0;HDR=NO;IMEX=1"""; using (OleDbConnection connection = new OleDbConnection(connString)) { connection.Open(); using (OleDbCommand command = new OleDbCommand(query, connection)) { using (OleDbDataReader reader = command.ExecuteReader()) { while (reader.Read()) { object value = reader.GetValue(0); } } } } } } }
从经验来看,你可能要做的最好的是以下。 我一直有问题与Excel文件,阅读数据。 这就是为什么我鄙视excel作为数据传输机制。
我曾经为一家通过excel获得了所有“银行数据”的公司工作。 我很高兴被certificate是错误的。
注意。 GetValue(0)运行后,在其上放置一个监视。 它可能会告诉你它的一个string。 但是你可以确定它的想法,然后调整你的“获取”方法。 就像,如果值是一个“string”,您可以将GetValue(0)更改为GetString(0)。
while (reader.Read()) { Decimal tryParseResultDec; object value = reader.GetValue(0); if !(Decimal.TryParse(value, out tryParseResultDec)) { throw new ArgumentException(string.Format("Unable to parse '{0}'.", value)); } }
额外的build议。
而不是“0”,“1”,“2”等等,我通常会把一些私有的const放在类的顶部来告诉我列是什么。
private const int EXCEL_COLUMN_TOTAL_AMOUNT = 0;
(你可以做这样的事情,你只是简单的例子)
额外提示:
我认为它的工作方式是,Excel会查看第一行数据 ,查看数据types,并将其用于同一列中的其余行。 我不认为它说“检查每行的数据types”。 因此你的难题。
如果你说没有标题行,它将在A1中查找A中所有行的数据types。如果你说有一个标题行,它将在A中查看A2中所有行的数据types。
尝试在连接string中使用HDR=YES
并停止跳过第一行:
string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\Temp\Test.xls;Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""";
[UPDATE]
我build议您使用的解决方法是读取文件两次(使用相同的方法):
- 首先,你得到了标题行,以后可能需要这个数据结构
- 在第二次读取时,您跳过标题并读取行。
这应该是这样的:
using System; using System.Collections.Generic; using System.Linq; using System.Data.OleDb; using System.Data; using System.IO; class Program { static void Main(string[] args) { // the Excel file string file = @"c:\Temp\Test.xls"; if (!File.Exists(file)) { Console.WriteLine("File not found."); return; } // DataTable bonus! :) System.Data.DataTable dt = new System.Data.DataTable(); IEnumerable<List<object>> header = new List<List<object>>(); IEnumerable<List<object>> rows = new List<List<object>>(); // read the header first header = GetData(file, true); // read the rows rows = GetData(file, false); // add the columns foreach (var column in header.First()) { dt.Columns.Add(column.ToString()); } // add the rows foreach (var row in rows) { dt.Rows.Add(row.ToArray()); } // now you may use the dt DataTable for your purpose } /// <summary> /// Read from the Excel file /// </summary> /// <param name="file">The path to the Excel file</param> /// <param name="readHeader">True if you want to read the header, /// False if you want to read the rows</param> /// <returns></returns> private static IEnumerable<List<object>> GetData(string file, bool readHeader) { string query = "SELECT * FROM [List1$]"; string connString = @"Provider=Microsoft.ACE.OLEDB.12.0;" + @"Data Source=" + file + @";Extended Properties=""Excel 12.0 Xml;HDR=NO;IMEX=" + ((readHeader) ? "1" : "0") + @";"""; using (OleDbConnection connection = new OleDbConnection(connString)) { connection.Open(); using (OleDbCommand command = new OleDbCommand(query, connection)) { using (OleDbDataReader reader = command.ExecuteReader()) { bool isHeaderRead = false; while (reader.Read()) { if (readHeader && isHeaderRead) { break; } isHeaderRead = true; List<object> values = new List<object>(); for (int i = 0; i < reader.FieldCount; i++) { values.Add(reader.GetValue(i)); } yield return values; } } } } } }