... Assinatura do site por 3 anos + Kit MontaRibbons + 3 Livros em PDF + Diversas Revistas (pdf) de brinde, por apenas R$145,00
(
podendo parcelar em até 10 vezes no cartão de crédito)...

Clique aqui e obtenha mais detalhes do nosso kit completo e de como comprar.


Transferir dados entre tabelas com campos dos tipos Anexo e Múltiplos Valores 

Novos tipos de campos

Da versão 2007 em diante, dois novos tipos de campos foram inseridos no Access: o campo tipo Anexo e o campo tipo Múltiplos Valores

Usando Access - campo tipo Anexo e múltiplos Valores

Esses dois tipos de campos não são permitidos em consultas de ação de Inclusão (INSERT) e de Alteração (UPDATE).  A razão de não funcionarem com as consultas de ação é que o Access cria tabelas internas para armazenar os dados dos campos.  Além das tabelas, o Access também cria um relacionamento de 1 para Muitos entre a tabela que contém o campo em questão e a tabela interna. 

Para o campo tipo Anexo, o Access cria três campos na tabela interna, de nomes:  FileData, FileName e FileType.  Veja na lista da consulta: 

Usando Access - campo tipo Anexo

Na tabela interna do campo tipo Múltiplos Valores, o campo criado recebe o nome de Value. 

Usando Access - campo tipo Mútiplos Valores

É importante saber esses nomes criados, pois serão utilizados nos códigos oferecidos mais abaixo.

Vamos supor que você tenha criado a seguinte consulta de inserção (INSERT), na qual a tabela_A e a tabela_B  tenham a mesma estrutura e  campos do tipo Anexo e/ou do tipo Múltiplos Valores:

Currentdb.execute "INSERT INTO Tabela_B SELECT * FROM Tabela_A;"

Ao executar a consulta, como era de se esperar, será exibida a seguinte mensagem de falha:

Usando Access - Erro 3824

Qual é a solução para este caso ?

A solução é fazer uso dos Recordset para poder acessar as tabelas internas e  percorrer registro por registro para capturar os dados e realizar a gravação. 

Exemplo fornecido

Para entender como o Recordset  funciona na prática, segue um arquivo exemplo que contém quatro tabelas.  Duas tabelas contendo campo do tipo Anexo e as outras duas contendo campo do tipo Múltiplos Valores. 

Usando Access - Arquivo exemplo


A tabela tblCampoAnexoArquivo receberá os registros da tabela tblCampoAnexo

A tabela tblCampoMultiplosValoresArquivo receberá os registros da tabela tblCampoMultiplosValores

Baixe o arquivo exemplo:

Código exemplo para o campo do tipo Múltiplos Valores

Veja o código utilizado para gravar o campo do tipo Valores Múltiplos.  Leia atentamente os comentários :

Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rsfilho As DAO.Recordset2
Dim rsfilho2 As DAO.Recordset2

CurrentDb.Execute "DELETE * FROM tblCampoValoresMultiplosArquivo;"
'-----------------------------------
'Abre a tabela tblValoresMúltiplos
'------------------------------------
Set rs = CurrentDb.OpenRecordset("tblCampoValoresMultiplos")
'------------------------------------------------------------------
'Abre a tabela tblValoresMultiplosArquivo que receberá os registros
'da tabela tblValoresMúltiplos
'------------------------------------------------------------------
Set rs2 = CurrentDb.OpenRecordset("tblCampoValoresMultiplosArquivo")
'---------------------------------------------------------
'Percorre todos os registros da tabela tblvaloresMultiplos
'---------------------------------------------------------
Do While Not rs.EOF
   '-------------------------------------------------------------
   'Passa os registros da tabela interna, do campo carros para
   'o Recordset rsFilho. Com isso temos acesso aos dados contidos
   'do campo carro.
   '----------------------------------------------------------
   Set rsfilho = rs!carro.Value
   '----------------------------------------------------------------
   'Inicia a gravação dos campos da tabela tblValoresMúltiplos na
   'tabela tblValoresMultilosArquivo
   '---------------------------------------------------------------
   rs2.AddNew
      '-----------------------------------------------------------
      'O Recordset rsFilho2 assume a tabela interna do campo 
      'carro, da tabela tblValoresMultiplosArquivo.
      '----------------------------------------------------------- 
      Set rsfilho2 = rs2!carro.Value
      rs2!Cliente = rs!Cliente
      '-------------------------------------------------------------------
      'Percorre todos os registros da tabela interna do campo carro.
      '-------------------------------------------------------------------     
      Do While Not rsfilho.EOF
         rsfilho2.AddNew
            '------------------------------------------------------------ 
            'A cada registro percorrido, o campo VALUE de uma tabela 
            'interna será gravado na outra tabela interna.
            '------------------------------------------------------------
            rsfilho2!Value = rsfilho!Value
         rsfilho2.Update
         rsfilho.MoveNext
      Loop
   rsfilho2.Close
   rsfilho.Close
   rs2.Update
