0

我在这里做了一些搜索,虽然有些问题很相似,但它们似乎并不是我所需要的。

我要做的是通过 SSIS 将 Excel 文件导入 SQL 表,但问题是我永远不会知道确切的文件名。我们以不稳定的间隔获取文件,并且文件通常在名称中包含日期/月份。例如,我们当前的文件是“Census Data - May 2013.xls”。我们一次只会加载一个文件,所以我不需要循环访问多个 Excel 文件的目录。

我的概念是我可以获取这个文件,将它复制到“加载”目录,然后从那里加载它。在打包开始的时候,我会先清除加载目录,然后在原目录中扫描一个Excel文件,复制到加载目录,然后加载到SQL中。我想我可能必须将文件名存储在某个地方,这样我就不会在接下来的几个月中将相同的文件复制到加载目录中,但我不确定处理它的最佳方法。

除了扫描目录中的 Excel 文件并将其复制到加载目录的部分之外,我几乎已经完成了所有工作。我已经从这个页面获取了我的大部分信息,这(再次)接近我想要做的,但不完全是我需要的解决方案。

谁能带我越过终点线?我似乎无法正确使用 Excel 连接管理器(这是我第一次使用变量),而且我不知道如何将文件放入 Loading 目录。

4

1 回答 1

8

问题陈述

如何动态识别文件名?

您将需要一些机制来检查文件夹的内容并查看存在的内容。具体来说,您正在“加载”目录中查找 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 答案中再次指出了这一点。

于 2013-09-05T15:19:09.027 回答