在“脚本转换”中为多个输入列应用行转换

时间:2015-02-09 18:00:57

标签: c# excel ssis

我尝试在已合并单元格的SSIS中导入Excel文件,并且SSIS将这些合并的单元格读取为除具有数据的第一个单元格之外的其他单元格。

我正在尝试解析信息,为此我想将合并的单元格数据应用于之前合并的每个单元格。

我有这个代码,我发现将代码应用于F1列(在我的输入中)

    // This script adjusts the value of all string fields
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]

public class ScriptMain : UserComponent
{
    string filledField1 = "";

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        // Check if the value is null
        if (Row.F1_IsNull)
        {
            // If null => replace value by variable
            Row.F1 = filledField1;
        }
        else
        {
            // If not null => replace variable by value
            filledField1 = Row.F1;
        }
    }
}

我想要的是通过foreach循环将此代码应用于多个列,但我只能在之前知道列的名称时才这样做。

如何转换此代码以仅为每列的每一行而不是F1列应用转换?

2 个答案:

答案 0 :(得分:1)

你无法对其进行整合。如果有人不知道,我会很乐意将其删除并给予答案。

无法完成的原因是,在Input0_ProcessInputRow方法的ScriptMain类中,接受Input0Buffer作为参数。 Input0Buffer是一个自动生成的类。以下注释将定位BufferWrapper.cs文件,该文件定义了Input0Buffer类

/* THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT!
*  Microsoft SQL Server Integration Services buffer wrappers
*  This module defines classes for accessing data flow buffers
*  THIS IS AUTO-GENERATED CODE THAT WILL BE OVERWRITTEN! DO NOT EDIT! */

因此,该类定义了ProcessInputMethod中可用的内容。它为之前选择的所有列生成了一堆getter和/或setter方法以及一个IsNull方法之前单击了"编辑脚本"按钮。

Input0Buffer派生自ScriptBuffer类。 ScriptBuffer的定义是

namespace Microsoft.SqlServer.Dts.Pipeline
{
    public class ScriptBuffer
    {
        protected PipelineBuffer Buffer;
        protected int[] BufferColumnIndexes;

        public ScriptBuffer(PipelineBuffer BufferToUse, int[] BufferColumnIndexesToUse, OutputNameMap OutputMap);

        protected object this[int ColumnIndex] { get; set; }

        protected void AddRow();
        protected void DirectRow(string outputName);
        protected bool EndOfRowset();
        protected bool IsNull(int ColumnIndex);
        protected bool NextRow();
        protected void SetEndOfRowset();
        protected void SetNull(int ColumnIndex);
    }
}

重要的是要注意名为Buffer的PipelineBuffer实例在ScriptBuffer类中被定义为受保护。它在我们的自动生成的类中没有被定义为任何东西,因此它不能在该类定义之外访问。这意味着当我们使用实例时,正如我们在ScriptMain中所做的那样,我们无法触及受保护的成员,因为它们的行为就像私有一样。

我确定你可以实现一个IEnumerable接口,这样你就可以做你想要在Input0Buffer类上做的事情,但是知道每次打开脚本时,Visual Studio都会重新生成该课程并删除你的编辑。

在我输入此内容时,我正在记录Extension Methods如何提供方法......

答案 1 :(得分:1)

事实上,您实际上可以 访问脚本中的基础对象并在缓冲区上进行迭代,而无需使用命名列。您需要继承缓冲区并在public override void ProcessInput(int InputID, string InputName, PipelineBuffer Buffer, OutputNameMap OutputMap)中使用此继承的类。我通常使用从Input0Buffer继承的类(自动生成的类),以便可以访问 both 和named以及可迭代的列。 例如:

