热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Excel与数据库之间的那些事

说起Excel几乎是人人熟知的,一般人都会用他来记录一些数据,这种方式很方便他们的使用,他们可以很方便的对这些数据进行操作。可现在问题就来了,为了方便用户的这种需求,开发人员就必须把他们的数据变成自己

说起Excel几乎是人人熟知的,一般人都会用他来记录一些数据,这种方式很方便他们的使用,他们可以很方便的对这些数据进行操作。可现在问题就来了,为了方便用户的这种需求,开发人员就必须把他们的数据变成自己的程序代码可以操作的数据,并且将数据操作完成以后,还要生成客户需要的数据。那么在这个过程中就涉及到了,Excel表的数据与数据库表数据的交互问题。在这里我只针对SQL数据库来说明我对Excel数据的操作

  首先我对自己的思路做一个整体的概述:

      我在这里做一个公共实现方法:(具体代码是在放在一个类ImportExcel)
      实现思路:
        (1)将要导入的Excel表格上传到服务器路径的临时存储文件夹,并保存该路径
        (2)以该路径打开刚刚导入的Excel文件
        (3)检查该Excel文件是否为空值,若为空则提示用户“该文件为空,数据导入失败” 
        (4)并在此时关闭对Excel的打开连接,删除该Excel文件,返回到导入页面,显示错误信息! 
        (5)若检查该文件不为空,则获取该Excel文件的Sheet表名,注意这里的Sheet表的名称应该与你要导入的目标表的数据表名相同,若检查初该Excel文件中没有与目标数据表名相匹配的Sheet表名,则提示用户“该文件中不存在目标表名,请检查后再导入”重复(4) 
        (6)若判断该Sheet表名存在,则去获取Sql Server数据库中目标表的模式(Schema)同时也去获得Excel中该Sheet表的模式(Schema),以Sheet表的的模式参考,首先是检查Sheet表中的列名及其顺序数据库中表是不是对应的,(为了确保这里的数据导入成功,必须检查列的顺序是否对应,意即Sheet表中某字段名是第一列则他在数据库的表中也必须是第一列)
      (7)若检查字段顺序不对应,则提示用户“该Excel表中的列名顺序与与数据库不对应,请检查后再导入”,重复(4)
      (8)若列名顺序对应,但数据库表中还存在其他列名,但这些列名是与用户导入数据无关的,那么此时就必须去遍历这些列,并为这些列附上相应的值,当然这些值必须保证数据库数据的正确性,那么关于这些值,可以先检查其对应字段的类型,编写一些对应数据类型的固定赋值模式,然后对该字段附上固定的值。(这里实际是以用户为核心来考虑的,先保证数据能以最大可能成功导入到数据库,但要注意,附上了固定的值以后,你还得再单独用语句将其修改为正确的值)
      (9)当这些操作均完成时,提示用户“数据导入成功”重复(4)

  这是我在做Excel导入到数据库时,逐步完善总结出来的一些经验,某些地方可能也不免有些不完善,但大体上的功能都能实现,现在拿出来和大家交流交流,若大家有更好的方法我也乐于学习下。

        关于公共类的方法接口:(这是放到公共类的模块,这样在多个页面只需调用函数即可)

   

  1 public class ImportExcel
