对于从sqlserver中导入、导出excel,虽然sqlserver已经给了较为简单的方式,通过交互式的对话框形式实现,但是有时这种方式存在的很多问题,比方说导入、导出数据不全。而且,对于一个项目而言,我们都不希望功能的实现离开该软件程序。因此,我们便想着用程序来实现sqlserver的导入导出。
一、从sqlserver中导出excel表
我们将查出的数据首先要保存到数据表中DataTable,这里我就不具体说明如何从查出结果,存放到DataTable中了,相信网上有很多实现的例子。
接下拉我们做的就是先找到存放这个文件的路径,代码如下:
这段代码,意思是看是否存在文件夹,如果存在,则查看是否存在文件,如果不存在文件夹或者文件,都将进行创建。
private void exportout_Click(object sender, EventArgs e)
{
Helper helper = new Helper();//这是我自己写的类,具体你可以不用看,只知道它是用来获取Debug路径的就可以了。具体代码看我上一篇文章:http://blog.csdn.net/ztzi321/article/details/44077563
Global.filepath = helper.GetAssemblyFileDirectory()+@"\Excel";
if (!Directory.Exists(Global.filepath))
{
Directory.CreateDirectory(Global.filepath);
}
saveFile=Global.filepath +=@"\党员基本信息表.xlsx";
if (!File.Exists(saveFile))
{
File.Create(saveFile);
}
Global.ExportExcel(partyMemberTable, Global.filepath);//调用导出excel函数,partyMemberTable为存储查询结果的DataTable。Global是我定义的一个全局类,里面有全局变量和函数,这里我将实现导出excel函数也放在了里面。
}
导出excel函数具体实现如下:
public static void ExportExcel(System.Data.DataTable dt,String saveFile )
{
object objectMissing;
objectMissing = System.Reflection.Missing.Value;//将一个默认值返回个objectMissing
if (dt == null || dt.Rows.Count == 0) return;
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();//创建Excel应用程序。
if (xlApp == null)
{
return;
}
//System.Globalization.CultureInfo CurrentCI = System.Threading.Thread.CurrentThread.CurrentCulture;
//System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;//创建一个工作簿集合对象。
Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(objectMissing);//创建一个新的工作簿
Microsoft.Office.Interop.Excel.Worksheet worksheet = workbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;//创建一个工作表对象。
Microsoft.Office.Interop.Excel.Range range;//创建一个excel表格的范围对象。
long totalCount = dt.Rows.Count; //获取导出数据行数
long rowRead = 0;
float percent = 0;
此段代码为表格标题列内容
for (int i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[1, i + 1] = dt.Columns[i].ColumnName;//excel的行列是从1开始的
range = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, i + 1];
range.Interior.ColorIndex = 15; //15号字体
range.Font.Bold = true;//粗体
}
此段代码为将数据表中的内容导入到excel表中,因此是从第二行开始的
for (int r = 0; r < dt.Rows.Count; r++)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells[r + 2, i + 1] = dt.Rows[r][i].ToString();
}
rowRead++;
percent = ((float)(100 * rowRead)) / totalCount;
}
// xlApp.Visible = true;
try
{//因为在之前我们已经创建了excel表,但是之前那个还没有数据,因此需要保存。msdn上介绍了save的用法,“当第一次保存excel表示用SaveAs来进行保存文件,下边具体的参数含义,可以具体参照msdn介绍的WookBool.SaveAs()方法”
workbook.SaveAs(saveFile, objectMissing, objectMissing, objectMissing, objectMissing, objectMissing,
XlSaveAsAccessMode.xlShared, objectMissing, objectMissing, objectMissing, objectMissing, objectMissing);
}
catch(Exception ex)
{
MessageBox.Show("有错误:"+ex.ToString());
}
MessageBox.Show("保存成功!");
xlApp.Quit();//关闭程序。
//xlApp.
}
二、从Excel表中将数据导入到sqlserver中
首先,我们需要确定的是,excel表中的表列名应该和数据库中的表列名相一致。
这里我先讲解一下实现过程的原理:创建一个DataTable,首先将excel表与DataTable进行创建连接,将excel表中的数据保存到DataTable中,然后用sql语句进行循环的一行行插入到sqlserver中。
具体实现代码如下:
这里我创建了一个按钮,通过按钮的点击事件进行处理
private void exportin_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();//创建一个DataTable表,用于存储从excel表中读取的数据
OpenFileDialog open = new OpenFileDialog();//创建一个打开文件窗口类
if(open.ShowDialog()==DialogResult.OK)
{
string fileName = open.FileName;//获取选取的文件,这里你也可以用过滤方式,过滤一下文件类型。
bind(dt,fileName);//excel表中数据导入到DataTable中过程函数
}
}
将excel中的数据导入到DataTable中
private void bind(DataTable table,string fileName)
{
/*1.数据库引擎:microsoft.ace.oledb.12.0和Microsoft.Jet.OLEDB.4.0
*2.Extended Properties:扩展属性, Excel中8.0为07以上至03,Excel 12.0为07和10
*3.HDR=Yes,这代表第一行是标题,不做为数据使用 ,如果用HDR=NO,则表示第一行不是标题,做为数据来使用。系统默认的是YES\
*4.IMEX ( IMport EXport mode )设置
IMEX 有三种模式:
0 is Export mode
1 is Import mode
2 is Linked mode (full update capabilities)
我这里特别要说明的就是 IMEX 参数了,因为不同的模式代表著不同的读写行为:
当 IMEX=0 时为“汇出模式”,这个模式开启的 Excel 档案只能用来做“写入”用途。
当 IMEX=1 时为“汇入模式”,这个模式开启的 Excel 档案只能用来做“读取”用途。
当 IMEX=2 时为“连結模式”,这个模式开启的 Excel 档案可同时支援“读取”与“写入”用途。
意义如下:
0 ---输出模式;
1---输入模式;
2----链接模式(完全更新能力)
*/
string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + fileName + ";" +
"Extended Properties='Excel 12.0; HDR=Yes; IMEX=1'";
//String sheetName = "党员基本信息表";
String excelStr =String.Format("select * from [党员基本信息表$]");//这里是sheet表名
OleDbDataAdapter da = new OleDbDataAdapter( excelStr,strConn);
DataSet ds = new DataSet();//创建数据集,数据集这里你可以看作包含多个数据表
try
{
da.Fill(ds);//将excel表中的数据保存到DataTable中。
table = ds.Tables[0];
//this.dataGridView1.DataSource = dt;
}
catch (Exception err)
{
MessageBox.Show("操作失败!" + err.ToString());
}
foreach(DataRow dr in table.Rows)
{
insertToSql(dr);//此函数是将数据表table中的数据一行行的插入到sqlserver中。
}
}
将数据表中的数据插入到sqlserver中
private void insertToSql(DataRow dataRow )
{//1、Data Source:数据库引擎名,一般用(lcoal),如果设置了实例,则用.\实例名方式。
//2、Initial Catalog:数据库名字
//3、User ID:用户名
//4、Password:密码;其它的不做过多解释了,可以不用写
string connString = @"Data Source=.\SQLSERVER2008R2;Initial Catalog=organization;Persist Security Info=False;User ID=sa;Password=123;Min Pool Size=10;Max Pool Size=1000";
SqlConnection conn = new SqlConnection(connString);//创建连接
conn.Open();//打开连接
//数据库sql语句
String sqlstring = "use Organization insert into partyMembers(memberID,memberName,sex,cardID,birthDate,nation,nativePlace,politicalStatus,education,"
+ "partyDate,orgID,branchID,depID,duty,beginYear,endYear,editor,editTime,parentOrg,audit,auditTime,status,remark) "
+ "values('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}',"
+ "'{10}','{11}','{12}','{13}',{14},{15},'{16}','{17}','{18}','{19}',"
+ "'{20}','{21}','{22}')";
sqlstring = String.Format(sqlstring,
Convert.ToString(dataRow["memberID"]), Convert.ToString(dataRow["memberName"]),
Convert.ToString(dataRow["sex"]), Convert.ToString(dataRow["cardID"]),
Convert.ToDateTime(dataRow["birthDate"]).ToString("yyyy-MM-dd"),
Convert.ToString(dataRow["nation"]), Convert.ToString(dataRow["nativePlace"]),
Convert.ToString(dataRow["politicalStatus"]), Convert.ToString(dataRow["education"]),
Convert.ToDateTime(dataRow["partyDate"]).ToString("yyyy-MM-dd"),
Convert.ToString(dataRow["orgID"]), Convert.ToString(dataRow["branchID"]),
Convert.ToString(dataRow["depID"]), Convert.ToString(dataRow["duty"]),
Convert.ToString(dataRow["beginYear"]), Convert.ToString(dataRow["endYear"]),
Convert.ToString(dataRow["editor"]),
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
Convert.ToString(dataRow["parentOrg"]), Convert.ToString(dataRow["audit"]),
Convert.ToString(dataRow["auditTime"]), Convert.ToString(dataRow["status"]),
Convert.ToString(dataRow["remark"]));
SqlCommand command = new SqlCommand(sqlstring, conn);
command.ExecuteNonQuery();//执行sql语句
}
1、
这个问题我们第一眼上会认为是计算机本身安装的office有问题,其实问题并不在此,因为excel导入到sqlserver中程序对于64位支持性不好,所以我们将项目的CPU由ANY Cpu改为x86.如下图所示:
如果没有x86,需要先创建,点击“配置管理器”,具体界面如下:
这样此问题就解决了。
(续:随后发现这样修改也并不能实际解决问题,于是又参考了一下,右击项目-属性,然后将生成改为x86,发现之前为any cpu ,上边那种方式还是无法根本修改。)
如下图所示:
2、
外部表不是预期格式,此问题有以下几个:
1)、不要用程序生成的excel
2)、将excel保存为97-03版excel,格式为.xls(我个人理解是excel兼容性问题,97-03更加适合编程使用)
3、显示“连接登录失败”
查看连接字符串是否正确,可以从以下几方面查看:
1)、Data Source 中实例名是否正确
2)、数据库名是否正确
3)、数据库用户是否存在,若存在,密码是否正确
4、对于excel表中的多位数的格式设置:
例如身份者证号:18位,在excel表设置格式,应设置为text格式,如果设置成数值形式的话,它会将在数据库中以16进制表示形式表示。
至此,sqlserver与excel表的导入、导出完毕!!祝好运!!