C#使用oledb读取excel数据并以指定格式格式化并插入到SQL Server数据库中

networking和C#。 我需要编写一个程序来浏览和读取一个Excel,然后parsing它以指定的格式,最后插入到SQL Server数据库。

  1. 我已经使用oledb读取excel,并从excel创buildDataTable。 现在我有麻烦来parsing它在所需的格式。 这里是什么是Excelinput的图片链接,以及什么是预期的格式插入到数据库。 input和预期的输出格式

  2. 现在我正在用简单的数据在将来我需要做的大型Excel数据(3000列)parsing成250000条logging。 在性能方面也请给我build议。 现在我使用oledb是好的,还是我需要使用其他任何东西。

这里是我的示例代码C#代码文件

OleDbConnection Econ; SqlConnection con; string constr, Query, sqlconn; protected void Page_Load(object sender, EventArgs e) { } // excel connection private void ExcelConn(string FilePath) { constr = string.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0 Xml;HDR=YES;""", FilePath); Econ = new OleDbConnection(constr); } // sql connection private void connection() { sqlconn = ConfigurationManager.ConnectionStrings["SqlCom"].ConnectionString; con = new SqlConnection(sqlconn); } // read data from excel and creating a datatable private void ExcelToDataTable(string FilePath) { ExcelConn("C:\\Users\\username\\Desktop\\EmpEx.xlsx"); Query = string.Format("Select * FROM [Sheet1$]"); OleDbCommand Ecom = new OleDbCommand(Query, Econ); Econ.Open(); OleDbDataAdapter oda = new OleDbDataAdapter(Ecom); DataTable dtExcel = new DataTable(); Econ.Close(); oda.Fill(dtExcel); // DataTable parseTable = ParseDataTable(dtExcel); //connection(); // printing data table foreach (DataRow dataRow in dtExcel.Rows) { foreach (var item in dataRow.ItemArray) { Response.Write(item); } } Response.Write("<br> Colums: " + dtExcel.Columns.Count.ToString() + "<br>"); Response.Write("Rows: " + dtExcel.Rows.Count.ToString() + "<br>"); //print on screen foreach(DataRow row in dtExcel.Rows) { foreach(DataColumn col in dtExcel.Columns) { Label1.Text = Label1.Text + row[col].ToString() + "\t"; } } } // Method to make data table in specified format public DataTable ParseDataTable(DataTable dtExcel) { var dt = new DataTable("sourceData"); dt.Columns.Add(new DataColumn("id", typeof(String))); dt.Columns.Add(new DataColumn("name", typeof(String))); dt.Columns.Add(new DataColumn("variable", typeof(String))); dt.Columns.Add(new DataColumn("year", typeof(String))); dt.Columns.Add(new DataColumn("value", typeof(String))); // NOT GETTING TO PARSE In specified format /**** NEED HELP HERE *****/ return dt; } protected void Button1_Click(object sender, EventArgs e) { string CurrentFilePath = Path.GetFullPath(FileUpload1.PostedFile.FileName); ExcelToDataTable(CurrentFilePath); } 

请帮我怎么做到这一点。 我怎样才能parsinginput的excel数据在指定的格式,如附件中的链接(截图)所述。 请任何方式来解决我的问题。

我用C#OLEDB ACE引擎解决了这个问题。 目前它只支持大约250列。 它至今满足我的要求。

解决scheme是我可以通过input文件的代码获取表单名称和表单范围。 我复制input文件到一个C#oledb数据表inputtable,使用该数据表我创build了另一个格式化的数据表,它保存来自基于条件逻辑的inputtable的值。 我用linq来查询数据表,以生成格式化的结果。

点击button:

  string rangeStringwithSHeet = sheetName + excelComm.GetRange(sheetName, excelConn); dataQuery = string.Format("SELECT Institution" + queryIn + " FROM [{0}] ", rangeStringwithSHeet); // connect to excel with query and get the initiall datatable from excel input dataExcelTable = excelComm.FillDataTableWithQuery(dataQuery, excelConn); formattedDataTableExcel(dataExcelTable); 

我在formattedDataTableExcel()方法中包含的实际转换逻辑,我在这里为我的web应用程序创build了这个逻辑。 我根据自己的业务逻辑写逻辑。 我没有在这里发布实际的逻辑。 如果有人有类似的问题,让我知道我可以帮助转换过程。

我的build议是重新考虑你的工具。 在像SQL Server集成服务(SSIS)或其他唯一目的是这样的工具的工具中,这样做会容易得多。

从SSIS Wiki文章中 ,“SSIS是一个数据集成和工作stream应用程序的平台”。

从C#维基文章 “C#(发音如见sharp”)是一个多范式编程语言“。

