SSIS - 从文件夹中的最新excel文件中提取工作表

时间:2013-10-21 22:25:04

标签: sql-server excel ssis

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

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

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

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

  • Sheet1:Excel来源 - > OLE DB目的地
  • Sheet2:Excel来源 - > OLE DB目的地
  • Sheet3:Excel来源 - > OLE DB目的地

我发现的内容涉及将文件名作为变量传递给连接管理器,但我找不到的示例也考虑了工作表名称。有人请帮助我使这更有活力吗?

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

2 个答案:

答案 0 :(得分:0)

我可以帮助您获取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驱动程序,如果您没有安装ACE驱动程序,则需要将sExcelConn替换为文件的连接字符串。

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

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

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

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

这可以帮助您获得所需的内容,您可以动态选择要处理的工作表,并从那里执行您需要执行的操作。

答案 1 :(得分:0)

我有一个更好的方法来代替脚本任务。 对于不了解C#或VB.net的人来说,脚本不容易,所以替代方法是使用WMI监视程序。 如果有新文件,它将继续监视该文件夹,它将启动该程序包并将文件信息(如fileName)存储到sql server中。 另一种方法是使用cmd作为sql表的文件名,执行包后它将删除或存档该文件,因此我们在该文件夹中将始终有一个新文件。 我在我的一个项目中正在做同样的事情。