【问题标题】:Importing Excel file with dynamic name into SQL table via SSIS?通过SSIS将具有动态名称的Excel文件导入SQL表?
【发布时间】:2013-09-09 12:10:58
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 我没有在这里投反对票,但请注意:(1)当您(两次)说某些东西不是我所需要的时,请详细说明以何种方式。 (2) “……所以我不需要遍历目录”……谁说的?来自专家开发人员的大量网络示例使用这种方法来处理不可预测的文件名。 (3) 你的段落“我的概念......”听起来不错:循环扫描文件,并复制到静态文件名,然后很多很容易。 (4) 下面的素材,来自blinkc,做的不错,值得大家关注! (5) 还有障碍吗?提供您迄今为止工作的详细信息、图片或文字。

标签: sql-server excel ssis


【解决方案1】:

问题陈述

如何动态识别文件名?

您将需要一些机制来检查文件夹的内容并查看存在的内容。具体来说,您正在“加载”目录中查找 Excel 文件。你知道文件扩展名,就是这样。

决议 A

使用 ForEach 文件枚举器。

使用FileSpec*.xls*.xlsx 上的表达式配置枚举器,具体取决于您处理的Excel 类型。

Directory 上添加另一个表达式作为您的加载目录。

我通常创建名为 FolderInputFileMask 的 SSIS 变量并在枚举器中分配它们。

现在,当您运行您的包时,枚举器将在 Diretory 中查找所有与 FileSpec 匹配的文件。

某事需要对找到的内容进行处理。您需要使用 Enumerator 返回的文件名。这是通过变量映射选项卡完成的。我创建了名为 CurrentFileName 的第三个变量,并将枚举器的结果分配给它。

如果您在 ForEach 枚举器中放置一个脚本任务,您应该能够看到 @[User::CurrentFileName] 在“Locals”窗口中的值已从 whatever 到“真实”文件名。

决议 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,因为当包开始执行时,变量的设计时值将无效。请参阅此answer for a longer explanation,但 Siva 在他们的 SO 回答中再次指出了这一点。

【讨论】:

  • 投反对票的人,是否愿意帮助我理解投票,以便我可以改进答案?
  • 改进?这是一个了不起的答案!可能是 serial-downvoting the OP 的同一个家伙。
猜你喜欢
  • 2013-08-09
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
  • 1970-01-01
相关资源
最近更新 更多