在脚本转换中对多个输入列应用行转换

Apply row transformation for multiple input columns in Script Transformation

我正在尝试在 SSIS 中导入一个包含合并单元格的 Excel 文件,SSIS 将这些合并单元格读取为 NULL,而不是第一个包含数据的单元格。

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

我发现这段代码将代码应用于 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 列?

您将无法将其泛化。如果有人不知道,我会很乐意删除它并悬赏他们的答案。

为什么不能完成是因为在您的 Input0_ProcessInputRow 方法中,在 ScriptMain class 中接受一个 Input0Buffer 作为参数。 Input0Buffer 是自动生成的 class。以下注释是定义 Input0Buffer class

BufferWrapper.cs 文件的开头
/* 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! */

因此,class 定义了您在 ProcessInputMethod 中可用的内容。它为您 select 单击 "Edit script" 之前的所有列生成一堆 getters and/or setter 方法和一个 IsNull 方法按钮。

Input0Buffer 派生自 ScriptBuffer class。 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 class 中定义为受保护。它没有在我们自动生成的 class 中定义为任何内容,因此在 class 定义之外无法访问它。这意味着当我们 使用 实例时,就像我们在 ScriptMain 中所做的那样,我们不能触及受保护的成员,因为它们的行为就像私有的一样。

我相信你可以实现一个 IEnumerable something 接口,这样你就可以在 Input0Buffer 上做你想做的事情 class 但要知道每次打开脚本时,Visual Studio 将重新生成 class 并删除您的编辑。

当我打字时,我正在做笔记以检查 Extension Methods 他们可能提供的方法...

事实上,您实际上可以访问脚本中的底层对象并遍历缓冲区,而无需使用命名列。您需要继承缓冲区并在public override void ProcessInput(int InputID, string InputName, PipelineBuffer Buffer, OutputNameMap OutputMap)中使用这个继承的class。我通常使用从 Input0Buffer(自动生成的)继承的 class,因此我可以访问 both 命名的和可迭代的 columns.You 可以通过以下方式获取列的索引使用 Reflection 例如:

