2009-07-13 18 views
23

ja skopiowanie fragmentu kodu VBA z MSDN, który pokazuje mi jak chwycić wyników z zapytania SQL do arkusza Excel (Excel 2007):Dostęp do bazy danych SQL w programie 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 

już dodane Microsoft Obiekty ActiveX Data Objects 2.1 jako odniesienie. I ta baza danych jest dostępna.

Teraz, kiedy uruchomić ten podprogram, że ma błąd:

Run-time error 3704: Operacja nie jest dozwolona, ​​gdy obiekt jest zamknięty.

Na rachunku:

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

Każdy pomysł dlaczego?

Dzięki.

+0

Pomoc! Mam ten sam błąd, ale poniższe rozwiązania nie pomogły: http://stackoverflow.com/questions/1682717/vba-adodb-run-time-error-3704 – Steven

Odpowiedz

20

Dodałem katalog początkowy do ciągu połączenia. Opuściłem również składnię ADODB.Command na rzecz prostego utworzenia własnego polecenia SQL i otwarcia zestawu rekordów dla tej zmiennej.

Mam nadzieję, że to pomoże.

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

To zadziałało dla mnie, dzięki, pamiętaj, aby dodać w odniesieniu do Microsoft ActiveX Data Objects 2.1, dodałem jednak wersję 2.6. Nie musisz też zamykać połączenia na końcu? jak objMyRecordset.Close? –

0

Czy to jest właściwy ciąg połączenia?
Gdzie znajduje się instancja serwera SQL?

Należy sprawdzić, czy możliwe jest połączenie z serwerem SQL przy użyciu ciągu połączenia określonego powyżej.

EDYCJA: Sprawdź właściwość State zestawu rekordów, aby sprawdzić, czy jest otwarta?
Zmień także właściwość CursorLocation na adUseClient przed otwarciem zestawu rekordów.

1

Siedzę przy komputerze bez żadnych istotnych fragmentów oprogramowania, ale z pamięci ten kod wygląda źle. Wykonujesz polecenie, ale odrzucasz , które zwraca.

zrobiłbym:

Set objMyRecordset = objMyCommand.Execute 

... a potem stracić "otwarte" część zestawu rekordów.

15

Proponowane zmiany:

  • Nie wywoływać sprzeciw Command na Execute metody;
  • Ustaw właściwość Źródło obiektu Zestaw rekordów jako obiekt polecenia;
  • Wywołaj metodę Open obiektu Recordset bez parametrów;
  • Usuń nawiasy z obiektu Recordset w wywołaniu do CopyFromRecordset;
  • Właściwie zadeklarować zmienne :)

Poprawiony kod:

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 do usuwania nawiasów. Niepotrzebne nawiasy połączone z odwołaniami do obiektów wydają się powodować dziwne błędy VBA. – barrowc

+0

Ten przykład zadziałał dla mnie, dzięki! – nekomatic

+0

Rozumiem, że jest to stary wątek - ale zastanawiałem się, czy istnieje sposób modyfikacji powyższego kodu w celu pobrania nagłówków tabeli? – firedrawndagger

0

Dodaj set nocount on do początku przechowywanych proc (jeśli jesteś na SQL Server). Właśnie rozwiązałem ten problem w mojej pracy i było to spowodowane pośrednimi wynikami, takimi jak "1203 Rows Affected", ładowanie do Recordset próbowałem użyć.

0

@firedrawndagger: notować nazwy pól/nagłówki kolumn iterację rekordów Fields kolekcji i wstawić nazwę:

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 
Powiązane problemy