C# 读取Excel到DataTable两种方式对比

方式一 OLEDB读取 数据库引擎

优点:读取速度快,依据sheet排序读取

缺点:对于Excel版本依赖强,无法读取指定sheet

错误提示:本地计算机未指定 Microsoft.ACE.OLEDB.12.0

解决方法:win7(64位)+office 2010(64位) 更改目标平台为X86

win10(64位)+office 2010(64位) 更改目标平台无效,下载安装AccessDatabaseEngine.exe,重启无效,项目需求采用方式二

注:2019年7月20日之前和平台无关,均可使用(可能office服务被禁,公司特殊),情况紧急,采用方式二。

代码如下:

public static List<DataTable> excelToDataTable(string filePath)

{

List<DataTable> dtList = new List<DataTable>();

string connStr = "";

string fileType = System.IO.Path.GetExtension(filePath);

if (string.IsNullOrEmpty(fileType)) return null;

if (fileType == ".xls")

connStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + filePath + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"";

else

connStr = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + filePath + ";" + ";Extended Properties=\"Excel 12.0;HDR=N0;IMEX=1\"";

string sql_F = "Select * FROM [{0}]";

OleDbConnection conn = null;

OleDbDataAdapter da = null;

DataTable dtSheetName = null;

DataSet ds = new DataSet();

DataTable dtNew = new DataTable();

try

{

// 初始化连接,并打开

conn = new OleDbConnection(connStr);

conn.Open();

// 获取数据源的表定义元数据

string SheetName = "";

dtSheetName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });

// 初始化适配器

da = new OleDbDataAdapter();

for (int i = 0; i < dtSheetName.Rows.Count; i++)

{

DataTable dt = new DataTable();

SheetName = (string)dtSheetName.Rows[i]["TABLE_NAME"];

if (SheetName.Contains("$") && !SheetName.Replace("'", "").EndsWith("$"))

{

continue;

}

da.SelectCommand = new OleDbCommand(String.Format(sql_F, SheetName), conn);

dt.TableName = i.ToString();

da.Fill(dt);

dtList.Add(dt);

}

}

catch (Exception ex)

{

//MessageBox.Show(ex.ToString());

}

finally

{

// 关闭连接

if (conn.State == ConnectionState.Open)

{

conn.Close();

da.Dispose();

conn.Dispose();

}

}

return dtList;

}

方式二 Excel引擎读取 Microsoft.Office.Interop.Excel

使用方式:引用 Microsoft.Office.Interop.Excel 调用Excel读取

优点:不受Excel版本限制,可指定sheet读取

缺点:读取速度慢,几千数据10分钟

代码如下:

public static List<DataTable> excelToDataTable(string filePath,bool hasTitle = false)

{

List<DataTable> dtList = new List<DataTable>();

int iRowCount;

int iColCount;

Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();

Microsoft.Office.Interop.Excel.Sheets sheets;

object oMissiong = System.Reflection.Missing.Value;

Microsoft.Office.Interop.Excel.Workbook workbook = null;

DataTable dt = new DataTable();

try

{

if (app == null) return null;

workbook = app.Workbooks.Open(filePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,

oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);

sheets = workbook.Worksheets;

//将数据读入到DataTable中

Microsoft.Office.Interop.Excel.Worksheet worksheet = sheets.get_Item(1);

if (worksheet == null) return null;

iRowCount = worksheet.UsedRange.Rows.Count;

iColCount = worksheet.UsedRange.Columns.Count;

//生成列头

for (int i = 0; i < iColCount; i++)

{

var name = "column" + i;

if (hasTitle)

{

var txt = ((Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, i + 1]).Text.ToString();

if (!string.IsNullOrWhiteSpace(txt)) name = txt;

}

while (dt.Columns.Contains(name)) name = name + "_1";//重复行名称会报错。

dt.Columns.Add(new DataColumn(name, typeof(string)));

}

//生成行数据

Microsoft.Office.Interop.Excel.Range range;

int rowIdx = hasTitle ? 2 : 1;

for (int iRow = rowIdx; iRow <= iRowCount; iRow++)

{

DataRow dr = dt.NewRow();

for (int iCol = 1; iCol <= iColCount; iCol++)

{

range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[iRow, iCol];

dr[iCol - 1] = (range.Value2 == null) ? "" : range.Text.ToString();

}

dt.Rows.Add(dr);

}

dtList.Add(dt);

for (int i = 2; i <= sheets.Count; i++)

{

worksheet=sheets.get_Item(i);//读取第一张表

iRowCount = worksheet.UsedRange.Rows.Count;

iColCount = worksheet.UsedRange.Columns.Count;

//生成列头

for (int j = 0; j < iColCount; j++)

{

var name = "column" + i;

if (hasTitle)

{

var txt = ((Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, j + 1]).Text.ToString();

if (!string.IsNullOrWhiteSpace(txt)) name = txt;

}

while (dt.Columns.Contains(name)) name = name + "_1";//重复行名称会报错。

dt.Columns.Add(new DataColumn(name, typeof(string)));

}

//生成行数据

Microsoft.Office.Interop.Excel.Range range1;

int rowIdx1 = hasTitle ? 2 : 1;

for (int iRow = rowIdx1; iRow <= iRowCount; iRow++)

{

DataRow dr = dt.NewRow();

for (int iCol = 1; iCol <= iColCount; iCol++)

{

range1 = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[iRow, iCol];

dr[iCol - 1] = (range1.Value2 == null) ? "" : range1.Text.ToString();

}

dt.Rows.Add(dr);

}

dtList.Add(dt);

}

return dtList;

}

catch { return null; }

finally

{

workbook.Close(false, oMissiong, oMissiong);

System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);

workbook = null;

app.Workbooks.Close();

app.Quit();

System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

app = null;

}

}