问题陈述
如何动态识别文件名?
您将需要一些机制来检查文件夹的内容并查看存在的内容。具体来说,您正在“加载”目录中查找 Excel 文件。你知道文件扩展名,就是这样。
决议 A
使用 ForEach 文件枚举器。
根据您正在处理的 Excel 的风格,使用FileSpec
表达式配置枚举器。*.xls
*.xlsx
添加另一个表达式Directory
作为您的加载目录。
FolderInput
我通常会创建名为and的SSIS 变量,FileMask
并在枚举器中分配这些变量。
现在,当您运行您的包时,枚举器将在 Diretory 中查找并找到与 FileSpec 匹配的所有文件。
需要对发现的内容进行处理。您需要使用 Enumerator 返回的文件名。这是通过变量映射选项卡完成的。我创建了名为 CurrentFileName 的第三个变量,并将枚举器的结果分配给它。
如果您在 ForEach 枚举器中放置一个脚本任务,您应该能够看到 @[User::CurrentFileName] 的“Locals”窗口中的值已从任何东西的设计时间值更新为“真实”文件名.
决议 B
使用脚本任务。
您仍然需要创建一个变量来保存当前文件名,并且同时拥有 FolderInput 和 FileMask 变量可能不会有什么坏处。将前者设置为 ReadWrite,将后者设置为 ReadOnly 变量。
选择您选择的 .NET 语言。我正在使用 C#。System.IO.Directory.EnumerateFiles方法
using System;
using System.Data;
using System.IO;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
namespace ST_fe2ea536a97842b1a760b271f190721e
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
string folderInput = Dts.Variables["User::FolderInput"].Value.ToString();
string fileMask = Dts.Variables["User::FileMask"].Value.ToString();
try
{
var files = Directory.EnumerateFiles(folderInput, fileMask, SearchOption.AllDirectories);
foreach (string currentFile in files)
{
Dts.Variables["User::CurrentFileName"].Value = currentFile;
break;
}
}
catch (Exception e)
{
Dts.Events.FireError(0, "Script overkill", e.ToString(), string.Empty, 0);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
决策树
鉴于上述问题的两种解决方案,您如何选择?通常,人们会说“它取决于”,但只有在加载文件夹中确实存在多个文件的情况下,进程是否应该停止/出错可能取决于它的时间。这就是 ForEach 枚举器比脚本任务更麻烦的情况。否则,正如我在最初的回复中所说,这会增加您的开发、测试和维护项目的成本,而没有明显的收益。
比特和鲍勃
进一步解决问题中的细微差别:配置 Excel - 您需要更具体地说明什么不起作用。Siva 的 SO 答案和链接的 blogspot 文章都显示了如何使用我调用的变量的值CurrentFileName
来确保 Excel 文件指向“正确”文件。
您需要将DelayValidation
连接管理器和数据流都设置为 True,因为当包开始执行时,变量的设计时值将无效。请参阅此答案以获得更长的解释,但 Siva 在他们的 SO 答案中再次指出了这一点。