将数据从excel导入到多个表中

我正在构build一个离线的C#应用​​程序,它将从电子表格中导入数据并将它们存储在我创build的SQL数据库中(项目内部)。 通过一些研究,我已经能够使用一些可以导入一个静态表的代码到一个与工作表中的列完全相同的数据库中

我想要做的是有特定的列到正确的名字的基础上,这样我的数据库devise正确,而不是只有一个巨大的表来存储的一切。

以下是我用来将一些静态字段导入到一个表中的代码,我希望能够将导入的数据分成多个。

做这个的最好方式是什么?

public partial class Form1 : Form { string strConnection = ConfigurationManager.ConnectionStrings ["Test3.Properties.Settings.Test3ConnectionString"].ConnectionString; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //Create connection string to Excel work book string excelConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Test.xls; Extended Properties=""Excel 8.0;HDR=YES;"""; //Create Connection to Excel work book OleDbConnection excelConnection = new OleDbConnection(excelConnectionString); //Create OleDbCommand to fetch data from Excel OleDbCommand cmd = new OleDbCommand ("Select [Failure_ID], [Failure_Name], [Failure_Date], [File_Name], [Report_Name], [Report_Description], [Error] from [Failures$]", excelConnection); excelConnection.Open(); OleDbDataReader dReader; dReader = cmd.ExecuteReader(); SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection); sqlBulk.DestinationTableName = "Failures"; sqlBulk.WriteToServer(dReader); } 

如果你正在寻找更多的代码相关的答案,你可以使用下面的代码来修改你的代码,以处理困难的列名称/不同的表格:

  private void button1_Click(object sender, EventArgs e) { //Create connection string to Excel work book string excelConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Test.xls; Extended Properties=""Excel 8.0;HDR=YES;"""; //Create Connection to Excel work book OleDbConnection excelConnection = new OleDbConnection(excelConnectionString); //Create OleDbCommand to fetch data from Excel OleDbCommand cmd = new OleDbCommand ("Select [Failure_ID], [Failure_Name], [Failure_Date], [File_Name], [Report_Name], [Report_Description], [Error] from [Failures$]", excelConnection); excelConnection.Open(); DataTable dataTable = new DataTable(); dataTable.Columns.Add("Id", typeof(System.Int32)); dataTable.Columns.Add("Name", typeof(System.String)); // TODO: Complete other table columns using(OleDbDataReader dReader = cmd.ExecuteReader()) { DataRow dataRow = dataTable.NewRow(); dataRow["Id"] = dReader.GetInt32(0); dataRow["Name"] = dReader.GetString(1); // TODO: Complete other table columns dataTable.Rows.Add(dataRow); } SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection); sqlBulk.DestinationTableName = "Failures"; sqlBulk.WriteToServer(dataTable); } 

现在,您可以控制列的名称以及将数据导入到哪个表中。 SqlBulkCopy适合插入大量的数据。 如果你只有less量的行,你最好创build一个标准的数据访问层来插入你的logging。

您可以尝试一个ETL(提取 – 转换 – 加载)体系结构:

提取:一个类将打开文件,并获取所有数据块,你知道如何处理(通常你从文件中取一行,并将其数据parsing成一个POCO对象,其中包含保存相关数据的字段),并将这些数据成为其他工作stream程可以从中取得的队列。 在这种情况下,你可能首先要做的事情是让Excel打开文件并将其重新保存为CSV文件,这样你就可以在进程中重新打开文件,并有效地将其切断。 你也可以读取列名并build立一个“映射字典”; 这个列被命名,所以它转到这个数据对象的这个属性。 这个过程应该尽可能快地发生,唯一的原因就是失败的原因是行的格式与给定文件结构的内容不匹配。

转换:一旦文件的内容被提取到基本行的实例中,执行任何validation,计算或其他业务规则,以将文件中的行转换为符合您的域模型的一组域对象。 这个过程可以像你所需要的那样复杂,但是它也应该像你所要求的所有业务规则一样简单直接。

加载:现在你已经在自己的域对象中有一个对象图,你可以使用你要调用的持久性框架来处理任何其他方式创build的域对象。 这可能是基本的ADO,像NHibernate或MSEF这样的ORM,或者对象知道如何坚持自己的Active Record模式。 这不是批量加载,但它可以节省你不得不实现一个完全不同的持久性模型,只是为了获得基于文件的数据到数据库中。

ETL工作stream程可以帮助您将重复性任务分解为简单的工作单元,并从那里可以识别花费大量时间并考虑并行stream程的任务。

或者,也可以在调用批量插入例程来处理数据之前,通过检测要使用的列并将其排列成与批量input规范相匹配的格式来取出该文件并按照其格式。 这个文件处理程序可以做任何你想做的事情,包括将数据分成几个文件。 然而,这是整个文件一次工作的一个大的过程,并且优化或并行处理的机会有限。 然而,如果你的加载机制很慢,或者你有很多简单易懂的数据,它甚至可能比精心devise的ETL更快。

在任何情况下,我都尽可能避免使用Office格式和纯文本(或XML)格式,而且我会毫不犹豫地避免必须在服务器上安装Office。 如果有任何方式,您可以要求文件在加载之前像CSV一样容易parsing的格式,那么更好。 在服务器上进行Office安装通常是非常糟糕的事情,而在服务器应用程序中进行的OLE操作并不会更好。 该应用程序将是非常脆弱的,任何Office想告诉你将导致应用程序挂起,直到login到服务器,并清除对话框。

如果您只对文本感兴趣(而不是格式化等),或者您可以将excel文件另存为CSV文件,然后parsingCSV文件,这很简单。

根据程序的生命周期,我会推荐两个选项之一。

  1. 如果程序是短期使用,或者通常是一个“扔掉”的项目,我会推荐一系列的例程,使用标准的SQLparsing和input数据到另一组表中,根据需要进行一些string处理。

  2. 如果该计划将持续更长的时间和/或在日常的基础上发现更多的使用,我会build议实施类似于@KeithS推荐的解决scheme。 通过一系列明确的数据处理步骤,可以获得很大的灵活性。 更具体地说,.NETentity framework可能非常适合。 作为一个奖励,如果你还没有精通这个领域,你可能会发现你在使用ORM(例如EF)的第一个阶段处理边界(xls – > sql – >等)数据时学到了很多东西。