【问题标题】:Get an SSIS C# Script component to read from Excel via OleDb:获取一个 SSIS C# 脚本组件以通过 OleDb 从 Excel 中读取:
【发布时间】:2020-04-30 01:33:47
【问题描述】:

我正在尝试构建一个 SSIS 包以从 Excel 中读取。我找到了一个很好的例子here,它非常接近我的需要。

我的问题是:从一个空白解决方案开始,让 C# 脚本组件从 .xlsx 文件中读取所需的最少步骤是什么?

这是我的代码:

using System;
using System.Data;
using System.Data.OleDb;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{    
    public override void CreateNewOutputRows()
    {
        string fileName = @"E:\SFTP\RSS\Results.xlsx";    
        string cstr = "Provider.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"";

        using (OleDbConnection xlConn = new OleDbConnection(cstr))
        {
            xlConn.Open();
            OleDbCommand xlCmd = xlConn.CreateCommand();
            xlCmd.CommandText = "Select top 10 * from Responses";
            xlCmd.CommandType = CommandType.Text;
            using (OleDbDataReader rdr = xlCmd.ExecuteReader())
            {
                while (rdr.Read())
                {
                    for (int i = 2; i < rdr.FieldCount; i++) //loop from 3 column to last
                    {
                        Output0Buffer.AddRow();
                        Output0Buffer.Question = rdr.GetName(i);
                        Output0Buffer.Response = rdr.ToString();
                    }

                }
            }
            xlConn.Close();
        }
    }

}

这些是我遇到的问题和我遇到的问题: 我需要在解决方案级别配置连接管理器吗?在脚本组件上还是代码包含我需要的所有内容?

我使用什么数据类型/函数/方法将单元格读取为数字、日期或字符串?

以下是我遇到的一些错误:

(2,14): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'System' (are you missing an assembly reference?)
(3,14): error CS0234: The type or namespace name 'Data' does not exist in the namespace 'System' (are you missing an assembly reference?)
(4,17): error CS0234: The type or namespace name 'SqlServer' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
(5,17): error CS0234: The type or namespace name 'SqlServer' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)
(8,27): error CS0246: The type or namespace name 'UserComponent' could not be found (are you missing a using directive or an assembly reference?)
 + additional 10 errors

我正在使用:VS2019、SQL Server 2016 SP2、Office 2016。

这是我的 Excel 表格的屏幕截图:

它包含对第 3 方呼叫中心提供的调查的回复。有几列来标识调用,然后每个列标题包含问题,列数据是响应。它目前有 189 列,并且会随着时间的推移而增长/变化。我的想法是选择前 4 列可靠地识别每一行加上 1 个附加列对于每个问答,并遍历拾取每个列标题和内容的工作表,以便可以插入到表中。随着更多列的添加,它们只会被附加为额外的行。我粘贴的示例代码仅显示 2 列,因为我试图保持示例简单。

这是我尝试过的。 1. 将DataFlow 任务添加到Control Flow。

  1. 将脚本组件添加到 DataFlow。

出现提示时选择来源。

双击打开编辑器。

选择连接管理器。点击添加

在新行上选择新连接,

出现添加新的 SSIS 连接管理器。

这是关于我卡住的地方。我一直在选择 OLEDB Connection。

  1. 在 OLEDB 连接管理器中我应该选择什么?

我已经尝试过 Access 和 MS Oledb Simple Provider。事情开始在这里解开。鉴于脚本中提供了文件名、路径和驱动程序详细信息,连接管理器需要哪些详细信息?

我开始使用代码,但我不知道我在上游所做的工作是否有效。所以我试图从头开始。我正在寻求帮助,通过设置步骤到达 C# 点。

感谢大家的回复。

干杯

皮特

【问题讨论】:

  • 这看起来像是控制流中的脚本任务。您没有在数据流任务中使用 Excel 数据源的任何原因?
  • @thinkOfaNumber 代码是数据流中的脚本任务。 (这就是我想要做的)我想像示例一样使用 C#,因为 xls 布局会随着时间而改变。示例代码将允许我遍历列并获取列名和内容。
  • 我认为您的意思是控制流中的脚本任务。如果您在数据流中,它是脚本组件。请澄清
  • 从您的代码看来,您正在使用脚本组件。不是脚本任务
  • 不要选择连接管理器。您可以在代码中执行此操作。

标签: c# sql-server ssis oledb visual-studio-2019


【解决方案1】:

除了输出之外,没有什么需要添加到脚本组件 GUI 中(记住要正确获取数据类型。)

不要设置连接管理器,您在代码中这样做是因为您不希望 SSIS 试图找出您的列名,坦率地说,我们不知道第 4 列之后的列名。

这是您的代码。我只改变了一些东西。

public override void CreateNewOutputRows()
    {
        //Change this to your filename you do not need a connection manager
        string fileName = @"E:\SFTP\RSS\Results.xlsx";  
        string SheetName = "Sheet1";  
        string cstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + fileName + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"";

        using (System.Data.OleDb.OleDbConnection xlConn = new System.Data.OleDb.OleDbConnection(cstr))
        {
           xlConn.Open();
           System.Data.OleDb.OleDbCommand xlCmd = xlConn.CreateCommand();
           xlCmd.CommandText = "Select * from [" + SheetName + "$]"; //I assume this is the data you want
           xlCmd.CommandType = CommandType.Text;
           using (System.Data.OleDb.OleDbDataReader rdr = xlCmd.ExecuteReader())
           {
              while (rdr.Read())
              {
                 for (int i = 4; i < rdr.FieldCount; i++) //loop from 5th column to last
                 {
                    //The first 4 columns are static and added to every row
                    Output0Buffer.AddRow();
                    Output0Buffer.UniqueID = Int32.Parse(rdr[0].ToString());
                    Output0Buffer.Year = Int32.Parse(rdr[1].ToString());
                    Output0Buffer.ReportingWave = rdr.GetString(2);
                    Output0Buffer.SubmissionDate = rdr.GetString(3);
                    Output0Buffer.Question = rdr.GetName(i);
                    Output0Buffer.Answer = rdr.GetString(i);
                 }

            }
          }
          xlConn.Close();
       }
    }

此代码成功导入了一个如下所示的文件:

【讨论】:

  • 哇。谢谢你,基思太棒了。我会在早上开始。
  • 所以。将连接管理器留空。输出列呢?
  • 你需要定义输出
  • 各种进展。:) 我从一个新的脚本组件开始并添加了您的代码块。我已经设置了输出列(它们需要编号吗?),我现在可以运行数据流了。当我这样做时:没有在 ConnectionString 中指定 OLE DB 提供程序。例如,'Provider=SQLOLEDB;'。
  • @SirSwears-a-lot 现在已经过全面测试。我更改了 cstr(我在输入时搞砸了),我是如何读取整数的,并将日期更改为字符串(您可以稍后再转换)
猜你喜欢
  • 1970-01-01
  • 2012-10-28
  • 1970-01-01
  • 1970-01-01
  • 2010-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多