web-dev-qa-db-fra.com

Accès à la base de données SQL dans Excel-VBA

Je copie un extrait de code VBA de MSDN qui me montre comment récupérer les résultats d'une requête SQL dans une feuille Excel (Excel 2007):

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

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

Maintenant, quand j'exécute 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)

Une idée pourquoi?

Merci.

26
Saobi

J'ai ajouté le catalogue initial à votre chaîne de connexion. J'ai également abandonné la syntaxe ADODB.Command au profit de la création simple de ma propre instruction SQL et de l'ouverture du jeu d'enregistrements sur cette variable.

J'espère que cela t'aides.

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
25
David Walker

Modifications suggérées:

  • N'appelez pas la méthode Execute de l'objet Command;
  • Définissez la propriété Source de l'objet Recordset comme votre objet Command;
  • Appelez la méthode Open de l'objet Recordset sans paramètres;
  • Supprimez les parenthèses autour de l'objet Recordset dans l'appel à CopyFromRecordset;
  • Déclarez réellement vos variables :)

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
16
onedaywhen

Je suis assis devant un ordinateur sans aucun des logiciels pertinents, mais de mémoire, ce code semble incorrect. Vous exécutez la commande mais jetez le RecordSet that objMyCommand.Execute résultats.

Je ferais:

Set objMyRecordset = objMyCommand.Execute

... puis perdez la partie "jeu d'enregistrements ouvert".

1
Gary McGill

@firedrawndagger: pour répertorier les noms de champ/en-têtes de colonne, parcourez la collection Fields du jeu d'enregistrements et insérez 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
0
Jock

Ajouter set nocount on au début du processus stocké (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", en cours de chargement dans le Recordset que j'essayais d'utiliser.

0
ecounysis

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

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

EDIT: regardez la propriété State du jeu d'enregistrements pour voir si elle est ouverte?
Modifiez également la propriété CursorLocation en adUseClient avant d'ouvrir le jeu d'enregistrements.

0
shahkalpesh