导入数据
可以分两步: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 生成。”
解决办法:数据库主键没设置,要设置好,这样避免数据重复。
- 帮助文档 microsoft helo viewer
- c#开发环境及visual studio安装注意事项
- c#程序基本结构-基本语法
- Q1: public static void main(String[] args) 是什么意思
- Q2: c#命名空间+Main方法
- Q3:注释+命名规则+代码规则
- Q4: c#语句 system => console
- Q5: 数据类型 .net
- Q5: 常用名字、变量、运算符
- Q6: 对话窗输入-属性
- Q7: 递归
- Q8:决策分支、条件判断语句 if 语句
- Q9:数组
- Q10:字符串
- Q11:对象、类、访问权限、静态动态函数
- Q12:方法及参数——继承于类
- Q13:构造函数
- Q14:继承——base 关键字
- Q15:多态、虚方法、接口
- Q16:创建窗体应用、控件
- Q17:Ado数据访问、连接 sqlserver 数据库
- Q18: 读取数据command + DataRead( )、DataSet + DateAdapter
- Q19: Entity Framwork、entity 与 ADO.net的区别
- Q20: 对话框、文件、文件夹
- Q21: 导入excel数据、更新到 dbo 数据库中
- Q26: 获取 excel 中每个 sheet 的表名
- Q22: 两个窗体之间数据+方法传递
- Q23: 数学对象
- Q24: c#网站编写
- Q25: visual studio2017如何查看帮助
- Q27: c# dictionary 字典对象
- Q28: 数组与dataTable互相转化