红色部分为2013.1.19日修改的内容。
最近做项目,项目经理让我把一个600多行的Excel文件录入数据库。本来不是什么难事,因为很多数据库管理工具都提供Excel表格导入功能,像Navicat for MySQL,Sql Server Management等都自带导入Excel表格功能。但接过Excel文件打开一看傻眼了,这个Excel文件里面的数据格式类似tree,每个根节点下面好多子节点,额,表达能力不好,我还是直接上图给大家看吧。
先拆分了一下单元格,结果留下了无数的空白单元格需要我手动填满,不是拖一下鼠标就能解决的,坑爹啊!让我动手填满?没门,累死老子都不干这种缺心眼的事!作为一个程序猿,思考了一下决定写个C#桌面程序吧,写asp.net的话拿到别的电脑上用还得用IIS才行。
先放上做完之后的效果图:
需要完成的功能:
1、正常连接数据库(SqlServer,MySQL,Oracle)
2、能解析Excel文件(Excel2003及以下版本的.xls以及2007及以上版本的.xlsx)
3、Excel文件中空白单元格能自动填充。
4、可以从数据库中将数据导出为Excel文件。
大概说说编码的过程。
一、首先就是连接数据库。针对三种不同的数据库,连接方法也不相同。MySQL引用了外部组件MySql.Data.dll,版本6.5.4.0。下面是数据库连接字符串:
protected string ConString() { string CnnString = ""; switch (cbSelDB.SelectedIndex) { case 0://Sql Server数据库连接字符串 CnnString = "Provider=SQLOLEDB;server=" + txtHost.Text + ";database=" + txtDBname.Text + ";uid=" + txtUser.Text + ";pwd=" + txtPwd.Text; break; case 2://Oracle数据库连接字符串 CnnString = "Provider=OraOLEDB.Oracle;Data Source=" + txtDBname.Text + ";User id=" + txtUser.Text + ";Password=" + txtPwd.Text; break; case 1://MySQL数据库连接字符串 CnnString = "server=" + txtHost.Text + ";Database=" + txtDBname.Text + ";User Id=" + txtUser.Text + ";Password=" + txtPwd.Text; break; default: break; } return CnnString; }
二、解析.xls和.xlsx。C#中提供了Microsoft.Jet.OLEDB.4.0组件可以操作Excel2003及以下版本,但Excel2007及以上版本则不提供支持。没办法,上网搜,终于搜到了AccessDatabaseEngine提供的Microsoft.ACE.OLEDB.12.0组件,可以操作Excel2007。下载地址如下,下载完成后安装即可直接使用。
http://download.microsoft.com/download/7/0/3/703ffbcb-dc0c-4e19-b0da-1463960fdcdb/AccessDatabaseEngine.exe
3楼提出的问题确实存在,对代码进行了修改。
修改后依然存在一些小问题,这种方法,默认对于该列的前8条数据必须为混合型,该列才会作为混合型数据处理,否则只取前8条对于的数据类型。
解决方案:修改注册表,将默认值8修改为你需要的数值:
Jet 4.0: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel\TypeGuessRows
ACE 12.0: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Access Connectivity Engine\Engines\Excel\TypeGuessRows
private string CheckExcelVer()//Excel连接字符串 { string strConn = ""; if (txtPath.Text.EndsWith(".xlsx"))//判断当选择的文件后缀名是.xlsx时,调用Microsoft.ACE.OLEDB.12.0 { strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + txtPath.Text + ";Extended Properties=‘Excel 12.0;IMEX=1;'"; } else { strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + txtPath.Text + ";Extended Properties='Excel 8.0;IMEX=1;'"; } return strConn; }
三、读取Excel中分页并绑定至下拉菜单。
private void Excel_Changed(object sender, EventArgs e) { ArrayList al = new ArrayList(); string strConn = CheckExcelVer();//检查是.xlsx还是.xls文件 OleDbConnection conn = new OleDbConnection(strConn); conn.Open(); System.Data.DataTable sheetNames = conn.GetOleDbSchemaTable (System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" }); conn.Close(); comboBox1.DataSource = null; comboBox1.Items.Clear(); foreach (DataRow dr in sheetNames.Rows) { al.Add(dr[2]); comboBox1.Items.Add(dr[2].ToString()); } comboBox1.DataSource = comboBox1.Items; }
四、读取Excel分页中数据。
protected void ReadSheet() { string strConn = CheckExcelVer(); OleDbConnection cnnxls = new OleDbConnection(strConn); string sheet = comboBox1.SelectedValue.ToString(); OleDbDataAdapter myDa = new OleDbDataAdapter("select * from [" + sheet + "]", cnnxls);//sheet是下拉菜单中选中的分页 DataSet myDs = new DataSet(); myDa.Fill(myDs); string[] sqls=readExcel(myDs); }
五、构建写入数据库字符串。
protected string[] readExcel(DataSet myDs)//传过来的是包含Excel表格中数据的DateSet { string[] Sqls = new string[myDs.Tables[0].Rows.Count]; if (myDs.Tables[0].Rows.Count > 0) { string strSql = ""; string[,] t = new string[myDs.Tables[0].Rows.Count, myDs.Tables[0].Columns.Count]; string item = ""; for (int i = 0; i < myDs.Tables[0].Columns.Count; i++) { if (i > 0) { item += "," + myDs.Tables[0].Columns[i].ColumnName; } else { item += myDs.Tables[0].Columns[i].ColumnName; } } for (int i = 0; i < myDs.Tables[0].Rows.Count; i++) { strSql = "insert into " + txtTable.Text + " (" + item + ") values ('"; for (int h = 0; h < myDs.Tables[0].Columns.Count; h++) { t[i, h] = myDs.Tables[0].Rows[i].ItemArray[h].ToString(); if (radioButton1.Checked == true && comboBox2.SelectedIndex == 0)//选择了纵向填充。 { if (t[i, h] == "") { t[i, h] = t[i - 1, h]; } } if (radioButton1.Checked == true && comboBox2.SelectedIndex == 1)//选择了横向填充 { if (t[i, h] == "") { t[i, h] = t[i, h - 1]; } } if (h > 0) { strSql += "','" + t[i, h]; } else { strSql += t[i, h]; } } strSql += "')"; Sqls[i] = strSql; Step(i, myDs.Tables[0].Rows.Count); } } return Sqls; }
剩下的就是写入数据库了,就不赘述了。数据库导出Excel功能相信接触过的人都会做,很简单,不知道的百度一下。
最后附上成品,界面简单的设计了一下,写了个使用说明,希望对你有帮助!不知道院子里怎么传附件,我传到网盘里吧。
新生成的修复了一个小Bug,我改成了V2.1,已经重新传了。
源代码也已经共享咯,和软件一起放到了网盘里,需要的朋友自己下载看吧!喜欢的话请点一下推荐,你的支持才是我的动力!
http://dl.vmall.com/c0n9b3ljv4