【问题标题】:Import Excel (.xlsx) with SSIS and Excel source with worksheet containing multiple subsections使用包含多个小节的工作表导入带有 SSIS 和 Excel 源的 Excel (.xlsx)
【发布时间】:2021-08-02 23:31:18
【问题描述】:

我需要你的帮助。

我有一个如下所示的 .xlsx 文件:

我的目标是创建一个 SSIS 包,将这些数据推送到数据库表中。

现在,col1 到 col5 没问题,但每个部分都有一个名称,应该是表中的第 6 列。 所以最终的目标表看起来像:

col1 | col2 | col3 | col4 | col5 | col6(从上到下的名字姓氏)

到目前为止我已经尝试过:

  1. 从 Excel 工作表中创建记录集
  2. 使用 Ado foreach 枚举器逐行读取记录集
  3. 在每个枚举器中,我都有一组变量来表示列
  4. 我将这些变量刷新到数据流任务中,该任务将 变量到使用派生列的列并将其推送到 ODBC 目标

显然这对我来说不起作用,当我运行包时,我总是收到消息“0 行已插入 ODBC 目标”。

说实话,我不确定如何解决这个问题。

非常感谢任何帮助!!!

提前致谢!!!

编辑:

PS:我不能在这里使用任何一次或 Power BI / Query 技巧。它必须是纯 SSIS。

【问题讨论】:

  • 在将此 excel 数据导出到数据库之前,您可以编写一个小的 vba 宏,该宏可以根据您所需的格式将数据重新排列到新工作表中,然后将该工作表直接导入该数据库.
  • 嗨,感谢您的评论,这是大量文件的一部分,这样的事情对我来说是不可行的
  • 你需要使用Script Component编写一个C#/VB脚本来实现这个逻辑。
  • 安装 ACE OLE/DB 驱动程序是不是一个选项microsoft.com/en-us/download/details.aspx?id=54920

标签: excel import ssis


【解决方案1】:

我会为此使用 Power Query。它内置于 Excel、Power BI 和 Power Automate 中,并且具有比 SSIS 数据流更灵活的数据转换。您可以使用“M”(Power Query 语言)进行编码,但我很少这样做 - UI 几乎可以满足您的任何需求。

例如,一旦你想出一个计算列来创建“column6”,它就有一个“向下填充”功能,可以将每个组的值向下推到详细的行上。

这将是我计算“column6”的方法:

  1. 数据功能区/来自表/范围。指定工作表和范围
  2. 在 Power Query 编辑器中,选择 [Column1],然后选择 Add Column / Extract / First Characters / 1
  3. 选择[第一个字符],然后转换/数据类型/整数
  4. 选择[第一个字符],然后替换值/替换错误/空
  5. 添加列/条件列,指定新列名 = "Column6",如果 Column1" 等于 "column1" 则 "null" Else If "Column1" 等于 "null" then (Select a column) [Column1 ] 否则为“空”
  6. 选择[Column6],然后变换/填充/向下

一旦您有一个有效的查询,您可以将 PQ 代码复制到 SSIS 的 PQ 源中:

https://docs.microsoft.com/en-us/sql/integration-services/data-flow/power-query-source