我已经创build了一个解决scheme,可以在这里findF#中的数据。 由于F#可以在.NET CLR上运行,所以可以从C#调用它,或者使用linq等效操作将它转换为C#。

 // Sample Input as a jagged array let sampleInput = [| [| "id"; "name"; "variable1"; "variable1"; "variable2" |] [| ""; ""; "Fall 2000"; "Fall 2001"; "Fall 2000" |] [| "1"; "abc"; "1400"; "1500"; "1200" |] [| "2"; "xyz"; "1200"; "1400"; "1100" |] |] let variables = sampleInput.[0].[2 ..] let falls = sampleInput.[1].[2 ..] let idNameValues = sampleInput.[2 ..] |> Array.map (fun value -> (value.[0], value.[1], value.[2 ..])) // Output as an array of tuples let output = idNameValues |> Array.collect (fun (id, name, values) -> Array.zip3 variables falls values // Zip up the variables, falls and values data arrays for each old id, name combination |> Array.mapi (fun i (variable, fall, value) -> (i, int id, name, variable, fall, value)) // Flatten out over the row id, old id index and name ) |> Array.sortBy (fun (row, id, _, _, _, _) -> (row, id)) // Sort by row id and old id index |> Array.mapi (fun i (_, _, name, variable, fall, value) -> (i + 1, name, variable, fall, int value)) // Add new id index printfn "SampleInput =\n %A" sampleInput printfn "Output =\n %A" output 

我实际上已经把F#代码翻译成C#了。 我相信你也许可以在这里写更多的惯用的C#代码,性能可能与大量的linq缺乏,但它似乎工作!

你可以看到它在.NET的小提琴在这里工作 。

 using System; using System.Linq; public class Program { public static string[][] SampleInput() { return new string[][]{ new string[] { "id", "name", "variable1", "variable1", "variable2" }, new string[] { "", "", "Fall 2000", "Fall 2001", "Fall 2000" }, new string[] { "1", "abc", "1400", "1500", "1200" }, new string[] { "2", "xyz", "1200", "1400", "1100" } }; } public static Tuple<int, string, string, string, int>[] Unpivot(string[][] flattenedInput) { var variables = (flattenedInput[0]).Skip(2).ToArray(); var falls = (flattenedInput[1]).Skip(2).ToArray(); var idNameValues = flattenedInput.Skip(2).Select(idNameValue => Tuple.Create(idNameValue[0], idNameValue[1], idNameValue.Skip(2))).ToArray(); return idNameValues .SelectMany(idNameValue => variables .Zip(falls, (variable, fall) => Tuple.Create(variable, fall)) .Zip(idNameValue.Item3, (variableFall, val) => Tuple.Create(variableFall.Item1, variableFall.Item2, val)) .Select((variableFallVal, i) => Tuple.Create(i + 1, Convert.ToInt32(idNameValue.Item1), idNameValue.Item2, variableFallVal.Item1, variableFallVal.Item2, variableFallVal.Item3)) ) .OrderBy(rowId_ => Tuple.Create(rowId_.Item1, rowId_.Item2)) .Select((_NameVariableFallValue, i) => Tuple.Create(i + 1, _NameVariableFallValue.Item3, _NameVariableFallValue.Item4, _NameVariableFallValue.Item5, Convert.ToInt32(_NameVariableFallValue.Item6))) .ToArray(); } public static void Main() { var flattenedData = SampleInput(); var normalisedData = Unpivot(SampleInput()); Console.WriteLine("SampleInput ="); foreach (var row in SampleInput()) { Console.WriteLine(Tuple.Create(row[0], row[1], row[2], row[3], row[4]).ToString()); } Console.WriteLine("\nOutput ="); foreach (var row in normalisedData) { Console.WriteLine(row.ToString()); } } } 

编辑:下面是一个将文件path表示的excel文件转换为锯齿形string数组的示例。 在这种情况下,我使用Nuget Package ExcelDataReader从Excel中获取数据。

 using System; using System.IO; using System.Data; using System.Collections.Generic; using System.Linq; using Excel; // Install Nuget Package ExcelDataReader public class Program { public static string[][] ExcelSheetToJaggedArray(string fileName, string sheetName) { using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read)) { using (var excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream)) { var data = excelReader.AsDataSet().Tables .Cast<DataTable>() .FirstOrDefault(sheet => sheet.TableName == sheetName); return data.Rows .Cast<DataRow>() .Select(row => row.ItemArray .Select(cell => cell.ToString()).ToArray()) .ToArray(); } } } public static void Main() { // Sample use of ExcelSheetToJaggedArray function var fileName = @"C:\SampleInput.xlsx"; var jaggedArray = ExcelSheetToJaggedArray(fileName, "Sheet1"); foreach (var row in jaggedArray) { foreach (var cell in row) { Console.Write(cell.ToString() + ","); } Console.WriteLine(); } } }