2009-09-24 11 views
2

J'ai du mal à trouver un moyen d'obtenir et de modifier et d'exceler la connexion au classeur 2007 (Menu Données -> Connexions existantes -> Connexions sur ce classeur) .C'est une connexion (plusieurs en fait) à un serveur SQL et utilisé dans un tableau croisé dynamique.VSTO 3.0 Obtenir/modifier une connexion de classeur Excel 2007

J'ai essayé d'utiliser Application.ActiveWorkbook.Connections ou Globals.ThisWorkbook.Connections mais ils reviennent toujours à la fois Null..I've a essayé dans un événement de feuille ainsi que dans le cas de bouton d'un ruban personnalisé comme bien.

La seule voie de gauche, je peux penser est utilisé pour coder une méthode VBA qui fait le travail et l'invoquer dans mon code VSTO, mais ce n'est pas très élégant est-il ...

Répondre

0

Je ne peux pas rappelez-vous où, mais je me souviens avoir lu quelque part que la collection Connections était d'une utilité limitée pour l'écriture de connexions de type ODBC. Il a plusieurs valeurs enum pour une "connexion" mais je ne suis pas sûr si certaines d'entre elles sont en lecture seule depuis cette interface. Quoi qu'il en soit, il devrait être assez facile d'implémenter de nouvelles connexions et d'éditer celles existantes à partir de VSTO. La meilleure option serait à use COM interop to call le SQLConfigDataSource() function de la bibliothèque OD32 de ODBCCP32.DLL. Consultez également the following addin, ce qui facilite l'utilisation des tables de requêtes dans Excel.

2

Les connexions existantes dans Excel (cela fonctionne en 2007) ne sont pas des connexions actives. Vous devez vous connecter en utilisant une connexion existante avant de pouvoir acquérir cette connexion (je l'ai fait manuellement avant de cliquer sur un bouton qui a exécuté ce code).

var application = Globals.ThisAddIn.Application; 
//This must be an active connection otherwise handle exceptions 
// such as 'Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))' 
var connection = application.ActiveWorkbook.Connections["EXISTING_CONNECTION_NAME"]; 
var oledb = connection.OLEDBConnection; 
var settings = oledb.Connection; 
1

Ici, j'ajuste la chaîne de connexion d'Excel Connections. Prenez en compte que je n'ai qu'une seule connexion dans le classeur.

public class WorkbookConnectionsManager 
{ 
    public static void AdjustConnectionToSqlConnectionString(Excel.WorkbookConnection connection, String connectionString) 
    { 
    char[] propertiesSeparator = new char[] { ';' }; 
    char[] propertyValueSeparator = new char[] { '=' }; 

    Excel.OLEDBConnection oleDbConn = connection.OLEDBConnection; 

    Dictionary<string, string> dictExcelConnStrProperties = GetConnStrDictionary(oleDbConn.Connection, propertiesSeparator, propertyValueSeparator); 
    Dictionary<string, string> dictActualConnStrProperties = GetConnStrDictionary(connectionString, propertiesSeparator, propertyValueSeparator); 

    string[] reggedPropertyies = new string[] { "Integrated Security", "Persist Security Info", "User ID", "Password", "Initial Catalog", "Data Source", "Workstation ID" }; 

    foreach (string property in reggedPropertyies) 
     if (dictExcelConnStrProperties.ContainsKey(property) && dictActualConnStrProperties.ContainsKey(property) 
     && null != dictActualConnStrProperties[property] && !String.IsNullOrEmpty(dictActualConnStrProperties[property].ToString())) 
      dictExcelConnStrProperties[property] = dictActualConnStrProperties[property]; 

    string connStr = GetConnStrFromDict(dictExcelConnStrProperties, propertiesSeparator[0], propertyValueSeparator[0]); 

    oleDbConn.Connection = connStr; 
    } 

    private static string GetConnStrFromDict(Dictionary<string, string> dictConnStrProperties, char propertiesSeparator, char propertyValueSeparator) 
    { 
    StringBuilder connStrBuilder = new StringBuilder(); 
    foreach (KeyValuePair<string, string> keyValuePair in dictConnStrProperties) 
    { 
     connStrBuilder.Append(keyValuePair.Key); 
     if (!String.IsNullOrEmpty(keyValuePair.Value)) 
     { 
     connStrBuilder.Append(propertyValueSeparator); 
     connStrBuilder.Append(keyValuePair.Value); 
     } 
     connStrBuilder.Append(propertiesSeparator); 
    } 

    string connStr = String.Empty; 
    if (connStrBuilder.Length > 1) 
    { 
     connStr = connStrBuilder.ToString(0, connStrBuilder.Length - 1); 
    } 

    return connStr; 
    } 

    private static Dictionary<string, string> GetConnStrDictionary(string connString, char[] propertiesSeparator, char[] propertyValueSeparator) 
    { 
    string[] keyAndValue; 

    string[] arrayConnStrProperties = connString.Split(propertiesSeparator); 
    Dictionary<string, string> dictConnStrProperties = new Dictionary<string, string>(); 
    foreach (string excelConnStrProperty in arrayConnStrProperties) 
    { 
     keyAndValue = excelConnStrProperty.Split(propertyValueSeparator); 
     if (keyAndValue.Length > 1) 
     { 
     dictConnStrProperties.Add(keyAndValue[0], keyAndValue[1]); 
     } 
     else if (keyAndValue.Length > 0) 
     { 
     //standalone attribute 
     dictConnStrProperties.Add(keyAndValue[0], String.Empty); 
     } 
    } 

    return dictConnStrProperties; 
    } 



} 
+0

Pourriez-vous envisager de formater le code un peu mieux la prochaine fois? J'ai fait du reformatage mais ce serait bien si ce n'était pas nécessaire. –

+0

@KonradViltersten votre édition a fait très peu pour améliorer la mise en forme du code. Je suis revenu à l'original. –

+0

@TomRedfern Je vais reculer la source pour voir à quoi ça ressemblait. Juste vous le faire savoir, il ne semble pas être un acte immature de "est-trop/n'est-pas!", Matie. Comme le code regarde maintenant (indépendamment de ce que mon reformatage contribue) il est à peine lisible. La langue n'est même pas reconnue ... Laissez-moi voir ce que nous pouvons faire à ce sujet. –

Questions connexes