rs.MoveNext
Loop
rs2.Close
rs.Close
Set rsfilho2 = Nothing
Set rsfilho = Nothing
Set rs2 = Nothing
Set rs = Nothing
MsgBox "Registros transferidos com sucesso para a _
tabela tblCampoValoresMultiplosArquivo...", vbInformation, "Aviso"
DoCmd.OpenTable "tblCampoValoresMultiplosArquivo"

Código exemplo para o campo do tipo Anexo

Agora, observe o código para gravação do campo tipo Anexo.  São necessários dois campos da tabela interna (FlieName e FileData) para realizar a gravação:

Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rsfilho As DAO.Recordset2
Dim rsfilho2 As DAO.Recordset2

CurrentDb.Execute "DELETE * FROM tblCampoAnexoArquivo;"
Set rs = CurrentDb.OpenRecordset("tblCampoAnexo")
Set rs2 = CurrentDb.OpenRecordset("tblCampoAnexoArquivo")
Do While Not rs.EOF
   Set rsfilho = rs!Imagens.Value
   rs2.AddNew
      Set rsfilho2 = rs2!Imagens.Value
      rs2!paciente = rs!paciente
      Do While Not rsfilho.EOF
         rsfilho2.AddNew
            rsfilho2!FileName = rsfilho!FileName
            rsfilho2!FileData = rsfilho!FileData
         rsfilho2.Update
         rsfilho.MoveNext
      Loop
   rsfilho2.Close
   rsfilho.Close
   rs2.Update
   rs.MoveNext
Loop
rs2.Close
rs.Close
Set rsfilho2 = Nothing
Set rsfilho = Nothing
Set rs2 = Nothing
Set rs = Nothing
MsgBox "Registros transferidos com sucesso para a _
tabela tblCampoAnexoArquivo...", vbInformation, "Aviso"
DoCmd.OpenTable "tblCampoAnexoArquivo"

Abra o formulário frmTesteCopiaRegistro e clique nos botões para ver em ação, os códigos aqui apresentados.

Bom estudo!


 

 


22 comentários

Harysohn Pina   12/03/2014 13:51:36

Perfeito Mestre!

Cumprimentos.

Luís Augusto   12/03/2014 19:51:00

Parabéns Avelino!
Toda vez que leio um artigo seu, me surpreendo com o conteúdo e a forma clara com que explica.
Espero que nunca se canse de passar adiante o seu conhecimento.
Um grande abraço.

Atenciosamente, Luís Augusto.

Marcos Santos   12/03/2014 19:59:02

Muito bom!
Meus cumprimentos e agradecimentos, Avelino!

Luiz Carlos Junior   13/03/2014 08:55:12

Mestre dos mestres!

Belgamazzi   13/03/2014 09:24:06

Artigo muito bom. Explicação bem objetiva de facil entendimento...

Ronilson Silva   13/03/2014 10:10:48

Avelino este seu artigo me deu uma ideia para meu projeto. Como sempre nos surpreendendo e compartilhando conosco o seu conhecimento.

Avelino Sampaio   13/03/2014 10:39:37

Fico muito grato pela participação de todos!

Ronilson,

com este código ainda é possível subir e descer arquivo para uma pasta (compo tipo anexo), utilizando os métodos SaveToFile e LoadFromFile

rsfilho2!FileData.SaveToFile (strCaminho)
rsfilho2!FileData.LoadFromFile(strCaminho)

Sucesso!

Juliano   13/03/2014 11:26:23

Muito bom o artigo Avelino, fico na seguinte situação:
Como tratar para que o anexo não seja incorporado, apenas vinculado. Ou seja, utilizo apenas o caminho (string) do arquivo, para quando necessário exibi-lo sem precisar estar incorporado ao banco, "pesando" a minha aplicação?!

Avelino Sampaio   13/03/2014 11:50:11

Juliano,

vá na seção DICAS aqui do site e leia o artigo "Como vincular imagens PNG em botões"

Se pretende abrir um DOC, PDF, PPT, ... Pode utilizar o comando FollowHyperlink

application.FollowHyperlink INDIQUE AQUI O LOCAL DO ARQUIVO

Copie e cole este endereço no seu navegador e veja este caso. (tem que se cadastrar no fórum)

http://maximoaccess.maisforum.com/t17780-resolvidoproblemas-em-colocar-todos-os-arquivos-numa-listbox
Sucesso!

Haroldo Lima   13/03/2014 12:14:25

O Access 365 trabalha com o MSQL na Web?

Juliano   13/03/2014 12:39:46

