如果源文件中不存在,则ssis添加具有默认值的列

时间:2014-03-01 16:47:19

标签: sql sql-server excel ssis dataflow

我正在制作一个SSIS包,我在其中将一些Excel文件传输到一个独特的Excel文件中。

问题是输入文件可能有不同的结构(某些colulns可能不存在)。

我的SSIS结构就像这样:

  1. 一个逐个获取每个文件的foreach容器
  2. 一个脚本,显示一个允许我在变量
  3. 中输入列的默认值的窗体
  4. 我的数据流任务
  5. 在我的数据流任务中,我想从Excel文件中获取值并将它们放到目标文件中。 如果列不存在,我希望数据流使用默认值创建新列。

    我设法做到了,但我遇到了“如果列不存在”的问题。我添加了一个带有派生列的列,但是如何首先检查源文件中是否存在该列。我不想每次都设置默认值。如果列存在,我想使用它而不是默认值。

    感谢您的回答,

2 个答案:

答案 0 :(得分:1)

我通过使用脚本组件作为我的数据流源来获得我的答案。

这是我使用的结构

  1. windowsForm输入默认值和要读取的文件
  2. 数据流
  3. Scriptcomponent作为来源
  4. 手动读取文件(通过OleDB连接器)并将其放入数据表
  5. 检查条件是否存在于文件
  6. 如果列不存在,请将其添加到数据表
  7. 获取要在其中写入的列号
  8. 为每个可能不存在的列执行此操作
  9. for循环,为数据表
  10. 的每一行创建一个outputbuffer行
  11. 在每一行中,写下相应的值:如果列是手动创建的,则为default;否则为原始的,具有datatable.Rows [row] [column] procedure
  12. 最后,我的结构完全填充了默认值的原始列。

    我首先在数据流任务之前在脚本任务中使用windowsform 在这种形式下,我让用户通过openfiledialog选择文件,然后在windowsform上输入最终所需的默认值。

    这是我在scriptcomponent中编写的代码的摘录。 我有变量的默认值 我需要填写uniqueRef,EAN和名称:强制性 但有时我可能在文件中填充了value1和/或value2和/或颜色。如果他们是我想要获得他们的好价值。如果不是我想为所有列设置默认值。

    它可能没有被优化但是完成了工作(8年没有开发和第一次使用C#对我来说是一件相当困难的事情,但我别无选择,因为SSIS不想用UI来做它。)

        using System;
        using System.Data;
        using System.Windows.Forms;
        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
        {
            DataTable dt;
             public override void PreExecute()
            {
                base.PreExecute();
                /*
          get the xls file based on the inputPath and put its data in a datatable
                */
    
        String connString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Variables.InputPath + ";Extended Properties=\"Excel 8.0;IMEX=1\"";
        OleDbConnection connection = new OleDbConnection(connString);
    
        var DataAdapter = new OleDbDataAdapter("SELECT * FROM [ToImport$]", connection);
        dt = new DataTable();
        DataAdapter.Fill(dt);
        base.CreateNewOutputRows();
            }
    
            public override void PostExecute()
            {
                base.PostExecute();
    
            }
        public override void CreateNewOutputRows()
            {
    
        // initialize booleans which will tell if a column was present in the orignial file or has been created
        // data that don't have bool are considered as mandatory, program will fail if missing
        bool value1bool = false;
        bool value2bool = false;
        bool colorbool = false;
    
        // check if the column is in the original file. if not, set boolean to true and add the missing column to the datatable
        if ((dt.Columns.Contains("Value1")) == false)
        {
            dt.Columns.Add(new DataColumn("Value1", typeof(string)));
            value1bool= true;
        }
        if ((dt.Columns.Contains("Value2")) == false)
        {
            dt.Columns.Add(new DataColumn("Value2", typeof(string)));
            value2bool = true;
        }
        if ((dt.Columns.Contains("Color")) == false)
        {
            dt.Columns.Add(new DataColumn("Color", typeof(string)));
            colorbool = true;
        }
        //get the column number of each matching column name to be able to get values later
        int colRef = dt.Columns.IndexOf("UniqueRef");
        int colEan = dt.Columns.IndexOf("EAN");
        int colName = dt.Columns.IndexOf("Article Name");
        int colValue1 = dt.Columns.IndexOf("Value1");
        int colValue2 = dt.Columns.IndexOf("Value2");
        int colColor = dt.Columns.IndexOf("Color");
    
        //for each row of the datatable
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            // adds values of each line to the output buffer corresponding to LOTS output columns
            //generate a new row in the buffer
            LotsOutputBuffer.AddRow();
            //fill rows datas taking datas from the good column with a name matching
            LotsOutputBuffer.RefUnique = dt.Rows[i][colRef].ToString();
            LotsOutputBuffer.EAN= dt.Rows[i][colEan].ToString();
            // if Value1 column is not in the input file, default value from windowsform is taken
            if (Value1bool)
                LotsOutputBuffer.Value1 = Variables.Value1Var;
            else LotsOutputBuffer.Value1 = dt.Rows[i][colValue1].ToString();
            // if Value2 column is not in the input file, default value from windowsform is taken
            if (Value2bool)
                LotsOutputBuffer.Value2 = Variables.Value2Var;
            else    LotsOutputBuffer.Value2=dt.Rows[i][colValue2].ToString();
            ArticlesBuffer.Name = dt.Rows[i][colName].ToString();
            // if Color column is not in the input file, default value from windowsform is taken
            if (colorbool)
                ArticlesBuffer.Color = Variables.colorVar;
            else ArticlesBuffer.Color = dt.Rows[i][colColor].ToString();
        }
    
            }
    
        }
    

答案 1 :(得分:0)

对于你的问题:如果你想做foreach容器,foreach循环将不起作用。相反,我有另一个想法可以帮助你实现目标。

1)源代码将是您的数据流任务中的Excel源代码,Excel源代码后的拖动派生列&gt;目的地将是一个停滞不前的物理表

注意:在您的流程完成后,这个停滞不前的表格将被删除。

2)第二个数据流将从不稳定的表中读取文件,您可以编写案例陈述或定义完整的列名( SELECT COL1, COL12 from table)而不是(SELECT * FROM TABLE)

3)拖动目标源将是你在原始任务上所做的事情。