Excel的常用导出导入数据的实现


     说到Excel,那是叫个怕啊!一吧自己对Excel不熟悉,二吧大家都说Excel不好操作;心里上不知不觉就对它产生了畏惧。但是有句话说的好啊:你最怕的地方就是你最弱的地方。想要进步还是得想办法提高自己,就去搞自己最怕的!

其实说到怕,也并不是真的怕,而是对这方面不熟悉造成的;想要解决怕的问题,就得把它整明白了,下次在遇见就不怕不怕了;最近帮同学做了个Excel处理的小程序;涉及到了一下Excel的操作,特此给大家分享一下。

1. Excel导入到数据库的操作

 (1)、通过NPOI来实现。NPOI是个好东东,它能方便的让你对Excel的控制达到单元格级别;而且使用起来也比较方便,不需要依赖office的什么组件;基本上引用了官方提供的那几个dll就可以使用了。我在使用的过程中遇到了一个问题,NPOI提示缺少一个.dll,叫做:"ICSharpCode.SharpZipLib.dll",后来查了查资料,了解到Excel2007或2010的.xlsx格式的文件其实是压缩文件,NPOI在处理.xlsx文件的时候需要先解压缩,而解压缩就用到了ICSharpCode.SharpZipLib.dll,这是个比较常用的dll,可能系统由于某种原因造成了dll的丢失,然后从网上找了好久才找到合适的dll文件,有需要的童鞋可以点击"ICSharpCode.SharpZipLib.dll"下载我找的dll试试。

     NPOI的具体操作我就不再啰嗦了,大家可以点击"学习NPOI"去仔细研究;通过NPOI操作Excel是个不错的选择,在数据量不是特别大的时候可以考虑使用;因为NPOI在加载Excel的时候需要读取每个单元格的样式、格式等信息,所以不太适合大数据量的操作。

 (2)、使用SqlBulkCopy类。类描述:使您可以用其他源的数据有效批量加载 SQL Server 表。吊,微软的提供的类,想必很好用。通过程序测试了下,25W行的数量需要5秒左右;用法我大致说一下,不清楚的可以MSDN查查。

           思路:把Excel中的数据提取到内存DataTable中,然后通过SqlBulkCopy类写入到数据库,贴代码:

public static void InsertDBFromExcelData(string excelFile, string tableName, SqlBulkCopyColumnMapping[] mappings)
        {
            string mystring = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = '{0}';Extended Properties='Excel 12.0; HDR=Yes; IMEX=1'".With(excelFile);
            OleDbConnection cnnxls = new OleDbConnection(mystring);

            var allSheetNames = GetSheetNames(excelFile);
            foreach (string sheetName in allSheetNames)
            {
                OleDbDataAdapter myDa = new OleDbDataAdapter("select * from [{0}]".With(sheetName), cnnxls);
                DataTable dt = new DataTable();
                myDa.Fill(dt);
                if (dt.Rows.Count > 0)
                {
                    using (SqlBulkCopy copy = new SqlBulkCopy(DBConnectionStr))     //与目标服务器连接
                    {
                        copy.BulkCopyTimeout = 5000;
                        copy.DestinationTableName = tableName;                      //导入到数据库的表名
                        if (mappings != null)
                        {
                            foreach (var item in mappings)
                            {
                                copy.ColumnMappings.Add(item);
                            }
                        }
                        copy.WriteToServer(dt);
                    }
                }
            }
        }
View Code

 

2.从数据库导出到Excel

 (1)、使用NPOI写入,具体用法我就不说了;测试的时候,循环写入25W个单元格大致需要4~8秒,已经相当快了(未设置单元格的样式等信息)。

 (2)、使用利用驱动来实现。比如Sqlserver数据库,可以这么写sql语句:  SELECT * FROM INTO [SheetName] TABLE in "" [ODBC;Driver=SQL SERVER;Data Source=.;DataBase=sa;Integrated security=true] ;然后这样写执行语句:

 string cnnString = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = 'D:\Files\test.xlsx';Extended Properties='Excel 12.0; HDR=NO; IMEX=0'";

 using (OleDbConnection cnnxls = new OleDbConnection(cnnString)) { cnnxls.Open(); OleDbCommand cmd = new OleDbCommand(sql, cnnxls); cmd.ExecuteNonQuery(); cnnxls.Close(); } 

