Question

I have several SSIS packages that parse different files into their respective tables. Using SSIS File Watcher task, I want to create a master package that will check a folder for the files and then select the proper sub package based on the OutputVariableName using a precedence constraint. I'm not sure how to write the expression to set the variable correctly. I want to set it based on a FINDSTRING() in the file name.

Was it helpful?

Solution

Your question is about how to use the File Watcher Task from Konesans in an integration services packages.

OutputVariableName String The name of the variable into which the full file path found will be written on completion of the task. The variable specified should be of type string

Via http://www.sqlis.com/post/file-watcher-task.aspx

Create an SSIS Variable at the Package level, called CurrentFileName. Configure the File Watcher Task such that the property OutputVariableName is User::CurrentFileName. When you drop a file into the folder that the Task is watching, it will assign the full path to that variable CurrentFileName.

Your desire is to do something with that Variable with FindString function to help determine the package to fire. Since you don't specify the something I'm going to assume it's based on file name.

It's a pity you're forcing a person to use FindString to perform this task. I say that because the .NET library offers an excellent static method to determine base file names and I hate seeing people re-invent (and debug) the wheel.

I would create 3 Variables to support this endeavor.

  • BaseFileName - String - Evaluate as Expression = True
  • FileExtensionPosition - Int32 - Evaluate as Expression = True
  • LastSlashPosition - Int32 - Evaluate as Expression = True

The LastSlashPosition is going to use FindString to determine the last occurrence of \ in a string. The FileExtensionPosition is going to determine the last occurence of . in a string. BaseFileName will use these numbers to calculate where to slice the @[User::CurrentFileName]` string.

The lazy trick I use for finding the last X in a string is to reverse it. It's then the first element in the string and I can pass 1 as the final parameter to FindString.

The expression assigned to @[User::LastSlashPosition] is

FINDSTRING(REVERSE(@[User::CurrentFileName]), "\\", 1)

The expression assigned to @[User::FileExtensionPosition] is

FINDSTRING(REVERSE(@[User::CurrentFileName]), ".", 1)

The expression assigned to @[User::BaseFileName] then becomes

SUBSTRING((RIGHT(@[User::CurrentFileName], @[User::LastSlashPosition] -1 )), 1, LEN(RIGHT( @[User::CurrentFileName], @[User::LastSlashPosition] -1)) - @[User::FileExtensionPosition] )

Breaking that down, (RIGHT(@[User::CurrentFileName], @[User::LastSlashPosition] -1 )) translates to the base file name. If CurrentFileName equals J:\ssisdata\so\FileWatcher\CleverFile.txt then that evaluates to "CleverFile.txt" I substring that to strip out the end. You can reduce this to just a single substring operation but my brain hurts this late.

Now you are trying to use, I assume, a series of Execute Package Tasks based on a Precedence Constraint of Success and @[User::BaseFilename] == "SubPackage1 You can do this and it'll work fine, it's just that you'll need to set each one up and as you go to set up a new child, you'll have to repeat the work.

As an alternative to this approach, I'd use a ForEach enumerator and define all my key value pairs in there.

enter image description here

Column 0 is the value that BaseFileName could evaluate to.

Column 1 is the SSIS package I want to fire off in response.

I created two variables to support this and configured them as such

enter image description here

My resulting package looks like

enter image description here

Not shown is the File Watcher Task because I have no desire to install that on my machine. Assume that connects to the ForEach Loop.

The ForEach loop spins through the key value pairs shown above. The Script Task inside the container is there just to provide a base for the Precedence Constraint to work. I configure the precedence constraint as Success and @[User::KeyName] == @[User::BaseFileName]

I then simulate the Execute Package Task firing based on that. The actual package name would be driven by the value of @[User::KeyPackage]

And that's your over-engineered solution for the day ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top