方式一 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;
            }
        }

C# 读取Excel到DataTable两种方式对比的更多相关文章

  1. java读取excel文件的两种方式

    方式一: 借用 package com.ij34.util; /** * @author Admin * @date 创建时间:2017年8月29日 下午2:07:59 * @version 1.0 ...

  2. .NET环境下导出Excel表格的两种方式和导入两种类型的Excel表格

    一.导出Excel表格的两种方式,其中两种方式指的是导出XML数据类型的Excel(即保存的时候可以只需要修改扩展名为.xls)和真正的Excel这两种. using System; using Sy ...

  3. C++读取字符串数据的两种方式

    C++读取字符串数据的两种方式 对于同样的样例输入: ladder came tape soon leader acme RIDE lone Dreis peat ScAlE orb eye Ride ...

  4. [Python]xlrd 读取excel 日期类型2种方式

    有个excle表格须要做一些过滤然后写入数据库中,可是日期类型的cell取出来是个数字,于是查询了下解决的办法. 主要的代码结构 data = xlrd.open_workbook(EXCEL_PAT ...

  5. Java值创建线程的两种方式对比

    在Java中创建线程的方式有两种,第一种是直接继承Thead类,另一种是实现Runable接口.那么这两种方式孰优孰劣呢? 采用继承Thead类实现多线程: 优势:编写简单,如果需要访问当前线程,只需 ...

  6. 多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比

    Thread.Start(),ThreadPool.QueueUserWorkItem都是在实现多线程并行编程时常用的方法.两种方式有何异同点,而又该如何取舍? 写一个Demo,分别用两种方式实现.观 ...

  7. java操作excel常用的两种方式

    Excel是我们平时工作中比较常用的用于存储二维表数据的,JAVA也可以直接对Excel进行操作,在这篇博客中将为大家介绍两种操作Excel的方式,分别为:jxl和poi. 对于两者的区别网上有测试如 ...

  8. c# 读取excel数据的两种方法(转)

    转载自:http://developer.51cto.com/art/201302/380622.htm, 方法一:OleDb: 用这种方法读取Excel速度还是非常的快的,但这种方式读取数据的时候不 ...

  9. c# 读取excel数据的两种方法

    转载自:http://developer.51cto.com/art/201302/380622.htm, 方法一:OleDb: 用这种方法读取Excel速度还是非常的快的,但这种方式读取数据的时候不 ...

随机推荐

  1. 兄弟连 企业shell笔试题 16-31

    企业实践题16:企业案例:写网络服务独立进程模式下rsync的系统启动脚本 例如:/etc/init.d/rsyncd{start|stop|restart} .要求:1.要使用系统函数库技巧.2.要 ...

  2. React中ref的使用

    直接获取DOM元素时使用的,一般情况下尽量不要使用ref

  3. mongoose报错:DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

    mongoose报错:(node:15689) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes ...

  4. 3,HDFS原理

    1,HDFS体系结构 ··· HDFS是采用master/slaves即主从结构模型来管理数据的.这种模型主要由四部分组成,分别是Client.NameNode.DataNode.SecondaryN ...

  5. 联合索引在B+树上的存储结构及数据查找方式

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! 引言 上一篇文章<MySQL索引那些事>主要讲了MySQL索引的底层原理,且对比了B ...

  6. 生成JavaDoc文档

    JavaDoc是一种将注释生成HTML文档的技术,生成的HTML文档类似于Java的API,易读且清晰明了.在简略介绍JavaDoc写法之后,再看一下在Intellij Idea 中如何将代码中的注释 ...

  7. OpenCASCADE(一) VS2017+OpenCASCADE+MFC 下载配置安装运行单文档程序画个基本图形

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12368154.html 一.下载OpenCASCADE 官网下载是: http://www.o ...

  8. com.google.gson json字符串的序列化与反序列化

    经常做协议的时候用到json,个人习惯是定义协议文档,很少在这中场景中定义类,使用对象. 这里使用一个人物有名字,性别,有一个物品列表做个简单示例记录. 序列化 JsonObject jo=new J ...

  9. ubuntu18.04误删apt-get命令恢复总结

    1.背景 由于使用aptitude命令替换了apt-get命令后感到后悔,想要恢复apt-get命令,特此总结以下踩过的坑 aptitude和apt-get的区别:https://www.cnblog ...

  10. Linux 防SSH暴力攻击

    在下这几天发现我的VPS 总是莫名遭受到 江苏镇江那边的IP 登录请求攻击 ,跟踪了下路由,发现ip是从蒙古那边出去的,然后意识到可能是有扫描端口的.. 方法一: 现在的互联网非常不安全,很多人没事就 ...