方式一 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. asp.net mvc项目实战遇见问题及解决方式----ajax请求500错误,请求多表数据

    ajax请求出现500错误——但是想实现的功能是,把一个页面分成了两份,点击右边导航栏,利用ajax请求,请求数据,在右边出现相应页面,当时使用的是partialAction然后出现了这个500错误, ...

  2. c语言double类型的输入

    double输入用 %lf ,而不能用 %f 今天在使用double类型输入时先用了 scanf("%lf", &a),结果以%f输出的时候都是0,以%g,%e输出似乎是最 ...

  3. console控制台的用法

    参考链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Console 1,console.log('a'); 2,console.dir(xx); ...

  4. .NET CORE(C#) WPF亚克力窗体

    微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. .NET CORE(C#) WPF亚克力窗体 阅读导航 本文背景 代码实现 本文参考 源码 1 ...

  5. 展讯平台uboot启动流程

    启动流程 1. Stage1 start.S代码结构 u-boot的stage1代码通常放在start.S文件中,用汇编语言,主要实现功能如下:  (1) 定义入口: 该工作通过修改连接器脚本来完成. ...

  6. 《手把手教你构建自己的 Linux 系统》学习笔记(3)

    需要注意的是,制作操作系统权限全程都要用 root pushd 和 popd 为了方便目录管理,所以出现了这种两个命令,他们的原理就是利用堆栈来实现目录管理. 这两个命令,pushd 负责将指定的目录 ...

  7. Docker 网络原理

    引言 学习docker网络,可以带着下面两个问题来探讨 容器之间可以相互访问的原理 容器暴露端口后,通过宿主机访问到容器内应用,并且对于访问端而言不用感知容器存在的原理 Docker 本身的技术依赖L ...

  8. bzoj3162独钓寒江雪

    题意 \(n\)阶树,求本质不同的独立集个数 做法 重新编号后重心是不变的,如果有两个重心,可以加个虚点 用树哈希判子树有多少个相同的子树,设某种有\(k\)个,如果原本方案数为\(x\)个 则方案数 ...

  9. ipad的12系统里提示更新到ipdos13,原来安装在12上的app是不是没有了,要重新下载

    ipad的12系统里提示更新到ipdos13,原来安装在12上的app是不是没有了,要重新下载 更新后原来的WiFi密码都还在不用重新连接WiFi,桌面壁纸也是原来12系统上的 在Ipad的设置里将1 ...

  10. 并发编程之J.U.C的第一篇

    并发编程之J.U.C AQS 原理 ReentrantLock 原理 1. 非公平锁实现原理 2)可重入原理 3. 可打断原理 5) 条件变量实现原理 3. 读写锁 3.1 ReentrantRead ...