紅色部分為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。下載地址如下,下載完成后安裝即可直接使用。
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