2009-07-13 16 views
23

Ich bin Kopieren einen VBA-Code-Snippet von MSDN, das mir zeigt, wie Ergebnisse aus einer SQL-Abfrage in Excel-Tabelle (Excel 2007) greifen:Zugriff auf SQL-Datenbank in 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 

Ich habe bereits Microsoft hinzugefügt ActiveX Data Objects 2.1-Bibliothek als Referenz. Und diese Datenbank ist zugänglich.

Nun, wenn ich diese Unterroutine ausführen, hat es einen Fehler:

Laufzeitfehler 3704: Operation ist nicht erlaubt, wenn das Objekt geschlossen ist.

Auf der Aussage:

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

Jede Idee, warum?

Danke.

+0

Hilfe! Ich habe den gleichen Fehler, aber die folgenden Lösungen haben nicht geholfen: http://stackoverflow.com/questions/1682717/vba-adodb-run-time-error-3704 – Steven

Antwort

20

Ich habe den ersten Katalog zu Ihrer Verbindungszeichenfolge hinzugefügt. Ich habe auch die ADODB.Command-Syntax aufgegeben, um einfach meine eigene SQL-Anweisung zu erstellen und das Recordset für diese Variable zu öffnen.

Hoffe, das hilft.

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

Es funktionierte für mich, danke, daran zu erinnern, hinzuzufügen Als Verweis auf Microsoft ActiveX Data Objects 2.1 habe ich die Version 2.6 hinzugefügt. Müssen Sie die Verbindung am Ende auch nicht schließen? wie objMyRecordset.Close? –

0

Ist das eine richtige Verbindungszeichenfolge?
Wo befindet sich die SQL Server-Instanz?

Sie müssen sicherstellen, dass Sie mit der oben angegebenen Verbindungszeichenfolge eine Verbindung zu SQL Server herstellen können.

EDIT: Schauen Sie sich die State-Eigenschaft des Recordsets an, um zu sehen, ob es offen ist?
Ändern Sie auch die CursorLocation-Eigenschaft in AdUseClient, bevor Sie das Recordset öffnen.

1

Ich sitze an einem Computer mit keiner der relevanten Bits der Software, aber aus dem Speicher dieser Code sieht falsch aus. Sie führen den Befehl aus, verwerfen jedoch die RecordSet, die objMyCommand.Execute zurückgibt.

ich tun würde:

Set objMyRecordset = objMyCommand.Execute 

... und dann verlieren die "offene Cord-" -Teil.

15

Vorgeschlagene Änderungen:

  • Sie den Befehl Objekt der Execute-Methode nicht aufrufen;
  • Legen Sie die Source-Eigenschaft des Recordset-Objekts als Ihr Befehlsobjekt fest;
  • Rufen Sie die Open-Methode des Recordset-Objekts ohne Parameter auf;
  • Entfernen Sie die Klammern um das Recordset-Objekt in dem Aufruf an CopyFromRecordset;
  • Eigentlich Ihre Variablen deklarieren :)

Revised Code:

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 zum Entfernen der Klammern. Unnötige Klammern kombiniert mit Objektreferenzen scheinen seltsame VBA-Fehler zu verursachen – barrowc

+0

Dieses Beispiel funktionierte für mich, danke! – nekomatic

+0

Ich weiß, dass dies ein alter Thread ist - aber ich frage mich, ob es eine Möglichkeit gibt, den obigen Code zu modifizieren, um auch die Tabellenköpfe abzurufen. – firedrawndagger

0

hinzufügen set nocount on zu Beginn des gespeicherten proc (wenn Sie auf SQL Server sind). Ich habe gerade dieses Problem in meiner eigenen Arbeit gelöst und es wurde durch Zwischenergebnisse, wie "1203 Rows Affected" verursacht, in die Recordset geladen wurde, die ich versuchte zu verwenden.

0

@firedrawndagger: Feldnamen zur Liste/Spaltenüberschriften durchlaufen die Datensatzfelder Sammlung und fügen Sie den Namen:

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