using System.Reflection;
...    
#region Input0ByIndexBuffer
//inherit via BufferWrapper 
    public class Input0ByIndexBuffer : Input0Buffer
    {
        public Dictionary<string, int> ColumnIndexes = new Dictionary<string, int>();

        public Input0ByIndexBuffer(PipelineBuffer Buffer, int[] BufferColumnIndexes, OutputNameMap OutputMap) : base(Buffer, BufferColumnIndexes, OutputMap)
        {
            IList<string> propertyList = new List<string>();
            foreach (PropertyInfo property in typeof(Input0Buffer).GetProperties())
                if (!property.Name.EndsWith("_IsNull"))
                    propertyList.Add(property.Name.ToUpperInvariant());
            for (int i = 0; i < propertyList.Count; i++)
                ColumnIndexes[propertyList[i]] = i;
        }
        new public bool IsNull(int columnIndex)
        {
            return base.IsNull(columnIndex);
        }
        new public void SetNull(int columnIndex)
        {
            base.SetNull(columnIndex);
        }
        new public object this[int ColumnIndex]
        {
            get
            {
                return base[ColumnIndex];
                // return GetObject(ColumnIndex);
            }
            set
            {
                //SetObject(ColumnIndex, value, false);
                base[ColumnIndex] = value;
            }
        }
        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 object GetObject(int columnIndex)
        {
            BufferColumn columnInfo = GetColumnInfo(columnIndex);
            switch (columnInfo.DataType)
            {
                case DataType.DT_BOOL:
                case DataType.DT_BYREF_BOOL:
                    return GetBoolean(columnIndex);
                case DataType.DT_I2:
                case DataType.DT_BYREF_I2:
                    return GetInt16(columnIndex);
                case DataType.DT_I4:
                case DataType.DT_BYREF_I4:
                    return GetInt32(columnIndex);
                case DataType.DT_R4:
                case DataType.DT_BYREF_R4:
                    return GetSingle(columnIndex);
                case DataType.DT_R8:
                case DataType.DT_BYREF_R8:
                    return GetDouble(columnIndex);
                case DataType.DT_CY:
                case DataType.DT_BYREF_CY:
                case DataType.DT_DECIMAL:
                case DataType.DT_NUMERIC:
                case DataType.DT_BYREF_DECIMAL:
                case DataType.DT_BYREF_NUMERIC:
                    return GetDecimal(columnIndex);
                case DataType.DT_I1:
                case DataType.DT_BYREF_I1:
                    return GetSByte(columnIndex);
                case DataType.DT_UI1:
                case DataType.DT_BYREF_UI1:
                    return GetByte(columnIndex);
                case DataType.DT_UI2:
                case DataType.DT_BYREF_UI2:
                    return GetUInt16(columnIndex);
                case DataType.DT_UI4:
                case DataType.DT_BYREF_UI4:
                    return GetUInt32(columnIndex);
                case DataType.DT_I8:
                case DataType.DT_BYREF_I8:
                    return GetInt64(columnIndex);
                case DataType.DT_UI8:
                case DataType.DT_BYREF_UI8:
                    return GetUInt64(columnIndex);
                case DataType.DT_DBDATE:
                case DataType.DT_BYREF_DBDATE:
                    return GetDate(columnIndex);
                case DataType.DT_DATE:
                case DataType.DT_BYREF_DATE:
                case DataType.DT_FILETIME:
                case DataType.DT_BYREF_FILETIME:
                case DataType.DT_DBTIME:
                case DataType.DT_BYREF_DBTIME:
                case DataType.DT_DBTIMESTAMP:
                case DataType.DT_BYREF_DBTIMESTAMP:
                case DataType.DT_DBTIME2:
                case DataType.DT_BYREF_DBTIME2:
                case DataType.DT_DBTIMESTAMPOFFSET:
                case DataType.DT_BYREF_DBTIMESTAMPOFFSET:
                case DataType.DT_DBTIMESTAMP2:
                case DataType.DT_BYREF_DBTIMESTAMP2:
                    return GetDateTime(columnIndex);
                default:
                    throw new Exception(columnInfo.DataType.ToString() + " not yet supported ");
            }
        }
        public void SetObject(int columnIndex, object value, bool failSilently = true)
        {
            BufferColumn columnInfo = GetColumnInfo(columnIndex);
            try
            {
                switch (columnInfo.DataType)
                {
                    case DataType.DT_BOOL:
                    case DataType.DT_BYREF_BOOL:
                        SetBoolean(columnIndex, (bool)value);
                        break;
                    case DataType.DT_I2:
                    case DataType.DT_BYREF_I2:
                        SetInt16(columnIndex, (short)value);
                        break;
                    case DataType.DT_I4:
                    case DataType.DT_BYREF_I4:
                        SetInt32(columnIndex, (int)value);
                        break;
                    case DataType.DT_R4:
                    case DataType.DT_BYREF_R4:
                        SetSingle(columnIndex, (float)value);
                        break;
                    case DataType.DT_R8:
                    case DataType.DT_BYREF_R8:
                        SetDouble(columnIndex, (double)value);
                        break;
                    case DataType.DT_CY:
                    case DataType.DT_BYREF_CY:
                    case DataType.DT_DECIMAL:
                    case DataType.DT_NUMERIC:
                    case DataType.DT_BYREF_DECIMAL:
                    case DataType.DT_BYREF_NUMERIC:
                        SetDecimal(columnIndex, (decimal)value);
                        break;
                    case DataType.DT_I1:
                    case DataType.DT_BYREF_I1:
                        SetSByte(columnIndex, (sbyte)value);
                        break;
                    case DataType.DT_UI1:
                    case DataType.DT_BYREF_UI1:
                        SetByte(columnIndex, (byte)value);
                        break;
                    case DataType.DT_UI2:
                    case DataType.DT_BYREF_UI2:
                        SetUInt16(columnIndex, (ushort)value);
                        break;
                    case DataType.DT_UI4:
                    case DataType.DT_BYREF_UI4:
                        SetUInt32(columnIndex, (uint)value);
                        break;
                    case DataType.DT_I8:
                    case DataType.DT_BYREF_I8:
                        SetInt64(columnIndex, (long)value);
                        break;
                    case DataType.DT_UI8:
                    case DataType.DT_BYREF_UI8:
                        SetUInt64(columnIndex, (ulong)value);
                        break;
                    case DataType.DT_DBDATE:
                    case DataType.DT_BYREF_DBDATE:
                        SetDate(columnIndex, (DateTime)value);
                        break;
                    case DataType.DT_DATE:
                    case DataType.DT_BYREF_DATE:
                    case DataType.DT_FILETIME:
                    case DataType.DT_BYREF_FILETIME:
                    case DataType.DT_DBTIME:
                    case DataType.DT_BYREF_DBTIME:
                    case DataType.DT_DBTIMESTAMP:
                    case DataType.DT_BYREF_DBTIMESTAMP:
                    case DataType.DT_DBTIME2:
                    case DataType.DT_BYREF_DBTIME2:
                    case DataType.DT_DBTIMESTAMPOFFSET:
                    case DataType.DT_BYREF_DBTIMESTAMPOFFSET:
                    case DataType.DT_DBTIMESTAMP2:
                    case DataType.DT_BYREF_DBTIMESTAMP2:
                        SetDateTime(columnIndex, (DateTime)value);
                        break;
                    default:
                        throw new Exception(columnInfo.DataType.ToString() + " not yet supported ");
                }
            }
            catch (Exception e)
            {
                if (failSilently == false)
                    throw e;
                else
                    try { SetNull(columnIndex); } catch { }
            }
        }
        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 ushort GetUInt16(int columnIndex)
        {
            return Buffer.GetUInt16(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(BufferColumnIndexes[columnIndex], data);
        }
        public void AddBlobData(int columnIndex, byte[] data, int count)
        {
            Buffer.AddBlobData(BufferColumnIndexes[columnIndex], data, count);
        }
        public void ResetBlobData(int columnIndex)
        {
            Buffer.ResetBlobData(columnIndex);
        }
        public void SetBoolean(int columnIndex, bool value)
        {
            Buffer.SetBoolean(BufferColumnIndexes[columnIndex], value);
        }
        public void SetByte(int columnIndex, byte value)
        {
            Buffer.SetByte(BufferColumnIndexes[columnIndex], value);
        }
        public void SetBytes(int columnIndex, byte[] bytesValue)
        {
            Buffer.SetBytes(BufferColumnIndexes[columnIndex], bytesValue);
        }
        public void SetDate(int columnIndex, DateTime value)
        {
            Buffer.SetDate(BufferColumnIndexes[columnIndex], value);
        }
        public void SetDateTime(int columnIndex, DateTime value)
        {
            Buffer.SetDateTime(BufferColumnIndexes[columnIndex], value);
        }
        public void SetDateTimeOffset(int columnIndex, DateTimeOffset value)
        {
            Buffer.SetDateTimeOffset(BufferColumnIndexes[columnIndex], value);
        }
        public void SetDecimal(int columnIndex, decimal value)
        {
            Buffer.SetDecimal(BufferColumnIndexes[columnIndex], value);
        }
        public void SetDouble(int columnIndex, double value)
        {
            Buffer.SetDouble(BufferColumnIndexes[columnIndex], value);
        }
        public void SetGuid(int columnIndex, Guid value)
        {
            Buffer.SetGuid(BufferColumnIndexes[columnIndex], value);
        }
        public void SetInt16(int columnIndex, short value)
        {
            Buffer.SetInt16(BufferColumnIndexes[columnIndex], value);
        }
        public void SetInt32(int columnIndex, int value)
        {
            Buffer.SetInt32(BufferColumnIndexes[columnIndex], value);
        }
        public void SetInt64(int columnIndex, long value)
        {
            Buffer.SetInt64(BufferColumnIndexes[columnIndex], value);
        }
        public void SetSByte(int columnIndex, sbyte value)
        {
            Buffer.SetSByte(BufferColumnIndexes[columnIndex], value);
        }
        public void SetSingle(int columnIndex, float value)
        {
            Buffer.SetSingle(BufferColumnIndexes[columnIndex], value);
        }
        public void SetString(int columnIndex, string value)
        {
            Buffer.SetString(BufferColumnIndexes[columnIndex], value);
        }
        public void SetTime(int columnIndex, TimeSpan value)
        {
            Buffer.SetTime(BufferColumnIndexes[columnIndex], value);
        }
        public void SetUInt16(int columnIndex, ushort value)
        {
            Buffer.SetUInt16(BufferColumnIndexes[columnIndex], value);
        }
        public void SetUInt32(int columnIndex, uint value)
        {
            Buffer.SetUInt32(BufferColumnIndexes[columnIndex], value);
        }
        public void SetUInt64(int columnIndex, ulong value)
        {
            Buffer.SetUInt64(BufferColumnIndexes[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);
    }
}

我将从字典 ColumnIndexes 中获取的列名称的实际索引