2009-07-13 13 views
23

Je copie d'un extrait de code VBA de MSDN qui me montre comment saisir les résultats d'une requête SQL en feuille Excel (Excel 2007):Accéder à la base de données SQL dans Excel VBA

Sub GetDataFromADO() 

    'Declare variables' 
     Set objMyConn = New ADODB.Connection 
     Set objMyCmd = New ADODB.Command 
     Set objMyRecordset = New ADODB.Recordset 

    'Open Connection' 
     objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;User ID=abc;Password=abc;" 
     objMyConn.Open 

    'Set and Excecute SQL Command' 
     Set objMyCmd.ActiveConnection = objMyConn 
     objMyCmd.CommandText = "select * from myTable" 
     objMyCmd.CommandType = adCmdText 
     objMyCmd.Execute 

    'Open Recordset' 
     Set objMyRecordset.ActiveConnection = objMyConn 
     objMyRecordset.Open objMyCmd 

    'Copy Data to Excel' 
     ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset) 

End Sub 

Je l'ai déjà ajouté Microsoft Bibliothèque ActiveX Data Objects 2.1 sous comme référence. Et cette base de données est accessible.

Maintenant, quand je lance ce sous-programme, il a une erreur:

Erreur d'exécution 3704: l'opération n'est pas autorisée lorsque l'objet est fermé.

Sur la déclaration:

ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset) 

Toute idée pourquoi?

Merci.

+0

Aide! J'ai la même erreur, mais les solutions ci-dessous n'ont pas aidé: http://stackoverflow.com/questions/1682717/vba-adodb-run-time-error-3704 – Steven

Répondre

20

J'ai ajouté le catalogue initial à votre chaîne de connexion. J'ai également abandonné la syntaxe ADODB.Command en faveur de simplement créer ma propre instruction SQL et ouvrir le jeu d'enregistrements sur cette variable.

Espérons que cela aide.

Sub GetDataFromADO() 
    'Declare variables' 
     Set objMyConn = New ADODB.Connection 
     Set objMyRecordset = New ADODB.Recordset 
     Dim strSQL As String 

    'Open Connection' 
     objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=MyDatabase;User ID=abc;Password=abc;" 
     objMyConn.Open 

    'Set and Excecute SQL Command' 
     strSQL = "select * from myTable" 

    'Open Recordset' 
     Set objMyRecordset.ActiveConnection = objMyConn 
     objMyRecordset.Open strSQL    

    'Copy Data to Excel' 
     ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset) 

End Sub 
+2

Cela a fonctionné pour moi, merci, n'oubliez pas d'ajouter la référence à Microsoft ActiveX Data Objects 2.1, j'ai ajouté la version 2.6 cependant. N'avez-vous pas besoin de fermer la connexion à la fin? comme objMyRecordset.Close? –

0

Est-ce une bonne chaîne de connexion?
Où se trouve l'instance SQL Server?

Vous devrez vérifier que vous êtes en mesure de vous connecter à SQL Server à l'aide de la chaîne de connexion spécifiée ci-dessus.

EDIT: Regardez la propriété State du jeu d'enregistrements pour voir si elle est Open?
De même, remplacez la propriété CursorLocation par adUseClient avant d'ouvrir le jeu d'enregistrements.

1

Je suis assis devant un ordinateur sans aucun des logiciels concernés, mais de la mémoire ce code me semble incorrect. Vous exécutez la commande mais en ignorant les RecordSet retours objMyCommand.Execute.

Je ferais:

Set objMyRecordset = objMyCommand.Execute 

... puis perdre la partie "ouverte recordset".

15

changements suggérés:

  • Ne pas appeler l'objet Command Execute méthode;
  • Définissez la propriété Source de l'objet Recordset comme votre objet Command;
  • Appel de la méthode Open de l'objet Recordset sans paramètre;
  • Supprimez les parenthèses autour de l'objet Recordset dans l'appel à CopyFromRecordset;
  • En fait, les variables :) Déclarez vos

Code révisé:

Sub GetDataFromADO() 

    'Declare variables' 
     Dim objMyConn As ADODB.Connection 
     Dim objMyCmd As ADODB.Command 
     Dim objMyRecordset As ADODB.Recordset 

     Set objMyConn = New ADODB.Connection 
     Set objMyCmd = New ADODB.Command 
     Set objMyRecordset = New ADODB.Recordset 

    'Open Connection' 
     objMyConn.ConnectionString = "Provider=SQLOLEDB;Data Source=localhost;User ID=abc;Password=abc;"  
     objMyConn.Open 

    'Set and Excecute SQL Command' 
     Set objMyCmd.ActiveConnection = objMyConn 
     objMyCmd.CommandText = "select * from mytable" 
     objMyCmd.CommandType = adCmdText 

    'Open Recordset' 
     Set objMyRecordset.Source = objMyCmd 
     objMyRecordset.Open 

    'Copy Data to Excel' 
     ActiveSheet.Range("A1").CopyFromRecordset objMyRecordset 

End Sub 
+0

+1 pour supprimer les parenthèses. Les parenthèses inutiles combinées avec des références d'objet semblent causer des erreurs VBA étranges – barrowc

+0

Cet exemple a fonctionné pour moi, merci! – nekomatic

+0

Je réalise qu'il s'agit d'un ancien thread - mais je me demandais s'il y avait un moyen de modifier le code ci-dessus pour récupérer les en-têtes de table aussi bien? – firedrawndagger

0

Ajouter set nocount on au début de la procédure stockée (si vous êtes sur SQL Server). Je viens de résoudre ce problème dans mon propre travail et il a été causé par des résultats intermédiaires, tels que "1203 Rows Affected", étant chargé dans le Recordset que j'essayais d'utiliser.

0

@firedrawndagger: à la liste des noms de champs/têtes de colonne itérer à travers la collection Les champs et recordset insérer le nom:

Dim myRS as ADODB.Recordset 
Dim fld as Field 
Dim strFieldName as String 

For Each fld in myRS.Fields 
    Activesheet.Selection = fld.Name 
    [Some code that moves to next column] 
Next 
Questions connexes