Conectando o Excel a um banco de dados
Muitas vezes as planilhas ficam muito extensas com muitos dados, tornando
o carregamento da mesma muito demorado. Há outros casos em que a planilha
precisa ser acessada por mais de uma pessoa ao mesmo tempo. Para esses e
outros casos pode-se chegar à conclusão de que é melhor começar a guardar
os dados em um banco de dados.
o carregamento da mesma muito demorado. Há outros casos em que a planilha
precisa ser acessada por mais de uma pessoa ao mesmo tempo. Para esses e
outros casos pode-se chegar à conclusão de que é melhor começar a guardar
os dados em um banco de dados.
Há vários sistemas gerenciadores de bancos de dados (SGBDs) disponíveis
no mercado, alguns pagos e outros gratuitos. Entre os pagos há versões
gratuitas disponíveis, mas são limitadas e seu uso é mais para
aprendizado. Aqui utilizarei o SQL Server Express, que é uma versão
gratuita e limitada do SQL Server.
no mercado, alguns pagos e outros gratuitos. Entre os pagos há versões
gratuitas disponíveis, mas são limitadas e seu uso é mais para
aprendizado. Aqui utilizarei o SQL Server Express, que é uma versão
gratuita e limitada do SQL Server.
O primeiro passo é ir no editor de VBA, clicar no menu
Ferramentas e escolher a opção Referências. Uma janela se
abrirá e você deve habilitar a opção
Microsoft ActiveX Data Objects 2.8 Library (biblioteca de objetos
de dados ActiveX da Microsoft). Confira na imagem abaixo:
Ferramentas e escolher a opção Referências. Uma janela se
abrirá e você deve habilitar a opção
Microsoft ActiveX Data Objects 2.8 Library (biblioteca de objetos
de dados ActiveX da Microsoft). Confira na imagem abaixo:
Sem essa referência não é possível conectar a nenhum banco de dados. Essa
biblioteca contém os objetos necessários para estabelecer a conexão com o
banco de dados. Feito isso, vamos passar para o código. Fazendo uma
pesquisa na internet é possível encontrar vários links (inclusive no
suporte da Microsoft) que mostram códigos muito similares ao código
abaixo:
biblioteca contém os objetos necessários para estabelecer a conexão com o
banco de dados. Feito isso, vamos passar para o código. Fazendo uma
pesquisa na internet é possível encontrar vários links (inclusive no
suporte da Microsoft) que mostram códigos muito similares ao código
abaixo:
Sub ConnectSqlServer()
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sConnString As String
‘ Create the connection string.
sConnString = “Provider=SQLOLEDB;Data
Source=INSTANCESQLEXPRESS;” & _
Source=INSTANCESQLEXPRESS;” & _
“Initial Catalog=MyDatabaseName;” & _
“Integrated Security=SSPI;”
‘ Create the Connection and Recordset objects.
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
‘ Open the connection and execute.
conn.Open sConnString
Set rs = conn.Execute(“SELECT * FROM Table1;”)
‘ Check we have data.
If Not rs.EOF Then
‘ Transfer result.
Sheets(1).Range(“A1”).CopyFromRecordset rs
‘ Close the recordset
rs.Close
Else
MsgBox “Error: No records
returned.”, vbCritical
returned.”, vbCritical
End If
‘ Clean up
If CBool(conn.State And adStateOpen) Then
conn.Close
conn.Close
Set conn = Nothing
Set rs = Nothing
End Sub
Esse código pode parecer desafiador ou mesmo assustador para quem está
tendo um primeiro contato. Há dois objetos principais que são usados neste
código e que você usará sempre que for fazer uma conexão com banco de
dados:
tendo um primeiro contato. Há dois objetos principais que são usados neste
código e que você usará sempre que for fazer uma conexão com banco de
dados:
– ADODB.Connection: É o objeto que trata da conexão ao banco de
dados, criado no código acima como conn;
dados, criado no código acima como conn;
– ADODB.Recordset: É o objeto com o retorno do banco de dados
(conjunto de registros), criado no código acima como rs.
(conjunto de registros), criado no código acima como rs.
Para o objeto de conexão conn conectar é preciso ter uma
string de conexão, que no código acima recebeu o nome
sConnString. Para cada SGBD é preciso usar uma string de conexão
apropriada, o exemplo acima não deve funcionar em outros SGBDs. A melhor
fonte de pesquisa é o site
connectionstrings.com.
string de conexão, que no código acima recebeu o nome
sConnString. Para cada SGBD é preciso usar uma string de conexão
apropriada, o exemplo acima não deve funcionar em outros SGBDs. A melhor
fonte de pesquisa é o site
connectionstrings.com.
Essa string de conexão contém uma série de parâmetros que efetivam a
conexão com o SGBD. Se você estiver utilizando o SQL Server Express será
preciso editar dois parâmetros em relação ao exemplo acima.
Data Source é a instância do banco de dados que você irá se
conectar. Se você não sabe, entre no SQL Server Management Studio e
veja o campo Nome do servidor na tela de conexão, é esse valor que
será utilizado no código. Initial Catalog é o nome do banco de
dados que contém as tabelas que você irá acessar.
conexão com o SGBD. Se você estiver utilizando o SQL Server Express será
preciso editar dois parâmetros em relação ao exemplo acima.
Data Source é a instância do banco de dados que você irá se
conectar. Se você não sabe, entre no SQL Server Management Studio e
veja o campo Nome do servidor na tela de conexão, é esse valor que
será utilizado no código. Initial Catalog é o nome do banco de
dados que contém as tabelas que você irá acessar.
Essa string de conexão é usada junto ao método open do objeto
conn. Não há necessidade de se usar uma variável, poderia colocar a
string diretamente com o open.
conn. Não há necessidade de se usar uma variável, poderia colocar a
string diretamente com o open.
Assim como há o método open, há o close. Perceba que antes
de fechar a conexão é feita uma checagem para ver se o objeto está aberto
e isso é feito de uma forma que poucos devem compreender:
de fechar a conexão é feita uma checagem para ver se o objeto está aberto
e isso é feito de uma forma que poucos devem compreender:
If CBool(conn.State And adStateOpen) Then conn.Close
CBool faz uma conversão para valor booleano e a comparação com
operador And entre parênteses irá testar a nível de bit.
Isso porque a propriedade State usa os valores da enumeração
ObjectStateEnum:
operador And entre parênteses irá testar a nível de bit.
Isso porque a propriedade State usa os valores da enumeração
ObjectStateEnum:
– adStateClosed (0): Indica que o objeto está fechado;
– adStateOpen (1): indica que o objeto está aberto;
– adStateConnecting (2): indica que o objeto está conectando;
– adStateExecuting (4): indica que o objeto está executando um
comando;
comando;
– adStateFetching (8): indica que o objeto está obtendo os
registros solicitados.
registros solicitados.
Se você entende de flags binários e aritmética binária certamente
vai entender o porquê da forma de comparação acima. Se não entende pode
pesquisar na internet se tiver curiosidade. Uma outra forma de escrever
essa verificação (e que eu prefiro) é a seguinte:
vai entender o porquê da forma de comparação acima. Se não entende pode
pesquisar na internet se tiver curiosidade. Uma outra forma de escrever
essa verificação (e que eu prefiro) é a seguinte:
If (conn.State And adStateOpen) = adStateOpen Then conn.Close
No código há também o método Execute no objeto conn. É esse
método que irá enviar o comando SQL ao SGBD para ser processado. Note que
o resultado dessa operação está sendo armazenada no objeto
rs (RecordSet), que é o objeto que armazenará o retorno do
SQL.
método que irá enviar o comando SQL ao SGBD para ser processado. Note que
o resultado dessa operação está sendo armazenada no objeto
rs (RecordSet), que é o objeto que armazenará o retorno do
SQL.
Entre os quatro comandos básicos de SQL (Insert, Select,
Update e Delete), o único que retorna registros é o
Select. Desta forma, não há necessidade de usar o objeto de
registros com os outros comandos, pois estes serão executados sem devolver
registros.
Update e Delete), o único que retorna registros é o
Select. Desta forma, não há necessidade de usar o objeto de
registros com os outros comandos, pois estes serão executados sem devolver
registros.
Voltando ao código de exemplo, após a execução do comando SQL é feita uma
verificação da propriedade EOF (end of file). Essa
propriedade booleana tem valor verdadeiro quando encontra o fim dos
registros. Fazendo a verificação no começo como no exemplo, se
EOF for verdadeiro significa que não há nenhum registro retornado.
Se houver registros, o passo seguinte no exemplo é colar todos os
registros a partir da célula A1 usando o método CopyFromRecordset e
o objeto rs.
verificação da propriedade EOF (end of file). Essa
propriedade booleana tem valor verdadeiro quando encontra o fim dos
registros. Fazendo a verificação no começo como no exemplo, se
EOF for verdadeiro significa que não há nenhum registro retornado.
Se houver registros, o passo seguinte no exemplo é colar todos os
registros a partir da célula A1 usando o método CopyFromRecordset e
o objeto rs.
Se você for simplesmente colar na planilha o resultado da consulta, o
código de exemplo acima basta. Mas é bem provável que você precise
manipular os dados recebidos em variáveis e o que foi visto até aqui não
basta, é preciso conhecer mais detalhes.
código de exemplo acima basta. Mas é bem provável que você precise
manipular os dados recebidos em variáveis e o que foi visto até aqui não
basta, é preciso conhecer mais detalhes.
Nos exemplos de código daqui para a frente utilizarei o objeto
Registros (no plural mesmo, recordset significa conjunto de
registros) para ADODB.Recordset.
Registros (no plural mesmo, recordset significa conjunto de
registros) para ADODB.Recordset.
O objeto ADODB.Recordset possui métodos e propriedades que
permitem trabalhar registro a registro, permitindo manipular os dados sem
necessidade de jogar tudo em uma planilha. Vamos começar com os métodos de
posicionamento dos registros:
permitem trabalhar registro a registro, permitindo manipular os dados sem
necessidade de jogar tudo em uma planilha. Vamos começar com os métodos de
posicionamento dos registros:
– MoveFirst: Posiciona o ponteiro no primeiro registro;
– MoveLast: Leva o ponteiro até o último registro;
– MoveNext: Passa para o próximo registro;
– MovePrevious: Volta ao registro anterior.
Na maioria dos casos será utilizado uma estrutura de repetição desta
forma:
forma:
Do Until Registros.EOF = True
‘ Processamento do registro
‘ …
Registros.MoveNext
Loop
Esse laço irá processar os registros do primeiro até o último, quando
EOF será verdadeiro. Desta forma conseguimos processar cada
registro individualmente. Falta agora ver como obter o valor de cada
coluna retornada pelo SQL.
EOF será verdadeiro. Desta forma conseguimos processar cada
registro individualmente. Falta agora ver como obter o valor de cada
coluna retornada pelo SQL.
O objeto ADODB.Recordset possui um índice, assim como outros
objetos do Excel. O objeto de planilha, por exemplo, pode ser referenciado
como Sheets(1), Sheets(2), etc para cada objeto de planilha
que houver no arquivo. Aqui é a mesma coisa, podemos referenciar
Registros(0), Registros(1) etc. Note que aqui a contagem
começa do 0, não do 1. E da mesma forma que acontecem com o
objeto Sheets, podemos referenciar o objeto pelo nome da planilha,
como Sheets(“Produtos”). No caso o nome é o da coluna retornada
pelo SQL. Assim, se a primeira coluna for Codigo, podemos usar
Registros(“Codigo”), o que facilita muito o entendimento do código.
Também é possível usar a forma Registros.Fields(“Codigo”), mas a
forma anterior é mais curta. Editando o exemplo anterior e usando um
objeto Type para Produto:
objetos do Excel. O objeto de planilha, por exemplo, pode ser referenciado
como Sheets(1), Sheets(2), etc para cada objeto de planilha
que houver no arquivo. Aqui é a mesma coisa, podemos referenciar
Registros(0), Registros(1) etc. Note que aqui a contagem
começa do 0, não do 1. E da mesma forma que acontecem com o
objeto Sheets, podemos referenciar o objeto pelo nome da planilha,
como Sheets(“Produtos”). No caso o nome é o da coluna retornada
pelo SQL. Assim, se a primeira coluna for Codigo, podemos usar
Registros(“Codigo”), o que facilita muito o entendimento do código.
Também é possível usar a forma Registros.Fields(“Codigo”), mas a
forma anterior é mais curta. Editando o exemplo anterior e usando um
objeto Type para Produto:
Do Until Registros.EOF = True
Produto.Codigo = Registros(“Codigo”)
Produto.Nome = Registros(“Nome”)
Produto.Preco = Registros(“Preco”)
‘ Restante do processamento do registro
‘ …
Registros.MoveNext
Loop
O objeto ADODB.Recordset possui muitas outras propriedades e
métodos. Cito alguns bons para debug:
métodos. Cito alguns bons para debug:
– GetString: Este método retorna uma string, sendo os campos
separados por uma tabulação e cada registro em uma linha separada. É
excelente quando está criando uma consulta e quer saber se foi bem
sucedida sem esperar o código todo ficar pronto para executar, bastando
usar com um debug.print para ver o resultado;
separados por uma tabulação e cada registro em uma linha separada. É
excelente quando está criando uma consulta e quer saber se foi bem
sucedida sem esperar o código todo ficar pronto para executar, bastando
usar com um debug.print para ver o resultado;
– Save: Permite gravar o resultado da consulta em um arquivo.
Precisa de dois parâmetros, sendo o primeiro o nome do arquivo (com
caminho) onde será gravado e o segundo precisa ser um valor da enumeração
PersistFormatEnum. Há dois valores possíveis:
adPersistADTG (formato ADTG – Advanced Data TableGram) e
adPersistXML (formato XML – eXtensible Markup Language, mais fácil
de visualizar em um editor de texto);
Precisa de dois parâmetros, sendo o primeiro o nome do arquivo (com
caminho) onde será gravado e o segundo precisa ser um valor da enumeração
PersistFormatEnum. Há dois valores possíveis:
adPersistADTG (formato ADTG – Advanced Data TableGram) e
adPersistXML (formato XML – eXtensible Markup Language, mais fácil
de visualizar em um editor de texto);
– Source: Esta propriedade retorna o comando SQL que foi utilizado
no momento, útil para certificar de que está correto;
no momento, útil para certificar de que está correto;
– State: Assim como o ADODB.Connection, o
ADODB.Recordset também tem a propriedade State, que tem o
mesmo comportamento.
ADODB.Recordset também tem a propriedade State, que tem o
mesmo comportamento.
Dentro do ADODB.Recordset há a coleção Fields, que foi
vista acima. Ele não é necessário se quiser obter o valor (propriedade
Value), mas há muitas outras propriedades bem úteis:
vista acima. Ele não é necessário se quiser obter o valor (propriedade
Value), mas há muitas outras propriedades bem úteis:
– Name: Fornece o nome do campo da consulta SQL;
– Type: Fornece o valor do tipo de dado da coluna. Para comparar é
preciso usar a enumeração DataTypeEnum, que vem com a biblioteca
ADODB. Há valores como adDate, adNumeric,
adVarChar entre outros;
preciso usar a enumeração DataTypeEnum, que vem com a biblioteca
ADODB. Há valores como adDate, adNumeric,
adVarChar entre outros;
– DefineSize: Fornece o tamanho do campo (útil para Char e
VarChar);
VarChar);
– ActualSize: Fornece o tamanho atual do campo;
– NumericScale: Fornece o número de casas decimais permitidas para
um campo numérico;
um campo numérico;
– Precision: Fornece o número máximo de dígitos permitidos para um
campo numérico.
campo numérico.
Lembre-se que Fields é uma coleção e, portanto, deve ser utilizada
com o índice (iniciando em zero), exceto quando usar o método
Count, que retorna a quantidade de campos.
com o índice (iniciando em zero), exceto quando usar o método
Count, que retorna a quantidade de campos.
Com este conhecimento dá para fazer muita coisa com o Excel e o banco de
dados que aquele exemplo do começo do artigo não permite. No começo será
normal passar por alguns problemas e dores de cabeça, mas é um desafio que
vale a pena.
dados que aquele exemplo do começo do artigo não permite. No começo será
normal passar por alguns problemas e dores de cabeça, mas é um desafio que
vale a pena.
Espero que este artigo seja de grande valia. Até o próximo!
Pedro Martins
Pós-graduando em Business Intelligence e Big Data pela Faculdade Impacta
de Tecnologia. Formado em Tecnologia em Eletrônica Digital com Ênfase em
Microprocessadores
de Tecnologia. Formado em Tecnologia em Eletrônica Digital com Ênfase em
Microprocessadores
Catálogo de aulas (NOVIDADE)
Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.