#region Input0ByIndexBuffer
//inherit via BufferWrapper 
public class Input0ByIndexBuffer : Input0Buffer
{
    public Input0ByIndexBuffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap) : base(Buffer, BufferColumnIndexes, OutputMap)
    {
    }
    new public bool IsNull(int columnIndex)
    {
        return base.IsNull(columnIndex);
    }
    new public void SetNull(int columnIndex)
    {
        base.SetNull(columnIndex);
    }
    public BufferColumn GetColumnInfo(int columnIndex)
    {
        return Buffer.GetColumnInfo(BufferColumnIndexes[columnIndex]);
    }
    //expose the Buffer.Get methods using the columnindex, this enables iterations over index instead of columns names
    public sbyte GetSByte(int columnIndex)
    {
        return Buffer.GetSByte(BufferColumnIndexes[columnIndex]);
    }
    public byte GetByte(int columnIndex)
    {
        return Buffer.GetByte(BufferColumnIndexes[columnIndex]);
    }
    public bool GetBoolean(int columnIndex)
    {
        return Buffer.GetBoolean(BufferColumnIndexes[columnIndex]);
    }
    public short GetInt16(int columnIndex)
    {
        return Buffer.GetInt16(BufferColumnIndexes[columnIndex]);
    }
    public int GetInt32(int columnIndex)
    {
        return Buffer.GetInt32(BufferColumnIndexes[columnIndex]);
    }
    public uint GetUInt32(int columnIndex)
    {
        return Buffer.GetUInt32(BufferColumnIndexes[columnIndex]);
    }
    public long GetInt64(int columnIndex)
    {
        return Buffer.GetInt64(BufferColumnIndexes[columnIndex]);
    }
    public ulong GetUInt64(int columnIndex)
    {
        return Buffer.GetUInt64(BufferColumnIndexes[columnIndex]);
    }
    public decimal GetDecimal(int columnIndex)
    {
        return Buffer.GetDecimal(BufferColumnIndexes[columnIndex]);
    }
    public float GetSingle(int columnIndex)
    {
        return Buffer.GetSingle(BufferColumnIndexes[columnIndex]);
    }
    public double GetDouble(int columnIndex)
    {
        return Buffer.GetDouble(BufferColumnIndexes[columnIndex]);
    }
    public DateTime GetDateTime(int columnIndex)
    {
        return Buffer.GetDateTime(BufferColumnIndexes[columnIndex]);
    }
    public DateTime GetDate(int columnIndex)
    {
        return Buffer.GetDate(BufferColumnIndexes[columnIndex]);
    }
    public byte[] GetBytes(int columnIndex)
    {
        return Buffer.GetBytes(BufferColumnIndexes[columnIndex]);
    }
    public DateTimeOffset GetDateTimeOffset(int columnIndex)
    {
        return Buffer.GetDateTimeOffset(BufferColumnIndexes[columnIndex]);
    }
    public Guid GetGuid(int columnIndex)
    {
        return Buffer.GetGuid(BufferColumnIndexes[columnIndex]);
    }
    public string GetString(int columnIndex)
    {
        return Buffer.GetString(BufferColumnIndexes[columnIndex]);
    }
    public TimeSpan GetTime(int columnIndex)
    {
        return Buffer.GetTime(BufferColumnIndexes[columnIndex]);
    }

    //to test against componentwrapper?
    public uint GetBlobLength(int columnIndex)
    {
        return Buffer.GetBlobLength(BufferColumnIndexes[columnIndex]);
    }
    public byte[] GetBlobData(int columnIndex, int offset, int count)
    {
        return Buffer.GetBlobData(BufferColumnIndexes[columnIndex], offset, count);
    }



    public void AddBlobData(int columnIndex, byte[] data)
    {
        Buffer.AddBlobData(columnIndex, data);
    }
    public void AddBlobData(int columnIndex, byte[] data, int count)
    {
        Buffer.AddBlobData(columnIndex, data, count);
    }
    public void ResetBlobData(int columnIndex)
    {
        Buffer.ResetBlobData(columnIndex);
    }
    public void SetBoolean(int columnIndex, bool value)
    {
        Buffer.SetBoolean(columnIndex, value);
    }
    public void SetByte(int columnIndex, byte value)
    {
        Buffer.SetByte(columnIndex, value);
    }
    public void SetBytes(int columnIndex, byte[] bytesValue)
    {
        Buffer.SetBytes(columnIndex, bytesValue);
    }
    public void SetDate(int columnIndex, DateTime value)
    {
        Buffer.SetDate(columnIndex, value);
    }
    public void SetDateTime(int columnIndex, DateTime value)
    {
        Buffer.SetDateTime(columnIndex, value);
    }
    public void SetDateTimeOffset(int columnIndex, DateTimeOffset value)
    {
        Buffer.SetDateTimeOffset(columnIndex, value);
    }
    public void SetDecimal(int columnIndex, decimal value)
    {
        Buffer.SetDecimal(columnIndex, value);
    }
    public void SetDouble(int columnIndex, double value)
    {
        Buffer.SetDouble(columnIndex, value);
    }
    public void SetGuid(int columnIndex, Guid value)
    {
        Buffer.SetGuid(columnIndex, value);
    }
    public void SetInt16(int columnIndex, short value)
    {
        Buffer.SetInt16(columnIndex, value);
    }
    public void SetInt32(int columnIndex, int value)
    {
        Buffer.SetInt32(columnIndex, value);
    }
    public void SetInt64(int columnIndex, long value)
    {
        Buffer.SetInt64(columnIndex, value);
    }
    public void SetSByte(int columnIndex, sbyte value)
    {
        Buffer.SetSByte(columnIndex, value);
    }
    public void SetSingle(int columnIndex, float value)
    {
        Buffer.SetSingle(columnIndex, value);
    }
    public void SetString(int columnIndex, string value)
    {
        Buffer.SetString(columnIndex, value);
    }
    public void SetTime(int columnIndex, TimeSpan value)
    {
        Buffer.SetTime(columnIndex, value);
    }
    public void SetUInt16(int columnIndex, ushort value)
    {
        Buffer.SetUInt16(columnIndex, value);
    }
    public void SetUInt32(int columnIndex, uint value)
    {
        Buffer.SetUInt32(columnIndex, value);
    }
    public void SetUInt64(int columnIndex, ulong value)
    {
        Buffer.SetUInt64(columnIndex, value);
    }
}
#endregion

并将其用于:

public void Input0_ProcessInputRow(Input0ByIndexBuffer Row)
{
    //do your code
}
public override void ProcessInput(int InputID, string InputName, PipelineBuffer Buffer, OutputNameMap OutputMap)
{
    if (InputName.Equals(@"Input 0", StringComparison.Ordinal))
    {
        Input0_ProcessInput(new Input0ByIndexBuffer(Buffer, GetColumnIndexes(InputID), OutputMap));
    }

}

public  void Input0_ProcessInput(Input0ByIndexBuffer Buffer)
{
    while (Buffer.NextRow())
    {
        Input0_ProcessInputRow(Buffer);
    }
}

我将从ComponentMetaData.InputCollection[@"Input 0"].InputColumnCollection迭代获得的列名的实际索引