看sql语句和执行的链接串的写法,大致也能猜出个什么意思。 Provider = Microsoft.Ace.OleDb.12.0  表示驱动程序是OleDb.12.0,Extended Properties='Excel 12.0; HDR=yes; IMEX=0' 表示的链接的扩展属性:Excel12.0表示的是链接的Excel版本,如果是电脑中只安装了Excel2003,则需修改为:Excel4.0;如果安装了Excel2007或2010则不用修改了,一样能处理.xls和.xlsx文件;"HDR=yes;"是说第一行是列名而不是数据,"HDR=no;"正好与前面的相反,把第一行也当成数据处理,这样导入到数据库表中的数据就会多出第一行的标题数据(如果你的Excel文件的第一行是标题);另外说明一下IMEX的意义,不写了,抄了点儿,挺详细的:

      当 IMEX=0 时为“汇出模式”,这个模式开启的 Excel 档案只能用来做“写入”用途。
  当 IMEX=1 时为“汇入模式”,这个模式开启的 Excel 档案只能用来做“读取”用途。
  当 IMEX=2 时为“连結模式”,这个模式开启的 Excel 档案可同时支援“读取”与“写入”用途。
     意义如下:
     0 ---输出模式;
     1---输入模式;
     2----链接模式(完全更新能力)
使用该方法可以快速的把Excel中的数据导入到数据库中,我测试的是10列,25W行数据导入到Excel的时间只需要3秒即可;但是这个方法也有缺点,他不能对Excel的数据进行再加工;例如Excel数据格式的转变,或者计算列等需要深加工的数据就没什么办法了;比如Excel中有一列是数字,但是当导入数据库时可能就变成了科学表示法的文本了(10+E2),这样的问题要么改Excel的单元格格式,要么在取的时候转换一下。

 

另外遇到了一个奇怪的问题,就是去Excel所有工作簿的名字的问题,有时候明明一个工作簿,但是通过普通的方法总是能取到2个名字,比如:有一个工作簿:mysheet1;但是查询到会存在两个:mysheet1,mysheet1$,但其实不存在第二个工作簿。没有深究,写了方法干掉了第二个:

public static string[] GetSheetNames(string file)
        {
            List<string> names = new List<string>();
            string mystring = "Provider = Microsoft.Ace.OleDb.12.0 ; Data Source = '{0}';Extended Properties='Excel 12.0;'".With(file);
            using (OleDbConnection oleConn = new OleDbConnection(mystring))
            {
                oleConn.Open();
                DataTable dtOle = oleConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
                DataTableReader dtReader = new DataTableReader(dtOle);

                List<SheetName> allSheetNames = new List<SheetName>();
                foreach (DataRow row in dtOle.Rows)
                {
                    allSheetNames.Add(new SheetName(row));
                }
                allSheetNames = allSheetNames.Distinct(new SheetNameEquatilyCompare()).ToList();

                allSheetNames.ForEach(f =>
                {
                    names.Add(f.Name);
                });
                dtOle = null;
                oleConn.Close();
            }

            return names.Distinct().ToArray();
        }

//工作簿名称自定义比较器
class SheetNameEquatilyCompare : IEqualityComparer<SheetName>
    {

        public bool Equals(SheetName x, SheetName y)
        {
            return x.ModifyTime == y.ModifyTime && x.CreateTime == y.CreateTime && x.Name.TrimEnd('$') == y.Name.TrimEnd('$');
        }

        public int GetHashCode(SheetName obj)
        {
            return 10;
        }
    }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM