在不知道工作表名称的情况下使用 SSIS 从 Excel 导入数据
Posted
技术标签:
【中文标题】在不知道工作表名称的情况下使用 SSIS 从 Excel 导入数据【英文标题】:Import data from Excel using SSIS without knowing sheet name 【发布时间】:2010-12-14 20:58:20 【问题描述】:我有一个由另一台服务器更新的电子表格(我无法控制),我需要自动将该数据导入 SQL 2005。数据始终是电子表格的第一页。但是,该工作表的名称会根据行数而变化。
有没有办法在事先不知道工作表名称的情况下运行从 Excel 中提取数据的 SSIS 作业?它似乎依赖工作表名称作为数据源,但我希望告诉它“工作表编号 1”或类似的东西。
【问题讨论】:
能否查询Excel文件中的“表格”(工作表),然后只使用第一个? 好主意,但知道该怎么做吗? 【参考方案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 文件,该文件的工作表名称会因文件而异。
我无法开始工作的猜测是在数据连接的属性中使用表达式。您需要以某种方式将工作表名称读入变量,然后将该变量的结果用于数据连接的工作表名称。
祝你好运,很抱歉我无法提供更多帮助。
【讨论】:
以上是关于在不知道工作表名称的情况下使用 SSIS 从 Excel 导入数据的主要内容,如果未能解决你的问题,请参考以下文章