【问题标题】:Import data from Excel using SSIS without knowing sheet name在不知道工作表名称的情况下使用 SSIS 从 Excel 导入数据
【发布时间】:2010-12-14 20:58:20
【问题描述】:

我有一个由另一台服务器更新的电子表格(我无法控制),我需要自动将该数据导入 SQL 2005。数据始终是电子表格的第一页。但是,该工作表的名称会根据行数而变化。

有没有办法在事先不知道工作表名称的情况下运行从 Excel 中提取数据的 SSIS 作业?它似乎依赖工作表名称作为数据源,但我希望告诉它“工作表编号 1”或类似的东西。

【问题讨论】:

  • 能否查询Excel文件中的“表格”(工作表),然后只使用第一个?
  • 好主意,但知道该怎么做吗?

标签: sql excel ssis


【解决方案1】:

我会将工作表名称编写成 SSIS 用户变量。如果你不反对在你的 SSIS 包中插入一个脚本任务试试这个:(基于link text

Excel.Application xlApp = new Excel.ApplicationClass();
Excel.Workbook xlWorkBook = xlApp.Workbooks.Open("<Name of your excel app>.xls", 0, xlWorkBook true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
// Look up worksheet by index
Excel.Worksheet xlWorkSheet =(Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

user::worksheetname = xlWorkSheet.Name;

/* Do clean up.  Working with COM object */

【讨论】:

  • 在我看来这是最好的选择,如果我不得不再次解决这个问题,我会先尝试这条路线。谢谢阿达玛!不过,我正在工作的项目已经使用了 UI 自动化,所以我最终只是附加了一个脚本来自动更改名称。
  • 更新:我在这里找到了我的 Excel 参考:C:\Program Files (x86)\Microsoft Visual Studio 11.0\Visual Studio Tools for Office\PIA\Office14\Microsoft.Office.Interop.Excel.dll .如何获得对“Excel.Application”的引用?我需要添加 DLL 引用吗?我正在运行安装了“Microsoft Access Database Engine 2010 Redistributable”的 64 位 Excel,以允许我在 SSIS 中使用 Excel 源代码。
  • 上面代码中的 Open 方法中似乎还有一个杂散的“xlWorkBook”值。
【解决方案2】:

仅作记录,我在脚本任务中使用此代码来解决问题。使用的变量有:文件名SheetName

请注意,我的 Excel 文件名是动态的。

// GET NAME OF FIRST SHEET
string filename = (string)Dts.Variables["Filename"].Value;
string sheetName = null;

string connStr =
    String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"EXCEL 8.0;IMEX=1;\"", filename);

var conn = new OleDbConnection(connStr);
try 
{           
    conn.Open();

    using(var dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null))
    {
        var row0 = dtSheet.Rows[0];
        sheetName = row0["TABLE_NAME"].ToString();
    }
}
catch (Exception)
{
    throw;
}
finally
{
    conn.Close();
    conn.Dispose();
}

if (!String.IsNullOrEmpty(sheetName))
{
    Dts.Variables["SheetName"].Value = sheetName;
    Dts.Events.FireInformation(1, "User::SheetName", sheetName, "", 0, ref dummy);
    Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
    Dts.Events.FireError(0, "User::SheetName", "No SheetName found!", String.Empty, 0);
    Dts.TaskResult = (int)ScriptResults.Failure;
}

【讨论】:

    【解决方案3】:

    我遇到了类似的问题。我实现的解决方案是首先使用 OleDB 连接读取 excel 文件。打开连接,然后检索所有工作表名称。这是一个例子

    Dim strConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\ABC.xls;Extended Properties=""EXCEL 8.0;"""
    
    Dim lstSheetName As List(Of String) = Nothing
    Try
     objConn = New OleDbConnection(Me.ConnectionString)
     objConn.Open()
     lstSheetName = New List(Of String)
     Using dtSheetTable As DataTable =       objConn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,Nothing)
    
      For Each drRow As DataRow In dtSheetTable.Rows
         lstSheetName.Add("[" & drRow("TABLE_NAME").ToString().Replace("'", "''") & "]")
      Next
     End Using
    Catch ex as Exception
     Throw
    Finally
     If objConn.State = ConnectionState.Open Then objConn.Close()
     objConn.Dispose()
    End Try
    

    所有代码都是用 ASPX.VB 编写的,然后我通过后面的代码执行 SSIS 包,并在 lstSheetName 变量 (lstSheetName(0).ToString()) 中传递第一个值

    这是

    【讨论】:

      【解决方案4】:

      如果有人在使用 JET 驱动程序时遇到问题,您现在可以使用 AccessDatabase 驱动程序。这是从上面改编的,并且经过验证可以在我的机器上运行,不需要额外的参考。

      using System;
      using System.Data;
      using Microsoft.SqlServer.Dts.Runtime;
      using System.Windows.Forms;
      using System.Data.OleDb;
      
          public void Main()
          {
              // GET NAME OF FIRST SHEET
              string filename = Dts.Variables["User::ActiveFileName"].Value.ToString();
              string sheetName = null;
              bool dummy = true;
      
              string connStr =
                  String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"EXCEL 12.0 XML;HDR=YES\";", filename);
              var conn = new OleDbConnection(connStr);
              try
              {
                  conn.Open();
      
                  using(var dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null))
                  {
                      var row0 = dtSheet.Rows[0];
                      sheetName = row0["TABLE_NAME"].ToString();
                  }
      
                  if (!String.IsNullOrEmpty(sheetName))
                  {
                      Dts.Variables["SheetName"].Value = sheetName;
                      Dts.Events.FireInformation(1, "User::SheetName", sheetName, "", 0, ref dummy);
                      Dts.TaskResult = (int)ScriptResults.Success;
                  }
                  else
                  {
                      throw new Exception("No SheetName found!");
                  }
              }
              catch (Exception ex)
              {
                  Dts.Events.FireError(0, "User::SheetName", ex.Message, String.Empty, 0);
                  Dts.TaskResult = (int)ScriptResults.Failure;
              }
              finally
              {
                  conn.Close();
                  conn.Dispose();
              }
          }
      

      【讨论】:

        【解决方案5】:

        我不这么认为...我不知道任何可以使用的序数引用语法,例如 Sheets[0]。

        因此,如果您在不知道工作表名称的情况下无法获取数据 - 您只需要动态找出工作表名称即可。 getting Excel schema info in SSIS 上的这个链接应该可以帮助你做到这一点。一旦你有了它,你就可以将工作表名称作为变量传递,然后就可以走了。

        【讨论】:

          【解决方案6】:

          我自己过去也遇到过同样的问题,并且无法找到解决方案来读取 Excel 文件,该文件的工作表名称会因文件而异。

          我无法开始工作的猜测是在数据连接的属性中使用表达式。您需要以某种方式将工作表名称读入变量,然后将该变量的结果用于数据连接的工作表名称。

          祝你好运,很抱歉我无法提供更多帮助。

          【讨论】:

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