ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
导入数据 可以分两步:1、从 excel 导入数据到 datagridview 控件中,2、从 datagridview 控件导入数据库 # 1、打开 excel 文件并显示在dataGridView控件中 excel 导入失败时: ``` System.InvalidOperationException:“未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序。” ``` 此时下载插件安装,方法如下。 https://blog.csdn.net/stableboy/article/details/80405144 http://www.microsoft.com/downloads/details.aspx?FamilyID=c06b8369-60dd-4b64-a44b-84b371ede16d&displayLang=zh-cn 如果安装后还是提示“未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”,原因是用 64位的系统要启用 32位的程序,就会出错。则可以换一种方式启用: 在visual 的项目属性设置中,将平台目标设置为 x64 [https://blog.csdn.net/yyzzhc999/article/details/79367114](https://blog.csdn.net/yyzzhc999/article/details/79367114) ![](https://img.kancloud.cn/5f/45/5f458f16ca68569847a02c6d11cac1cf_327x506.png) ![](https://tva1.sinaimg.cn/large/006y8mN6gy1g78krprfx2j30k10as0ty.jpg) 或者调用 C:\Program Files (x86)\Microsoft SQL Server\100\DTS\Binn\DTExec.exe来执行package。 ![](https://img.kancloud.cn/3d/92/3d924fbdb37e1e6354a83640996204f3_835x398.png) 完整代码如下: ``` public DataSet getData()//获取数据,这部分单独写出来,然后在后续其他地方直接用 { //1、打开文件 OpenFileDialog fd = new OpenFileDialog(); fd.ShowDialog(); fd.Filter = "Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls"; // filter过滤器,只允许选excel文件 var path = fd.FileName;//获取文件名 string filesuffix = System.IO.Path.GetExtension(path);//获取文件扩展名 if (string.IsNullOrEmpty(filesuffix)) { return null; } //2、生成dataset临时表格 using (DataSet ds = new DataSet()) { //判断excel是.xlsx还是.xls,两个版本的excel处理不一样 string connString = ""; if(filesuffix == ".xls") { connString = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; } else { connString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; } //读取文件 string sql_select = "select * from [sheet1$]"; using (OleDbConnection conn = new OleDbConnection(connString)) using (OleDbDataAdapter da = new OleDbDataAdapter(sql_select, conn)) // 这两句using之间没有符号,不然会错 { conn.Open(); da.Fill(ds, "from_excel"); } if(ds == null || ds.Tables.Count <=0) { return null; } else { return ds; } } } private void btn_打开_Click(object sender, EventArgs e) { dataGridView1.DataSource = null; System.Data.DataTable dt = getData().Tables["from_excel"]; dataGridView1.DataSource = dt; } ``` # 2、datagridview更新到数据库 https://blog.csdn.net/xiongyongting/article/details/54170159 https://blog.csdn.net/foreverling/article/details/37376675 https://www.cnblogs.com/kongxiaoshuang/p/6062368.html # 3、第二步中用数组插入到 c# 的dataGridView 控件中 https://zhidao.baidu.com/question/42361870.html ### 关键是设置连接字符串 可以理解为 excel 也是 access 数据库的一种,所以要提供的是 provider,以及 DataSource ![](https://box.kancloud.cn/e8336f6e20762bef9d928e5a20381728_818x439.png) ``` private void button1\_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "表格(\*.xls)|\*.xls"; string strPath; if (ofd.ShowDialog()== DialogResult.OK ; { try { strPath = ofd.FileName; // 这一行要在打开以后才有,所以不能写在“if (ofd.ShowDialog()== DialogResult.OK )”前面 string strCon = "provider = microsoft.jet.oledb.4.0; data source = " + strPath + "; extended properties = excel 8.0"; OleDbConnection oleconn = new OleDbConnection(strCon); string strsql = "select \* from \[Sheet2$\]"; OleDbDataAdapter da = new OleDbDataAdapter(strsql ,strCon); DataSet ds = new DataSet(); da.Fill(ds, "new\_table3"); dataGridView1.DataSource = ds.Tables\["new\_table3"\]; } catch(Exception ex) { MessageBox.Show(ex.ToString()); } } } ``` # 4、如何真正把 excel 数据更新到数据库中 参考:项目管理台账.csv-登录窗口 [https://www.cnblogs.com/dylanblog/p/4284016.html](https://www.cnblogs.com/dylanblog/p/4284016.html) [https://www.cnblogs.com/yechangzhong-826217795/p/11077125.html](https://www.cnblogs.com/yechangzhong-826217795/p/11077125.html) 思路: 1. 导入 excel 表格,形成临时表 dataTable dt。 2. 从 dt 导入 dbo 中, 不要一条条复制数据,直接批量从 dt 到 dbo!! 以下是错误示范: ### 方法 1:sqlAdapter 方法 先写下面这些 ![](https://img.kancloud.cn/32/27/3227c5303d5cb87eff7d46d872bcef72_777x467.png) 然后再在必要的地方写一个循环 ![](https://img.kancloud.cn/32/d8/32d8fc89643276d6c65a01e93a5c6f9f_381x108.png) 但有个不好,每次插入一行,都必须打开一次 sql,6000行数据直接卡死。 ### 方法 2: 用sqlCommand.ExecuteNonQuery()方法 cmd.ExecuteNonQuery() 也卡死 ### 方法 3:用sqlBulkCopy() [https://www.cnblogs.com/zhaoshujie/p/9691010.html](https://www.cnblogs.com/zhaoshujie/p/9691010.html) 下面这个比较短: [https://www.cnblogs.com/fanqf/p/9026316.html](https://www.cnblogs.com/fanqf/p/9026316.html) ### 推荐方法 4:用 dt 表更新 1. excel 与dbo分别生成 dt1, dt2 ![](https://img.kancloud.cn/f9/cf/f9cffd72bb28949394e227fbc9ff8e33_686x493.png) 2. 清空 dt2里面的东西,将dt1 里面的东西复制到 dt2中 3. 将dt2更新回数据库。 详见 可以封装ddd(),返回值为 dataTable ![](https://img.kancloud.cn/a8/8a/a88a22a7ccc82b5d46b5f6d449b1fe35_815x234.png) 然后在 button 中调用 ddd()。 ![](https://img.kancloud.cn/30/b4/30b414eae1ab039e2b644ee5be5aca80_599x119.png) 但有个问题,这样生成以后,ddd 中的da,有可能在 button 就失效了,一旦失效,那么 da 与 dt 脱节,则 dt 就无法通过 da 再更新回数据库。 > **解决办法:修改 ddd,使得返回类型为 dataSet,而不是dt,这样即使脱离 ddd,ds 也可以继续有效,那么 button 中的 dt 还是可以与数据库有联系的,能继续用** ![](https://img.kancloud.cn/a4/31/a4311d89b6a258753cc7ed6e4224999d_900x633.png) 但也要考虑功能性的问题,如果功能集中,那么就不利于调用。 ## 更新遇到问题: dt 无法更新到 sql 中:如果按下文写的,那么 da 还是原来的 da,并不是更新以后的。所以这三条语句必须合起来写。 ![](https://tva1.sinaimg.cn/large/006y8mN6gy1g8ckm2k1uyj30lw09vgnd.jpg) 但不能重复写两个 da,怎么办?解决办法:前面的用sqlcommand连接。 [https://www.cnblogs.com/MR-Lee/articles/2312062.html](https://www.cnblogs.com/MR-Lee/articles/2312062.html) ![](https://tva1.sinaimg.cn/large/006y8mN6gy1g8ckk9crdyj30oi0ccmyw.jpg) > 详见 连接测试.cs - 导入 excel,或 项目管理台账.cs-公共 ``` //导入dbo数据 SqlConnection sqlconn = new SqlConnection("server = "); string pagename = this.tabControl1.SelectedTab.Text; SqlCommand sqlcomm = new SqlCommand("select \* from dbo.阶段评估", sqlconn); sqlconn.Open(); SqlDataReader sqlrd = sqlcomm.ExecuteReader(); DataTable dt2 = new DataTable(); dt2.Load(sqlrd); //修改dt中的数据 for (int i = 0; i < dt2.Rows.Count;i++) { DataRow dr2 = dt2.Rows\[i\]; if (Convert.ToString( dr2\["项目编号"\]) == "1533023") { dr2.Delete(); } } //将修改后的dt写回sql中。这三行一定要写一起,如果把da写到前面第一步,则update就毫无意义,因为识别的还是原来没修改之前的da SqlDataAdapter da2 = new SqlDataAdapter(sqlcomm); SqlCommandBuilder sqlcmdB = new SqlCommandBuilder(da2); da2.Update(dt2); MessageBox.Show("更新成功"); ``` ## 问题 System.InvalidOperationException:“对于不返回任何键列信息的 SelectCommand,不支持 UpdateCommand 的动态 SQL 生成。” 解决办法:数据库主键没设置,要设置好,这样避免数据重复。