2014-03-01 11 views
0

我正在制作一个SSIS包,其中我在一个唯一的Excel文件中传输多个Excel文件。ssis如果在源文件中不存在,则添加具有默认值的列

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

我的SSIS结构是这样的一个:

  1. 一个foreach容器由一个
  2. 一个脚本采取每个文件一个显示windowsform,让我为我的变量列中输入默认值
  3. 我的数据流任务

在我的数据流任务,我想从Excel文件取值,并把他们的目标文件。 如果该列不存在,我希望数据流使用默认值创建一个新列。

我设法做到这一点,但我有一个问题,“如果列不存在”的事情。我添加了一个派生列的列,但他怎么能首先检查该列是否不存在于源文件中。我不想每次都放置默认值。如果该列存在,我想使用它而不是默认值。

谢谢您的回答,

+0

你的意思是'有些colums可能不存在'?而不是'有些行可能不存在'。请注意,如果您使用X列定义与Excel文件的连接,并且随后需要读取Y列,那么您的软件包将无法运行。你能确认源文件绝对是XLSX/XLS而不是CSV吗? –

+0

thxs,那是列而不是行。我确认该文件是xls的。我可以设置最小数据并收集4列,并收集剩余列,如果他们的名字适合,而不是等待10列广告管理失踪? – MystereCoktail

+0

问题在于你的软件包中的excel源代码。如果您将其定义为4列Excel文件,并且您的循环尝试加载10列文件,则它将失败 - 请尝试并查看。我会这样做的方法是,预先尝试并计算文件中有多少列并分支到适当的数据流。你知道你有多少种组合?只有两种类型的文件? –

回答

1

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

这里是我用

  1. windowsForm输入默认值的结构和文件中读取
  2. 数据流
  3. Scriptcomponent作为源
  4. 手动读取文件(通过OLEDB连接器)和把它放在一个数据表中
  5. 检查是否条件如果文件存在于文件中
  6. 如果该列没有存在将其添加到DataTable
  7. 得到列号在后来写
  8. 做的每一列,可能不存在
  9. for循环的的数据表
  10. 每一行创建一个OutputBuffer中排在每一行中,写入相应的值:default如果该列是手动创建的,否则使用datatable.Rows [row] [column]过程的原始数据过程

最后,我的结构完全充满原始默认值的列。

我首先在脚本任务中使用windowsform,然后在这种形式的数据流任务 我让用户通过openfiledialog选择文件,然后在窗体上,他可以输入最后需要的默认值。

这里是我在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(); 
    } 

     } 

    } 
0

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

1)源将Excel中源在数据流任务,Excel源后,将派生列>目标将是脚手架表中的物理表

注:此脚手架表将你的进程后回落完成了。

2)第二个数据流将读取你的脚手架表文件,你可以写一个case语句或定义全列名(SELECT COL1, COL12 from table)而不是(SELECT * FROM TABLE)

3)拖动一个目标源将是你在做什么原始任务。

相关问题