Este exemplo eu ja conhecia, obrigado. Falo pelo controle "Anexo" porque ele permite múltiplos anexos ao campo, entretanto e infelizmente somente incorporados, não vinculados.
Para contornar isso, teria que ser uma outra tabela apenas para receber estes anexos (string do caminho), onde eu posso utilizar o relacionamento 1 para muitos e depois com FollowHyperlink acessar o arquivo. Bem, quem sabe a microsoft nao muda para as demais versoes e permita o anexo ser vinculado.

WaL   15/03/2014 20:16:17

Valeu pela explicação vou treinar mais. Obrigado.

Ricardo   31/03/2014 19:18:01

Excelente.
Estou a precisar de utilizar o código acima apresentado, mas verificando o seu arquivo de exemplo, os dados não estão a ser carregados nas tabelas... pode verificar por favor.

Avelino Sampaio   01/04/2014 07:06:09

Ricardo,

baixe novamente o aplicativo exemplo. Fiz uma pequena modificação.

Qual é a versão do seu Access ?

No aguardo

Syan   08/07/2015 13:23:32

Olá, gostaria de pedir uma ajuda. Estou tentando aplicar um filtro em um formulário que faz uso de um campo MULTIPLOS VALORES, mas aparece uma mensagem com o seguinte erro: "O campo '[x]' de valores múltiplos não pode ser usado em cláusula WHERE ou HAVING."

Como eu posso aplicar um filtro com esse campo?

Carol   26/08/2015 11:10:11

Syan, eu tive o mesmo problema e pra solucionar eu fiz o seguinte:

Criei uma consulta e lá no critério eu coloquei [MinhaTabela]![CampoMultiplo].[Value] = [Formulários]![MeuFormulario]![CampoDoFormulario]

Ou seja, além de colocar o campo tem que especificar que quer o valor selecionado da lista.

Espero ter ajudado.

José Waldick   08/03/2016 17:37:27

Avelino,
Parabéns pelo material apresentado, excelente!

Adalberto Rosado   06/05/2016 09:56:01

Grande ajuda.
Muito obrigado e parabéns pelo trabalho!

André Silveira   28/08/2016 17:02:05

Avelino, boa tarde!

Tenho que transferir da tabela A para a tabela B todos os registros que estão com o status finalizados e excluindo da tabela A os que foram transferidos, deixando somente os com status em aberto.
Tentei adaptar mas não consegui, isto é possível, conhece algum código?

Obrigado

Flavio Kneipp   19/05/2017 12:29:56

Tentei com o "Código exemplo para o campo do tipo Anexo" e não obtive sucesso.
Criei um Banco com as informações do texto acima, fui em formulário, criei um ícone, cliquei com botão direito, "construir evento, construtor de código" e entrei com o código abaixo.
Só que não passa nem da primeira linha.
Alguém pode me ajudar? Se precisar passo o Banco que criei para sugestões.
flaviokneipp@yahoo.com.br

Private Sub Comando3_Click()

Dim rs As DAO.Recordset
Dim rs2 As DAO.Recordset
Dim rsfilho As DAO.Recordset2
Dim rsfilho2 As DAO.Recordset2

CurrentDb.Execute "DELETE * FROM tblCampoAnexoArquivo;"
Set rs = CurrentDb.OpenRecordset("tblCampoAnexo")
Set rs2 = CurrentDb.OpenRecordset("tblCampoAnexoArquivo")
Do While Not rs.EOF
Set rsfilho = rs!Imagens.Value
rs2.AddNew
Set rsfilho2 = rs2!Imagens.Value
rs2!paciente = rs!paciente
Do While Not rsfilho.EOF
rsfilho2.AddNew
rsfilho2!FileName = rsfilho!Imagens
rsfilho2!FileData = rsfilho!Imagens

rsfilho2.Update
rsfilho.MoveNext
Loop
rsfilho2.Close
rsfilho.Close
rs2.Update
rs.MoveNext
Loop
rs2.Close
rs.Close
Set rsfilho2 = Nothing
Set rsfilho = Nothing
Set rs2 = Nothing
Set rs = Nothing
MsgBox "Registros transferidos com sucesso para a _
tabela tblCampoAnexoArquivo...", vbInformation, "Aviso"
DoCmd.OpenTable "tblCampoAnexoArquivo"

End Sub

Paulo gesse da Costa   30/07/2017 12:05:56

usei seu modulo. deu certo.
tentei adaptar para excluir o anexo e não deu certo. tem alguma sugestão para apagar o anexo pelo mesmo metodo

paulo gesse da costa   31/07/2017 09:48:19

retire o argumento que funciona.
CurrentDb.Execute "DELETE * FROM tblCampoAnexoArquivo;"

não entendi para que serviu esta parte.


Envie seu comentário: