Acessando banco de dados SQL em Excel-VBA
Pergunta
Estou copiando um trecho de código VBA do MSDN que me mostra como resultados da garra de uma consulta SQL em folha de 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
Eu já adicionou Microsoft ActiveX Data Objects 2.1 Library sob como uma referência. E esta base de dados é acessível.
Agora, quando eu executar este sub-rotina, que tem um erro:
Erro de tempo de 3704:. A operação não é permitida quando o objeto está fechado
Na declaração:
ActiveSheet.Range("A1").CopyFromRecordset (objMyRecordset)
Qualquer ideia porquê?
Graças.
Solução
Eu adicionei o catálogo inicial para a seqüência de conexão. Eu também abandonded a sintaxe ADODB.Command em favor de simplesmente criar a minha própria instrução SQL e abrir o conjunto de registos nessa variável.
Espero que isso ajude.
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
Outras dicas
As alterações sugeridas:
- não invocam o objeto de comando é Executar método;
- Defina a propriedade Fonte do objeto Recordset para ser seu objeto de comando;
- Invoke método Open do objeto Recordset sem parâmetros;
- Remover os parênteses em torno do objeto Recordset na chamada para
CopyFromRecordset
; - Na verdade declarar suas variáveis:)
código revisto:
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
Eu estou sentado em um computador com nenhum dos bits relevantes do software, mas a partir da memória que o código parece errado. Você está executando o comando, mas descartando a RecordSet
que objMyCommand.Execute
retornos.
Eu faria:
Set objMyRecordset = objMyCommand.Execute
... e depois perder a parte "aberta de registros".
Isso é uma seqüência de conexão adequada?
Onde está a instância do SQL Server localizado?
Você vai precisar para verificar se você é capaz de conenct ao SQL Server usando a seqüência de conexão, você especificado acima.
EDIT: Olhe para a propriedade do Estado do conjunto de registros para ver se ele é Open
?
Além disso, altere a propriedade CursorLocation para adUseClient antes de abrir o conjunto de registros.
Adicionar set nocount on
para o início do proc armazenado (se você estiver em SQL Server). Eu só resolveu este problema no meu próprio trabalho e foi causada por resultados intermediários, como "1203 Rows Affected"
, sendo carregado no Recordset
eu estava tentando utilização.
@firedrawndagger: lista de nomes de campos / cabeçalhos de coluna percorrer a coleção Fields de registros e inserir o nome:
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