2010-12-14 107 views
7

J'ai une feuille de calcul mise à jour par un autre serveur (hors de mon contrôle) et j'ai besoin d'automatiser l'importation de ces données dans SQL 2005. Les données sont toujours la première page du tableur. Cependant, le nom de cette feuille change en fonction du nombre de lignes.Importer des données depuis Excel en utilisant SSIS sans connaître le nom de la feuille

Existe-t-il un moyen d'exécuter un travail SSIS qui extrait des données d'Excel sans connaître le nom de la feuille au préalable? Il semble s'appuyer sur le nom de la feuille comme source de données, mais je cherche à lui dire "feuille numéro 1" ou quelque chose de similaire.

+0

Pouvez-vous faire une requête pour les "tables" (feuilles) dans le fichier Excel et ensuite utiliser le premier? – Gabe

+0

Bonne pensée, mais aucune idée de comment faire cela? –

Répondre

5

J'écrirais le nom de la feuille de calcul dans une variable utilisateur SSIS. Si vous n'êtes pas opposé à l'insertion d'une tâche de script dans votre package SSIS essayez ceci: (Basé sur 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 */ 
+0

C'est la meilleure option à mon avis, et si je devais aborder à nouveau ce problème, j'essaierais d'abord cette route. Merci AdamA! Le projet que je travaillais utilisait déjà l'automatisation de l'interface utilisateur, alors j'ai fini par ajouter un script pour automatiser la modification du nom. –

+0

Mise à jour: J'ai trouvé ma référence Excel ici: C: \ Program Files (x86) \ Microsoft Visual Studio 11.0 \ Outils Visual Studio pour Office \ PIA \ Office14 \ Microsoft.Office.Interop.Excel.dll. Comment obtenir une référence à "Excel.Application"? Ai-je besoin d'ajouter une référence DLL? Je cours 64 bits Excel avec le "Microsoft Access Database Engine 2010 redistribuable" installé pour me permettre d'utiliser la source Excel dans SSIS. – PeterX

+1

Il semble également y avoir une valeur erronnée "xlWorkBook" dans la méthode Open dans votre code ci-dessus. – PeterX

1

Je ne pense pas ... Je ne connais pas de syntaxe de référence ordinale, par exemple, Sheets [0] que vous pourriez utiliser. Par conséquent, si vous ne pouvez pas obtenir les données sans connaître le nom de la feuille, il vous suffit de rechercher dynamiquement le nom de la feuille. Ce lien sur getting Excel schema info in SSIS devrait vous aider à le faire. Une fois que vous avez cela, vous pouvez passer le nom de la feuille dans une variable, et vous partez.

1

J'ai moi-même eu ce même problème par le passé et je n'ai pas trouvé de solution permettant de lire un fichier Excel dans lequel son nom de feuille change de fichier en fichier.

Ma proposition, que je n'ai pas réussi à obtenir, consisterait à utiliser des expressions dans les propriétés de la connexion de données. Vous devez lire le nom de la feuille dans une variable, puis utiliser le résultat de cette variable dans le nom de la feuille pour la connexion de données.

Bonne chance à vous, et désolé je ne pourrais pas être plus utile.

3

J'ai eu un problème similaire. La solution que j'ai implémentée a d'abord été lue le fichier Excel en utilisant la connexion OleDB. Ouvrez la connexion, puis récupérez tous 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 

Ce tout le code est écrit ASPX.VB puis j'exécute le package SSIS par le code derrière et en passant la première valeur de la variable lstSheetName (lstSheetName(0).ToString())

Ce fut

4

Juste pour l'enregistrement, j'utilise ce code dans Script Task pour résoudre le problème. Les variables utilisées sont les suivantes: Nom de fichier, SheetName.

Notez que mon nom de fichier Excel est dynamique.

// 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; 
} 
+0

Cela m'a aidé, merci! – KathyBlue

1

Si quelqu'un a des problèmes avec le pilote JET, vous pouvez utiliser les pilotes AccessDatabase maintenant. Cela a été adapté d'en haut et est vérifié en travaillant 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(); 
     } 
    }