J'ai une feuille de calcul mise à jour par un autre serveur (hors de ma commande) et je dois automatiser cette donnée dans SQL 2005. Les données sont toujours la première page de la feuille de calcul. Cependant, le nom de cette feuille change en fonction du nombre de lignes. P>
Y a-t-il un moyen d'exécuter un travail SSIS qui tire dans des données d'Excel sans connaître le nom de la feuille à l'avance? Il semble fier sur le nom de la feuille comme source de données, mais je cherche à le dire "Numéro de feuille 1" ou quelque chose de similaire. P>
6 Réponses :
Je ne pense pas non plus ... Je ne connais aucune syntaxe de référence ordinale, par exemple des fiches [0] que vous pourriez utiliser. p>
Donc, si vous ne pouvez pas obtenir les données sans connaître le nom de la feuille - il vous suffit de trouver dynamiquement le nom de la feuille. Ce lien sur Obtenir une info Excel Schema dans SSIS devrait vous aider à faire cela. Une fois que vous aurez cela, vous pouvez transmettre le nom de la feuille en tant que variable, puis vous allez. P>
J'ai eu ce même problème moi-même dans le passé et je n'ai pas pu trouver une solution pour que le fichier Excel soit lu dans lequel son nom de feuille change du fichier au fichier. p>
Mon devinez, que je n'ai pas pu arriver au travail, serait d'utiliser des expressions dans les propriétés de la connexion de données. Vous auriez besoin de lire le nom de la feuille dans une variable, puis utilisez la variable résultant du nom de la feuille pour la connexion de données. P>
meilleure de la chance à vous et désolé, je ne pouvais pas être d'aide plus d'aide. P>
Je scriperais le nom de la feuille de calcul à une variable utilisateur SSIS. Si vous n'êtes pas opposé à l'insérer une tâche de script dans votre package SSIS, essayez ceci: (basé sur Texte de liaison )
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 */
C'est la meilleure option à mon avis et si je devais aborder ce problème, j'essaierais d'abord cet itinéraire. Merci Adama! Le projet que je travaillais déjà utilisait l'automatisation de l'UI, cependant, j'ai fini donc à ajouter un script pour automatiser le nom du nom.
Mise à jour: J'ai trouvé ma référence Excel ici: C: \ Fichiers de programme (X86) \ Microsoft Visual Studio 11.0 \ Visual Studio Tools pour Office \ Pia \ Office14 \ Microsoft.Office.interop.excel.dll. Comment puis-je faire référence à "Excel.application"? Dois-je besoin d'ajouter une référence de DLL? Je cours 64 bits Excel avec le "Moteur de base de données Microsoft Access 2010 Redistributable" installé pour me permettre d'utiliser Excel Source dans SSIS.
Il semble également y avoir une valeur erronée "xlworkbook" dans la méthode ouverte dans votre code ci-dessus.
J'ai eu un problème similaire. La solution que j'ai implémentée a été d'abord lu le fichier Excel à l'aide de la connexion OLEDB. Ouvrez la connexion puis récupérez toutes les noms de feuille. Voici un exemple
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
Juste pour l'enregistrement, j'utilise ce code dans la tâche de script pour résoudre le problème. Les variables utilisées sont les suivantes: nom de fichier em>, la feuille em>. Notez que mon nom de fichier Excel est dynamique. P> // 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;
}
Si quelqu'un a des problèmes avec le pilote Jet, vous pouvez utiliser les pilotes AccessDatabase maintenant. Ceci a été adapté d'en haut et est vérifié sur ma machine, aucune référence supplémentaire n'est nécessaire pour cela.
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(); } }
Pouvez-vous interroger pour les "tables" (feuilles) dans le fichier Excel, puis utilisez simplement le premier?
Bonne pensée, mais aucune idée de comment faire ça?