C# 使用 oledb 读取 Excel 数据,并将其格式化为指定的格式并插入到 SQL Server 数据库中

本文关键字:格式 插入 数据库 Server SQL 格式化 Excel 读取 oledb 使用 数据 | 更新日期: 2023-09-27 18:33:17

net 和 C#.我需要编写一个程序来浏览和读取 excel,然后以指定的格式解析它,最后插入到 sql server 数据库中。

  1. 我使用 oledb 来读取 excel,并从 excel 创建了 DataTable。现在我很难以所需的格式解析它。这是什么是excel输入以及预期插入数据库的格式的图片的链接。输入和预期输出格式

  2. 现在我正在处理简单的数据,将来我需要对大型 excel 数据(3000 列(进行解析,以解析为大约 250000 条记录。也请给我性能方面的建议。现在我正在使用 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);
    }  

请帮助我如何实现这一目标。如何解析指定格式的输入Excel数据,如链接(屏幕截图(中附图中所述。请建议我解决我的问题的任何方法。

C# 使用 oledb 读取 Excel 数据,并将其格式化为指定的格式并插入到 SQL Server 数据库中

我使用 C# OLEDB ACE 引擎解决了这个问题。目前它仅支持大约 250 列。到目前为止,它满足了我的要求。

解决方案是我能够通过输入文件的代码获取工作表名称和工作表范围。我将输入文件复制到 C# oledb 数据表输入表中,使用该数据表我创建了另一个格式化数据表,该表基于条件逻辑保存输入表中的值。我使用 linq 查询数据表以生成格式化的结果。

单击按钮时:

       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 应用程序创建了它。我根据我的业务逻辑编写逻辑。我不在这里发布实际逻辑。如果有人有类似的问题,请告诉我我可以帮助转换过程。

我的建议是重新考虑你的工具。 在像SQL Server Integration Services(SSIS(这样的工具或其他唯一目的是这样做的工具中,这将容易得多。

摘自 SSIS Wiki 文章"SSIS 是数据集成和工作流应用程序的平台"。

来自 C# Wiki 文章"C#(发音为 see sharp(是一种多范式编程语言"。

我创建了一个用于在 F# 中取消透视数据的解决方案,可以在此处找到。由于 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 Fiddle中工作。

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());
        }
    }
}

编辑:下面是将由文件路径表示的 excel 文件转换为交错字符串数组的示例。在本例中,我使用 Nuget 包 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();
        }
    }
}