使用Microsoft.ACE.OLEDB.12.0提供程序从Excel Sheet中读取数据。
我正在使用OleDbDataReader
和他的GetValue()
来获取数据。
第一行/每行(可能多于一行)是字符串标题,我不能跳过它。
接下来是设置为小数点后0位的数字数据,但是当我选择其中一个时,它会以正确的十进制格式显示在条形图中。
如何以完整的原始十进制格式读取此混合数据,如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);
}
}
}
}
}
}
}
答案 0 :(得分:2)
尝试在连接字符串中使用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] 强>
我建议您使用的解决方法是读取文件的两倍(使用相同的方法):
以下是它的外观:
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;
}
}
}
}
}
}
答案 1 :(得分:2)
根据经验,你可能会做的最好的是下面的。 我一直有excel文件的问题,阅读数据。 这就是为什么我鄙视excel作为数据传输机制。
我曾在一家通过Excel获得所有“银行数据”的公司工作。 我很高兴被证明是错的。
请注意。 GetValue(0)运行后,将手表放在上面。它可能会告诉你它的字符串。 但你可以确定它的想法,然后调整你的“获取”方法。 比如,如果值是“字符串”,则可以将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));
}
}
额外建议。
而不是“0”,“1”,“2”等,我通常会在类的顶部放置一些私有const来告诉我列是什么。
private const int EXCEL_COLUMN_TOTAL_AMOUNT = 0;
(你可以这样做,你只是保持这个例子简单)
额外提示:
我认为它的工作方式是excel将查看第一行数据,并查看数据类型,并将其用于同一列中的其余行。我不认为它说“检查每一行的数据类型”。因而你的难题。
如果你说没有标题行,它会在A1中查看A中所有行的数据类型。如果你说有一个标题行,它将在A2中查看A中所有行的数据类型。