当第一行是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议您使用的解决方法是读取文件两次(使用相同的方法):

  1. 首先,你得到了标题行,以后可能需要这个数据结构
  2. 在第二次读取时,您跳过标题并读取行。

这应该是这样的:

 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; } } } } } }