C#导入Excel重写

最近做项目有个页面需要导入excel然后更新数据库得数据,导入导出excel我是从来都不记德,其实也没什么好记德东西(一般都是用的时候在 excel中使用录制宏,嘿嘿),导入很快就写完了,测试没有问题,但拿来真实数据后就出现问题了。(文/小笨蛋:Lollipop

真实的数据如下图:



    网上导入excel的文章多如牛毛,使用OLEDB查询语句都是select * from [Sheet1$] 这样,但是一个真实的数据表是不会为你写好名称的,并且excel的工作簿的数量也是不却定的,这个在程序中导入当然是有问题的了。

    后来我想到了可以在导入excel的时候检索excel的架构信息,可想而之excel的架构信息里面一定会包含工作簿的数量,工作簿的名称,工作簿的创建日期等等。

  最终检索出来的结果如下图:



  excel工作簿的名称:



更改后的完整代码如下:
  1. #region 批量修改MSC ID
  2.         void btnBatchMscIdClick(object sender, RoutedEventArgs e)
  3.         {
  4.             try
  5.             {

  6.                 var ofd = new OpenFileDialog()
  7.                 {
  8.                     Filter = "Microsoft Office Excel 工作簿(*.xls)|*.xls",
  9.                     Multiselect = false
  10.                 };
  11.                 if (ofd.ShowDialog() == DialogResult.Cancel) return;

  12.                 var ds = new DataSet("msgIds");

  13.                 var strConn = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;", ofd.FileName);
  14.                 using (var oledbConn = new OleDbConnection(strConn))
  15.                 {
  16.                     oledbConn.Open();

  17.                     var sheetName = oledbConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,  // 检索excel的架构信息
  18.                                                                     new[] { null, null, null, "Table" });
  19.                     var sheet = new string[sheetName.Rows.Count];
  20.                     for (int i = 0, j = sheetName.Rows.Count; i < j; i++)
  21.                     {
  22.                         sheet = sheetName.Rows["TABLE_NAME"].ToString();
  23.                     }
  24.                                                             //这里您可以用一个for来查询每一个工作簿,我这里只查询了第一个
  25.                     var adapter = new OleDbDataAdapter(string.Format("select * from [{0}]", sheet[0]), oledbConn);
  26.                     adapter.Fill(ds);
  27.                 }

  28.                 int success = 0, lose = 0;
  29.                 using (var client = new DataCmClient("DataTransfer_http"))
  30.                 {
  31.                     foreach (DataTable dt in ds.Tables)
  32.                     {
  33.                         foreach (DataRow dr in dt.Rows)
  34.                         {
  35.                             var msc_name = dr[0].ToString();
  36.                             var msg_addr = dr[1].ToString();
  37.                             var isSuccess = client.UpdateMscId(msc_name, msg_addr);
  38.                             if (isSuccess)
  39.                             {
  40.                                 success++;
  41.                             }
  42.                             else
  43.                             {
  44.                                 lose++;
  45.                             }
  46.                         }
  47.                     }
  48.                 }
  49.                 MessageBox.Show(string.Format("成功更新{0}条数据,失败{1}条数据", success, lose),
  50.                     "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Question);
  51.             }
  52.             catch
  53.             {
  54.                 MessageBox.Show("导入数据过程中出现异常,请您重新操作",
  55.                     "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  56.             }

  57.         }
  58.         #endregion
复制代码
顺便解释一下GetOleDbSchemaTable 这个方法

注意,在使用 SqlClient.SqlConnection 对象时没有与 GetOleDbSchemaTable 等价的方法。

    OLE DB .NET 数据提供程序使用 OleDbConnection 对象的 GetOleDbSchemaTable 方法展示架构信息。GetOleDbSchemaTable 返回填充了架构信息的 DataTable。

    GetOleDbSchemaTable 的第一个参数是架构参数,它是一个 OleDbSchemaGuid 类型的标识,指定了要返回的架构信息的类型(如表、列和主键)。第二个参数是一个限制对象数组,对 DataTable 架构中返回的行进行过滤(例如,您可以指定对表的名称、类型、所有者和/或架构的限制)。

OleDbSchemaGuid 成员

OleDbSchemaGuid 参数指定 GetOleDbSchemaTable 方法要返回的架构表的类型。
OleDbSchemaGuid 成员主要包括:
•        列
•        外键
•        索引
•        主键
•        表
•        视图

限制

    限制是一个过滤值对象数组,每个元素对应于结果 DataTable 中的一个 DataColumn。OleDbSchemaGuid 参数决定了相应的限制。例如,在指定表的 OleDbSchemaGuid 时,限制数组如下所示:
{TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE}

    在传递限制数组的值时,对于不包含值的数组元素使用 Visual C# .NET 的 null 关键字。例如,如果要检索表的架构,使用 OleDbSchemaGuid.Tables。但是,如果指定了表,也将返回别名、同义词、视图和其他相关对象。因此,如果您希望过滤掉除表以外的所有其他对象,请对 TABLE_TYPE 使用 TABLE 限制。可以对 TABLE_CATALOG、TABLE_SCHEMA 和 TABLE_NAME 使用 null,因为您不过滤这些对象: schemaTable = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
new Object[] {null, null, null, "TABLE"});

返回的数据表

    每个符合 OleDbSchemaGuid 类型和限制规则的对象都对应于 GetOleDbSchemaTable 方法返回的 DataTable 中的一行。每个限制列对应于 DataTable 的一列,后面是基于 OleDbSchemaGuid 字段的其他架构信息。

例如,当您使用以下代码时,返回的 DataTable 的每一行是一个数据库表:
  1. schemaTable = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
  2. new Object[] {null, null, null, "TABLE"});
复制代码
DataTable 中返回的每一列是限制列(TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、TABLE_TYPE),后面是 TABLE_G UID、DESCRIPTION、TABLE_PROPID、DATE_CREATED 和 DATE_MODIFIED 的其他架构列。

    若要获得列名称的列表(即字段描述符,如 TABLE_CATALOG、TABLE_SCHEMA 和 TABLE_NAME),您可以使用列的位置顺序。注意 Columns 数组的元素下标是从 0 开始的:
  1. for (int i = 0; i < schemaTable.Columns.Count; i++) {
  2. Console.WriteLine(schemaTable.Columns.ToString());
  3. }
复制代码
若要获得每一列的值(即实际的表名称,如 Categories、Customers 和 Employees),您可以使用该行的 ItemArray 的位置顺序。注意 ItemArray 数组的元素下标是从 0 开始的:
  1. for (int i = 0; i < schemaTable.Rows.Count; i++) {
  2. Console.WriteLine(schemaTable.Rows.ItemArray[2].ToString());
  3. }
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值