无法根据SQL Server表中的列从excel文件中读取数据

时间:2018-02-11 18:42:32

标签: c# ssis

我需要将多个excel文件中的数据加载到sql server中的单个表中。但是,我可能会在不同的文件中获得不同的标题。此外,与table相比,excel中的列数不会更少。所以,我正在尝试从excel文件中获取列并与数据库中的系统表进行比较以获取相应的列名。我在SSIS包中的脚本任务中使用它。请参阅下面给出的代码和示例数据。在进行列映射时出错。

Name    EmpId   Salary
Anna    PD200   200
Julie   PD300   300

Name    EmpId   Sal
Maria   PD400   400
Treeza  PD500   500


CREATE TABLE [dbo].[testLoad]
(
    [Name] [nvarchar](255) NULL,
    [EmpId] [nvarchar](255) NULL,
    [Salary] [nvarchar](50) NULL
)

public void Main()
        {
            // TODO: Add your code here

            string filepath = Dts.Variables["User::var_File_Path"].Value.ToString();
            string tablename = Dts.Variables["User::var_Tbl_Name"].Value.ToString();
            string filename = Dts.Variables["User::var_File_Name"].Value.ToString();
            string tbl = tablename.Replace("[", "");
            tbl = tbl.Replace("]", "");
            tbl = tbl.Replace("dbo.", "");

            SqlConnection sqlconnection = new SqlConnection();
            sqlconnection = (SqlConnection)(Dts.Connections["ADOAUDIT"].AcquireConnection(Dts.Transaction));

            string ConStr;
            string HDR;
            HDR = "YES";
            ConStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=" + filepath + "; Extended Properties=\"EXCEL 12.0 XML; HDR="+HDR+"\";";
            OleDbConnection cnn = new OleDbConnection(ConStr);
            cnn.Open();
            DataTable dtSheet = cnn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);


            string sheetname = "";
            string ExcelColumn = "";
            string SqlColumn = "";
            string SqlColumns = "";
            string ExcelCol = "";
            string query = "";
            string querycol = "";

            foreach (DataRow drSheet in dtSheet.Rows)
            {
                sheetname = drSheet["TABLE_NAME"].ToString();
                OleDbCommand oconn = new OleDbCommand(" top 1  * from [" + sheetname + "]", cnn);
                OleDbDataAdapter adp = new OleDbDataAdapter(oconn);
                DataTable dt = new DataTable();
                adp.Fill(dt);
                cnn.Close();

                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    ExcelCol = dt.Columns[i].ColumnName;
                    ExcelCol = ExcelCol.Substring(0, 5);

                    querycol = "select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS " +
                        "where TABLE_NAME = '" + tbl + "' " +
                        "and COLUMN_NAME like '" + ExcelCol + "%'";
                    SqlCommand sqlCommand = new SqlCommand(querycol, sqlconnection);
                    SqlColumn = (string)sqlCommand.ExecuteScalar();

                    if (!String.IsNullOrEmpty(SqlColumn))
                    {
                        SqlColumns = SqlColumns + "'" + SqlColumn + "',";
                        ExcelColumn = ExcelColumn + "'" + dt.Columns[i].ColumnName + "',";
                    }
                }

                SqlColumns = SqlColumns.TrimEnd(',');
                ExcelColumn = ExcelColumn.TrimEnd(',');
                query = "select " + ExcelColumn + " from [" + sheetname + "]";

                OleDbConnection conn1 = new OleDbConnection(ConStr);
                conn1.Open();
                OleDbCommand oconn1 = new OleDbCommand(query, conn1);
                OleDbDataAdapter adp1 = new OleDbDataAdapter(oconn1);
                DataTable dt1 = new DataTable();
                adp1.Fill(dt1);
                conn1.Close();

                //Load Data from DataTable to SQL Server Table.
                using (SqlBulkCopy BC = new SqlBulkCopy(sqlconnection))
                {
                    BC.DestinationTableName = tablename;
                    foreach (var column in dt1.Columns)
                    {
                        BC.ColumnMappings.Add(column.ToString(), SqlColumns.ToString());
                    }

                    BC.WriteToServer(dt);
                }
                sqlconnection.Close();
            }

            Dts.TaskResult = (int)ScriptResults.Success;
        }

        #region ScriptResults declaration
        /// <summary>
        /// This enum provides a convenient shorthand within the scope of this class for setting the
        /// result of the script.
        /// 
        /// This code was generated automatically.
        /// </summary>
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion

    }

谢谢 朱莉

1 个答案:

答案 0 :(得分:0)

哇,设置和维护会很痛苦。这是一种将2个Excel文件合并为1的方法。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;


namespace WindowsFormsApplication5
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Excel.Application app = new Excel.Application();

            app.Visible = true;
            app.Workbooks.Add("");
            app.Workbooks.Add(@"C:\Users\Excel\Desktop\excel_files\Book1.xlsx");
            app.Workbooks.Add(@"C:\Users\Excel\Desktop\excel_files\Book2.xlsx");


            for (int i = 2; i <= app.Workbooks.Count; i++)
            {
                int count = app.Workbooks[i].Worksheets.Count;

                app.Workbooks[i].Activate();
                for (int j = 1; j <= count; j++)
                {
                    Excel._Worksheet ws = (Excel._Worksheet)app.Workbooks[i].Worksheets[j];
                    ws.Select(Type.Missing);
                    ws.Cells.Select();

                    Excel.Range sel = (Excel.Range)app.Selection;
                    sel.Copy(Type.Missing);

                    Excel._Worksheet sheet = (Excel._Worksheet)app.Workbooks[1].Worksheets.Add(
                    Type.Missing, Type.Missing, Type.Missing, Type.Missing
                    );

                    sheet.Paste(Type.Missing, Type.Missing);

                }
            }
        }
    }
}

如果我是你,我不会用C#来做这件事。我认为你最好使用VBA,将日期从每个Excel文件推送到SQL Server。以下是一些供您考虑的选项。

https://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm#Introduction

或者,使用SQL从excel文件中获取数据并将所有内容加载到SQL Server中。

SELECT *
FROM OPENROWSET(
    'Microsoft.ACE.OLEDB.12.0',
    'Excel 8.0;HDR=NO;Database=T:\temp\Test.xlsx',
    'select * from [sheet1$]')

或者,甚至考虑使用第三方资源将所有excel文件合并为1,然后将其加载到SQL Server中。以下是我所谈论的一个例子。

https://www.rondebruin.nl/win/addins/rdbmerge.htm

enter image description here