2 {
3 public string TransferData(string excelFile, string sheetName, string connectionString)
4 {
5 DataSet ds = new DataSet();
6 try
7 {
8 //建立Excel连接
9 string strCOnn= "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + excelFile + ";" + "Extended Properties=Excel 8.0;";
10 OleDbConnection cOnn= new OleDbConnection(strConn);
11 conn.Open();
12
13
14 //获取Excel的Sheet表名
15 DataTable dt = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
16 String[] excelSheets = new String[dt.Rows.Count];
17 int k = 0;
18 foreach (DataRow row in dt.Rows)
19 {
20 excelSheets[k] = row["TABLE_NAME"].ToString();
21 k++;
22 }
23
24 #region
25 //获取Excel的表的列名
26 OleDbDataAdapter oleCommand = null;
27 string oleExcel = "";
28 int n = 0;
29 oleExcel = string.Format("select * from [{0}$]", sheetName);
30 oleCommand = new OleDbDataAdapter(oleExcel, strConn);
31 DataTable oleschemaTable = null;
32 OleDbCommand olecmd = conn.CreateCommand();
33 olecmd.CommandText = oleExcel;
34 olecmd.ExecuteNonQuery();
35 OleDbDataReader ole_rdr = olecmd.ExecuteReader(System.Data.CommandBehavior.SchemaOnly);
36 oleschemaTable = ole_rdr.GetSchemaTable();
37 String[] exl_TableCloumn = new String[oleschemaTable.Rows.Count];
38 foreach (DataRow row in oleschemaTable.Rows)
39 {
40 exl_TableCloumn[n] = row["ColumnName"].ToString();
41 n++;
42 }
43 #endregion
44
45 #region
46 //读取Sql数据库中表的列名(设计模式)
47 System.Data.SqlClient.SqlConnection sqlcon = new System.Data.SqlClient.SqlConnection(connectionString);
48 sqlcon.Open();
49 int m = 0;
50 string sql = "select * from " + sheetName;
51 DataTable schemaTable = null;
52 SqlCommand cmd = sqlcon.CreateCommand();
53 cmd.CommandText = sql;
54 cmd.ExecuteNonQuery();
55 SqlDataReader rdr = cmd.ExecuteReader(System.Data.CommandBehavior.SchemaOnly);
56 schemaTable = rdr.GetSchemaTable();
57 String[] sqlTableCloumnName = new String[schemaTable.Rows.Count];
58 String[] sqlTableCloumnSize = new String[schemaTable.Rows.Count];
59 String[] sqlTableCloumnType = new String[schemaTable.Rows.Count];
60 foreach (DataRow row in schemaTable.Rows)
61 {
62 sqlTableCloumnName[m] = row["ColumnName"].ToString();//列名
63 sqlTableCloumnSize[m] = row["ColumnSize"].ToString();//
64 sqlTableCloumnType[m] = row["DataType"].ToString();//字段类型
65 m++;
66 }
67 sqlcon.Close();
68 #endregion
69
70 #region
71 //比较两数据表的中列名及其顺序是否对应
72 string tableInfo = "";
73 int i, j, p;
74 //读取数据库字段的正确顺序
75 for (i = 0; i 76 {
77 tableInfo = tableInfo + sqlTableCloumnName[i].ToString() + ",";
78
79 }
80 j = sqlTableCloumnName.Length - exl_TableCloumn.Length;
81 //检查Excel表中的字段顺序是否与数据库中匹配
82 for (i = 0; i 83 {
84 if (exl_TableCloumn[i].ToString() == sqlTableCloumnName[i].ToString())
85 {
86 continue;
87 }
88 else
89 {
90 conn.Close();
91 return "出错了!您提供的数据表的列名或列名的顺序有误!正确信息为:" + tableInfo;
92 }
93 }
94 #endregion
95
96 #region
97 //将Excel表中数据填充到ds中
98 OleDbDataAdapter myCommand = null;
99 string strExcel = "";
100 strExcel = string.Format("select * from [{0}$]", sheetName);
101 myCommand = new OleDbDataAdapter(strExcel, strConn);
102 myCommand.Fill(ds, sheetName);
103 #endregion
104
105
106 #region
107 //在DataSet中动态增加列并对其赋值
108 int a;
109 for (p = 0; p 110 {
111 a = 0;
112 ds.Tables[0].Columns.Add(sqlTableCloumnName[i].ToString(), Type.GetType(sqlTableCloumnType[i].ToString()));
113 if (sqlTableCloumnType[i].ToString() == "System.string")
114 {
115 foreach (DataRow row in ds.Tables[0].Rows)
116 {
117 //临时修改,请注意导入后用代码按要求修改
118 row[sqlTableCloumnName[i].ToString()] = "需要修改列";
119 }
120 }
121 else
122 {
123 foreach (DataRow row in ds.Tables[0].Rows)
124 {
125 row[sqlTableCloumnName[i].ToString()] = a.ToString();
126 a++;
127 }
128 }
129 }
130 #endregion
131
132
133 #region
134 //判断用户提交的是否是空表
135 if (ds.Tables[0].Rows.Count == 0)
136 {
137 ds.Clear();
138 conn.Close();
139 string message = "你提交的数据表为空表,请检查后再确认导入!";
140 return message;
141 }
142 #endregion
143
144
145 //关闭打开的Excel文件
146 conn.Close();
147
148
149 //如果目标表不存在则创建
150 string strSql = string.Format("if object_id('{0}') is null create table {0}(", sheetName);
151 foreach (System.Data.DataColumn c in ds.Tables[0].Columns)
152 {
153 strSql += string.Format("[{0}] varchar(255),", c.ColumnName);
154 }
155 strSql = strSql.Trim(',') + ")";
156
157 using (System.Data.SqlClient.SqlConnection sqlcOnn= new System.Data.SqlClient.SqlConnection(connectionString))
158 {
159 sqlconn.Open();
160 System.Data.SqlClient.SqlCommand command = sqlconn.CreateCommand();
161 command.CommandText = strSql;
162 command.ExecuteNonQuery();
163 sqlconn.Close();
164 }
165
166
167 //用bcp导入数据
168 using (System.Data.SqlClient.SqlBulkCopy bcp = new System.Data.SqlClient.SqlBulkCopy(connectionString))
169 {
170
171 //bcp.SqlRowsCopied += new System.Data.SqlClient.SqlRowsCopiedEventHandler(OnSqlRowsCopied);
172 bcp.BatchSize = 100;//每次传输的行数
173 bcp.NotifyAfter = 100;//进度提示的行数
174 bcp.DestinatiOnTableName= sheetName;//目标表
175 bcp.WriteToServer(ds.Tables[0]);
176 }
177
178 return "数据导入成功!";
179 }
180 catch
181 {
182 return "数据导入失败!";
183 }
184 }
185
186 }


  用户页面.cs代码如下:

 public void ButtonImport_Click(object sender, EventArgs e)
{
//判断是否选择了上传文件
if (FileUpload.HasFile == false)
{
LblJudgeMseeage.Visible = true;
this.LblJudgeMseeage.Text = "请选择你要导入的Excel文件!";
return;
}
//判断上传的文件是否为Excel文件
string ext_name = Path.GetExtension(FileUpload.FileName).ToString().ToLower();
if (ext_name != ".xls")
{
LblJudgeMseeage.Visible = true;
LblJudgeMseeage.Text = "你选择的文件不是Excel文件!请重新选择!";
return;
}
else
{
string file_name = FileUpload.FileName;//获取上传文件名
//TODO:此处要添加你的Excel文件的存储路径
string file_fullname = Server.MapPath("你的Excel文件的存储路径" + file_name);//含路径全名
FileUpload.PostedFile.SaveAs(file_fullname);//保存文件

//获取连接字
string cOnnStr= ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
//调用公共导入函数
Common.ImportExcel com = new ImportExcel();
string Msg = com.TransferData(file_fullname, "Users", connStr);

LblMessage.Visible = true;
LblMessage.Text = Msg;

//数据导入完成后删除该Excel工作表
File.Delete(file_fullname);



}

}


到此为止,这个Excel文件导入到Sql Server数据库的模块就已经搭建起来了,在这里和大家交流一下编写这个模块的心得体会:

          最初在做这个的时候,只是为了把最基本的功能实现,能把数据导入到数据库就行了。可是后来,随着功能一步一步的实现,并且结合自己在测试中的用户体验,我慢慢的觉得,作为一个开发人员,永远都不能只按自己的思路去思考问题。自己做出来的功能模块,对他的操作和使用自己当然是最清楚的,但是你却不能要求客户一定要有和你一样的想法,你应该做的是尽量去满足客户的需求。就以这个导入数据为例,最初在设计导入时,要求客户提供的数据必须和数据表列名字段都完全吻合才可以,不错既然要实现导入就必须得保证数据的完整性,但是那样以来的话,也就意味着用户在导入数据前要在Excel文件中添加一些与他毫不相关的数据。虽然那些数据也是那张数据表中必须的,但对于用户来说根本就毫无意义,而且还会增加用户的负担,所以此时这些工作就自然也是我们所需要考虑的,那么这一实现过程就必须要求开发人员去预料更多的突发情况和可能性,并从各方面去为这些可能性提供解决办法,这样才能使程序功能更加的健壮可靠,才能让用户得到更加人性化的体验!谨以此愚见和大家共勉,若大家有更好的想法和做法,乐意与大家交流共享!

推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
author-avatar
三哥是二姐的三哥
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有