我正在制作一个SSIS包,我在其中将一些Excel文件传输到一个独特的Excel文件中。
问题是输入文件可能有不同的结构(某些colulns可能不存在)。
我的SSIS结构就像这样:
在我的数据流任务中,我想从Excel文件中获取值并将它们放到目标文件中。 如果列不存在,我希望数据流使用默认值创建新列。
我设法做到了,但我遇到了“如果列不存在”的问题。我添加了一个带有派生列的列,但是如何首先检查源文件中是否存在该列。我不想每次都设置默认值。如果列存在,我想使用它而不是默认值。
感谢您的回答,
答案 0 :(得分:1)
我通过使用脚本组件作为我的数据流源来获得我的答案。
这是我使用的结构
最后,我的结构完全填充了默认值的原始列。
我首先在数据流任务之前在脚本任务中使用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)拖动目标源将是你在原始任务上所做的事情。