导入具有可变标头的excel文件

Vig*_*r A 6 sql-server excel ssis etl sql-server-data-tools

我有SSIS包,它将excel文件加载到数据库中.我已创建Excel源任务以将Excel列名称映射到数据库表列名称并且其工作正常.

在极少数情况下,我们正在接收带有一些空格的excel文件列名称(例如:列名称为"ABC"但我们正在接收"ABC")并且导致映射问题并且SSIS失败.

是否有可能在不打开excel的情况下修剪列名称.

注意:页面名称将是动态的,列位置可能会更改(例如:列"ABC可能存在于第一行或第二行或..").

Ven*_*Ven 5

这已经在 MSDN 中得到了很好的记录,运行了类似于@houseofsql 提到的步骤

第1步:

excel连接中排除第一行列名,使用sql命令作为数据访问方式 在此处输入图片说明

Step2:输出列中的别名列名与您的目的地相匹配,

Select * from[Sheet1$A2:I]将从第二行中选择

在此处输入图片说明

最后将目的地添加为 OLEDB 目的地

在此处输入图片说明


Had*_*adi 4

首先,我的解决方案基于@DrHouseofSQL和@Bhouse答案,所以你必须先阅读@DrHouseofSQL答案然后@BHouse答案然后继续这个答案

问题

注意:页面名称将是动态的,列位置可能会改变(例如:列“ABC可能存在于第一行或第二行或......

这种情况有点复杂,可以使用以下解决方法来解决:

解决方案概述

  1. 在导入数据的数据流任务前添加脚本任务
  2. 您必须使用脚本任务打开 Excel 文件并获取工作表名称和标题行
  3. 构建查询并将其存储在变量中
  4. 在第二个数据流任务中,您必须使用上面存储的查询作为源(请注意,您必须将Delay Validation属性设置为 true

解决方案详情

  1. 首先创建一个字符串类型的SSIS变量(即@[User::strQuery])
  2. 添加另一个包含 Excel 文件路径的变量(即 @[User::ExcelFilePath])
  3. 添加脚本任务,然后选择@[User::strQuery]“读写变量”和@[User::ExcelFilePath]“只读变量” (在脚本任务窗口中)
  4. 将脚本语言设置为 VB.Net,并在脚本编辑器窗口中编写以下脚本:

注意:你必须导入System.Data.OleDb

在下面的代码中,我们搜索ex​​cel前15行来查找标题,如果在15行之后可以找到标题,则可以增加数量。我还假设列范围是从AI

    m_strExcelPath = Dts.Variables.Item("ExcelFilePath").Value.ToString

    Dim strSheetname As String = String.Empty
    Dim intFirstRow As Integer = 0

    m_strExcelConnectionString = Me.BuildConnectionString()
    Try


        Using OleDBCon As New OleDbConnection(m_strExcelConnectionString)

            If OleDBCon.State <> ConnectionState.Open Then
                OleDBCon.Open()
            End If

            'Get all WorkSheets
            m_dtschemaTable = OleDBCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,
                                                               New Object() {Nothing, Nothing, Nothing, "TABLE"})

            'Loop over work sheet to get the first one (the excel may contains temporary sheets or deleted ones

            For Each schRow As DataRow In m_dtschemaTable.Rows
                strSheetname = schRow("TABLE_NAME").ToString

                If Not strSheetname.EndsWith("_") AndAlso strSheetname.EndsWith("$") Then

                    Using cmd As New OleDbCommand("SELECT * FROM [" & strSheetname & "A1:I15]", OleDBCon)

                        Dim dtTable As New DataTable("Table1")


                        cmd.CommandType = CommandType.Text

                        Using daGetDataFromSheet As New OleDbDataAdapter(cmd)

                            daGetDataFromSheet.Fill(dtTable)

                            For intCount As Integer = 0 To 15

                                If Not String.IsNullOrEmpty(dtTable.Rows(intCount)(0).ToString) Then

                                    '+1 because datatable is zero based indexed, +1 because we want to start from the second row
                                    intFirstRow = intCount + 2

                                End If


                            Next



                        End Using

                        If intFirstRow = 0 Then Throw New Exception("header not found")

                    End Using

                    'when the first correct sheet is found there is no need to check others
                    Exit For

                End If
            Next

            OleDBCon.Close()

        End Using

    Catch ex As Exception
        Throw New Exception(ex.Message, ex)
    End Try


    Dts.Variables.Item("strQuery").Value = "SELECT * FROM [" & strSheetname & "A" & intFirstRow.ToString & ":I]"

    Dts.TaskResult = ScriptResults.Success
End Sub
Run Code Online (Sandbox Code Playgroud)
  1. 然后你必须添加一个Excel连接管理器,并选择你想要导入的Excel文件(仅在第一次时选择一个示例来定义元数据)
  2. Select * from [Sheet1$A2:I]为变量分配默认值@[User::strQuery]
  3. 在数据流任务中添加 Excel 源,从变量中选择 SQL 命令,然后选择 @[User::strQuery]
  4. 转到列选项卡并按照 @BHouse 建议的相同方式命名列

图像 图片取自@BHouse 的回答

  1. 将数据流任务Delay Validation属性设置为True
  2. 将其他组件添加到 DataFlow Task

更新1:

来自OP评论:sometimes excel with empty data will come.(i.e) we have only header row not not data... in that case it fails entire task

解决方案:

如果您的 Excel 文件不包含数据(仅包含标题),您必须执行以下步骤:

  1. 添加 boolean * 类型的 SSIS 变量(即@[User::ImportFile]
  2. 添加@[User::ImportFile]到脚本任务ReadWrite变量
  3. 在脚本任务中检查文件是否包含行
  4. 如果是则设置@[User::ImportFile]= True,否则@[User::ImportFile]= False
  5. 双击将脚本任务连接到数据流的箭头(优先约束)
  6. 将其类型设置为约束和表达式
  7. 写出下面的表达式

    @[User::ImportFile] == True
    
    Run Code Online (Sandbox Code Playgroud)

注意:新的脚本任务代码为:

@[User::ImportFile] == True
Run Code Online (Sandbox Code Playgroud)

更新2:

来自OP评论:is there any other work around available to process the data flow task without skipping all data flow task,Actually one of the task will log the filename and data count and all, which are missing here

解决方案:

  1. 只需添加另一个数据流任务
  2. 使用另一个连接器和表达式将此数据流与脚本任务连接起来@[User::ImportFile] == False (与第一个连接器的步骤相同)
  3. 在 DataFlow 任务中添加 SCript 组件作为源
  4. 创建要导入到日志的输出列
  5. 创建包含您需要导入的信息的行
  6. 添加日志目标

或者Data Flow Task,您可以添加一个Execute SQL Task来在日志表中插入一行,而不是添加另一个