【问题标题】:SSIS - Extract sheets from latest excel file in a folderSSIS - 从文件夹中的最新excel文件中提取工作表
【发布时间】:2013-10-21 22:25:04
【问题描述】:

我正在创建一个理想情况下的 SSIS 包:

  • 通读文件夹
  • 获取最新文件的文件名和工作表名
  • 将文件名和工作表名传递给连接管理器
  • 仅逐页提取最新文件并将其加载到数据库中

该文件夹将定期更新为最新版本的文件。有问题的文件将有 3 张纸,按特定顺序依次加载。最好我想通过文件的最新写入时间来获取文件,而不是使用文件名。每次上传时文件名本身都会不同。

我创建了一个控制流,它在将工作表加载到数据库中时以正确的顺序进行提取和加载,但是它只从 Excel 连接管理器中的指定文件中读取:

  • Sheet1:Excel 源 -> OLE DB 目标
  • Sheet2:Excel 源 -> OLE DB 目标
  • Sheet3:Excel 源 -> OLE DB 目标

我发现将文件名作为变量传递给连接管理器,但我发现没有任何示例也考虑工作表名称。有人能帮我把它变得更有活力吗?

我正在使用 SQL Server 2012 并在 Visual Studio 2010 中进行设计。

【问题讨论】:

  • “工作表”实际上是连接管理器的“表”,这可能类似于在此 Stack Overflow 问题中设置数据库名称:stackoverflow.com/questions/10506962/…。 ((顺便说一句,仅供参考:我相信 Visual Studio 2010 不支持 SSIS:链接on MSDN。坦率地说,我的 SSIS 项目仍然使用 VS2005,而其他 Web 开发使用 VS2010。))
  • 也许我弄错了。我在 SQL Server Data Tools 中设计包,它在启动时将自己描述为 Visual Studio 2010 Shell。
  • 知道了,关于 VS2010 和 SSIS。如果您将工作表视为“表格”,那么另一个 Stack Overflow 问题对您有用吗?

标签: sql-server excel ssis


【解决方案1】:

我可以帮你获取 VS 2008 中的工作表名称(2010 年可能相同)。

创建一个 Object 类型的变量 (objExcelSheets) 创建脚本任务。 将文件名/路径变量添加到脚本(只读) 将对象变量添加到读写变量中

这是脚本任务的一些代码

Private Sub GetExcelSheets()
    Dim excelFile, connstr, curTable As String
    Dim excelConnection As OleDb.OleDbConnection
    Dim tablesInFile As DataTable
    Dim tablenameInFile As DataRow
    Dim tableCount As Integer = 0
    Dim tableIndex As Integer = 0
    Dim excelTables As String()
    Dim blnFound As Boolean = False

    ReDim excelTables(0)
    excelFile = Dts.Variables("sFilePath").Value.ToString
    connstr = GetExcelConnString()

    excelConnection = New OleDb.OleDbConnection(connstr)
    excelConnection.Open()

    tablesInFile = excelConnection.GetSchema("Tables")
    tableCount = tablesInFile.Rows.Count

    For Each tablenameInFile In tablesInFile.Rows
        curTable = tablenameInFile.Item("TABLE_NAME").ToString.Trim.ToLower

        If curTable.IndexOf("SOMETHING_IN_THE_SHEETS_TO_PROCESS") >= 0 Then
            blnFound = True
            ReDim excelTables(tableIndex)
            excelTables(tableIndex) = "[" + curTable + "]"
            tableIndex += 1
        End If
    Next

    If IsNothing(excelTables(0)) Then excelTables(0) = String.Empty

    excelConnection.Close()

    Dts.Variables("objExcelSheet").Value = excelTables
End Sub

Private Function GetExcelConnString() As String
    Dim sExtendedProperties, sExtension, sFilePath, sExcelConn As String

    sFilePath = Dts.Variables("sFilePath").Value.ToString
    sExtension = sFilePath.Substring(sFilePath.LastIndexOf("."))
    If sExtension.ToLower = ".xlsx" Then
        sExtendedProperties = ";Extended Properties=""EXCEL 12.0;HDR=NO"";"
    ElseIf sExtension.ToLower = ".xls" Then
        sExtendedProperties = ";Extended Properties=""EXCEL 8.0;HDR=NO;IMEX=1"";"
    Else
        sExtendedProperties = String.Empty
    End If

    sExcelConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & sFilePath & sExtendedProperties

    Return sExcelConn
End Function

请注意,这需要安装 ACE 驱动程序,如果您没有这些驱动程序,则需要将 sExcelConn 替换为文件的连接字符串。

这会将工作表名称中带有 SOMETHING_IN_THE_SHEETS_TO_PROCESS 的所有 Excel 工作表放入对象变量 objExcelSheet。您可以将其替换为您需要的任何内容或将其全部删除。

然后您可以执行 ForEach 循环来处理每张工作表。

来自变量枚举器的 Foreach - 变量 = objExcelSheet

变量映射 - 变量(索引为 0 的 WorksheetName)

这应该可以帮助您获得所需的内容,您可以在其中动态选择要处理的工作表并从那里做您需要做的事情。

【讨论】:

    【解决方案2】:

    我有一个更好的方法而不是 script task 。 对于不懂 C# 或 VB.net 的人来说,编写脚本并不容易,所以另一种方法是使用 WMI watcher。 如果有新文件,它将持续监视文件夹,它将启动包并将文件名等文件信息存储到 sql server 中。 另一种方法是使用 cmd 作为 sql 表的文件名,在执行包后,它将删除或存档该文件,因此我们将始终在该文件夹中拥有一个新文件。 我在我的一个项目中做同样的事情。

    【讨论】:

      猜你喜欢
      • 2021-11-22
      • 2014-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2021-03-30
      • 2017-05-07
      相关资源
      最近更新 更多