【讨论】:

    【解决方案2】:

    我能想到的解决方案,是通过脚本任务,在这些步骤中

    1. 从第 4 行读取 Excel 文件
    2. 为数据行添加名称的脚本任务
    3. 通过条件拆分删除列标题
    • 第一步打开 Excel 源属性,取消选择第一行中的列名,并将 OpenRowset 设置为从第四行读取 (Sheet1$A4:E):

    • 为第二步创建一个脚本组件转换。选择 5 列作为输入并创建一个新的输出变量(在本例中为名称)

    脚本本身:

    public class ScriptMain : UserComponent
    {
    
    
        string keepname;
        
        public override void Input0_ProcessInputRow(Input0Buffer Row)
        {
            if (Row.F5_IsNull)
                { keepname = Row.F1;
                
            }
            else
            {
                if (Row.F5 != "col5")
                {
                    Row.Name = keepname;
                }
    
            }
        }
        
    }
    

    解释:检查它是否是包含名称的行(col5 为空),如果是这样,它将名称保存到变量keepname。 如果不是这样,并且它不是标题(col1='col1'),则更新变量名称。

    • 最后一步只是通过条件拆分进行清理

    这样做的目的是拆分“名称行”或标题的行。你只需要携带一个默认输出。

    测试:

    【讨论】:

    • 我在读取工作表中的名字时遇到问题,其余部分按预期工作。我认为这是由于读取 ReadWrite 变量的限制,试图通过那个 rn
    • 当我测试时,我创建了 Name 作为输出变量,而不是读写。您是否收到错误消息或我们可以提供帮助的信息?
    • 可能发生的情况是,F5 在名字中不为空,您可以在 excel 源和脚本组件之间添加启用数据查看器以检查脚本正在接收什么
    • 当您说输出变量时,您的意思是输出列,对吗?我使用的条件是 DateTime.TryParse ,如果它是真的那么它是数据,否则它是名称
    • 我的意思是我在脚本组件本身中创建了它,如第二个屏幕截图所示,在输入输出选项卡中
    【解决方案3】:

    我认为导入此类文件的最佳方法是制作一个脚本任务,将 Excel 文件转换为 CSV,然后将 CSV 作为简单的平面文件源上传到数据库中。

    1. 使用 Excel 文件的路径创建两个名为 VarDataPath 的变量,使用 CSV 生成的文件的路径创建 VarCSVPath
    2. 使用以下 VB.net sn-p 创建脚本任务。不幸的是,我的计算机上目前没有 SSIS,所以我无法尝试我的代码。

    进口系统 导入 System.Data 导入 System.Math 导入 Microsoft.SqlServer.Dts.Runtime

    公共类ScriptMain

    Public Sub Main()
    
        Dim xl As Object
        Dim wb As Object
        Dim sh As Object
        Dim NumSheets As Integer
    
        Dim counter As Long
    
        Dim fs As Object
        Dim conv_file As Object
        Dim line As String
    
        Dim strDataPath As String = Dts.Variables("VarDataPath").Value.ToString() 'This variable contains the Excel path
        Dim strFileName As String = Dts.Variables("VarCSVPath").Value.ToString() 'This variable contains the CSV path
    
        Dim myArray As Integer() = New Integer() {4, 10, 16} ' Row number of FirstName/LastName
    
        xl = CreateObject("Excel.Application")
        wb = xl.WorkBooks.Open(strDataPath)
        sh = wb.Sheets(1)
    
        fs = CreateObject("Scripting.FileSystemObject")
        conv_file = fs.CreateTextFile(strFileName, True)
    
        ' CSV file head
        conv_file.writeline("Name,Col1,Col2,Col3,Col4,Col5")
    
        For Each val In myArray
        For a = 2 To 5 ' I have to loop all 4 rows of tables starting from 2 rows down the FirstName/LastName cell
        ' Each line I wrote valeu of Name,Col1,Col2,Col3,Col4,Col5
                line = ""
                line=line & sh.Cells(val, 1).ToString & ";" 'Name
                line=line & sh.Cells(val+a, 1).ToString & ";" 'Col1
                line=line & sh.Cells(val+a, 2).ToString & ";" 'Col2
                line=line & sh.Cells(val+a, 3).ToString & ";" 'Col3
                line=line & sh.Cells(val+a, 4).ToString & ";" 'Col4
                line=line & sh.Cells(val+a, 5).ToString & ";" 'Col5
                conv_file.writeline(line)
            Next
        Next
        
        
        conv_file.close()
    
        sh = Nothing
        wb.Close(False)
        wb = Nothing
        xl.Quit()
        xl = Nothing
    
        Dts.TaskResult = Dts.Results.Success
    End Sub
    

    结束类

    1. 执行包,让 SSIS 创建一个 CSV 文件。
    2. 在包中添加数据流,将生成的 CSV 上传到数据库中。

    另外,你可以看看这些文章:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多