Você pode obter um erro de runtime ao usar o DataObject da biblioteca Microsoft Forms para copiar texto para a área de transferência no VBA do Excel. Esse erro ocorre porque a biblioteca MSForms não está disponível ou está bloqueada por configurações de segurança. O erro impede que sua macro copie dados para uso em outros aplicativos. Este artigo explica por que esse erro acontece e fornece um método alternativo confiável que não requer a biblioteca MSForms.
Principais Conclusões: Corrigindo Erros de Área de Transferência no VBA
- Chamadas da API do Windows: Use a API da área de transferência do Windows diretamente para copiar texto sem bibliotecas externas.
- Instruções Declare Function: Adicione declarações de API específicas no topo do seu módulo VBA para acessar funções da área de transferência.
- Limpe a área de transferência primeiro: Sempre chame as funções
OpenClipboardeEmptyClipboardda API antes de colocar novos dados.
Por que o DataObject do MSForms Falha no VBA
O DataObject faz parte da Microsoft Forms 2.0 Object Library, referenciada como MSForms. Essa biblioteca não é um componente central do VBA do Excel. É um componente externo que precisa estar disponível no sistema do usuário. Se a biblioteca estiver ausente, danificada ou não referenciada em seu projeto VBA, seu código falhará com um erro como “Erro de runtime ‘429’: componente ActiveX não pode criar objeto”.
Mesmo com a referência configurada, alguns ambientes de TI corporativos restringem ou bloqueiam a biblioteca MSForms por motivos de segurança. Isso torna o método DataObject não confiável para distribuir macros. A API do Windows fornece uma maneira direta e de baixo nível de interagir com a área de transferência do sistema. Esse método está embutido no próprio Windows, portanto funciona em qualquer PC onde o Excel é executado, sem necessidade de referências extras.
Passos para Copiar Texto Usando a API do Windows
Este método usa funções nativas do Windows. Você deve declarar essas funções no topo de um módulo VBA padrão antes de escrever o procedimento de cópia.
- Abra o Editor VBA e insira um módulo
Pressione Alt + F11 para abrir o editor Visual Basic for Applications. Vá em Inserir > Módulo para criar um novo módulo padrão. - Declare as funções necessárias da API do Windows
Copie e cole o seguinte código no topo do novo módulo, acima de qualquer sub-rotina.Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function EmptyClipboard Lib "user32" () As Long
Private Declare Function CloseClipboard Lib "user32" () As Long
Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalSize Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long - Crie a sub-rotina principal para copiar texto
Abaixo das declarações, crie uma nova sub-rotina chamadaCopyToClipboardAPI. Esta sub-rotina conterá a lógica para colocar sua string de texto na área de transferência. - Escreva a lógica central de cópia dentro da sub-rotina
Use o seguinte padrão de código dentro de sua sub-rotina. Substitua “Seu texto aqui” pela string ou variável que deseja copiar.Sub CopyToClipboardAPI(text As String)
Dim hMem As Long, lpMem As Long, dataLen As Long
dataLen = Len(text) + 1
hMem = GlobalAlloc(&H2, dataLen)
If hMem <> 0 Then
lpMem = GlobalLock(hMem)
If lpMem <> 0 Then
lstrcpy lpMem, text
GlobalUnlock hMem
If OpenClipboard(0) <> 0 Then
EmptyClipboard
SetClipboardData 1, hMem
CloseClipboard
End If
End If
End If
End Sub - Chame a sub-rotina a partir de sua macro principal
Para usar a função, chame-a de outra parte do seu código. Por exemplo, para copiar o valor da célula A1, você escreveria:CopyToClipboardAPI Range("A1").Value.
Método para Windows e Office 64 bits
Se você estiver usando versões de 64 bits do Windows e Office, deve usar a palavra-chave PtrSafe em suas declarações. Substitua o primeiro bloco de declarações por esta versão.
#If VBA7 Then
Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
Private Declare PtrSafe Function EmptyClipboard Lib "user32" () As LongPtr
Private Declare PtrSafe Function CloseClipboard Lib "user32" () As LongPtr
Private Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr
Private Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr
#End If
O código da sub-rotina permanece o mesmo, mas você deve alterar os tipos de variáveis de Long para LongPtr para compatibilidade.
Se o Método da API Não Funcionar
O Excel Trava ao Chamar as Funções da API
Isso geralmente é causado por declarações de API incorretas, especialmente em sistemas de 64 bits. Certifique-se de estar usando as declarações PtrSafe dentro de um bloco #If VBA7 Then. Além disso, verifique se todos os tipos de variáveis correspondem à declaração. Usar Long onde LongPtr é necessário causará uma falha.
O Texto é Copiado, mas Aparece Distorcido em Outros Aplicativos
A área de transferência espera uma string terminada em nulo. A linha dataLen = Len(text) + 1 no código adiciona espaço para esse caractere nulo. Se você omitir o + 1, a string copiada pode ter caracteres extras indesejados no final. Sempre calcule o comprimento incluindo o terminador nulo.
A Área de Transferência está Bloqueada por Outro Aplicativo
A função OpenClipboard retorna zero se outro processo estiver usando a área de transferência. Seu código deve lidar com isso de forma adequada. Você pode envolver a chamada em um loop com um pequeno atraso para tentar novamente algumas vezes antes de desistir.
DataObject vs API do Windows: Principais Diferenças
| Item | MSForms DataObject | Método da API do Windows |
|---|---|---|
| Dependência de Biblioteca | Requer referência à biblioteca MSForms 2.0 Object Library | Nenhuma referência externa necessária |
| Confiabilidade de Implantação | Falha se a biblioteca estiver ausente ou bloqueada por política de administrador | Funciona em qualquer sistema Windows com Excel |
| Complexidade do Código | Simples, poucas linhas de código | Mais complexo, requer declarações precisas da API |
| Controle sobre os Dados | Cópia e colagem básica de texto | Controle total, pode definir formatos específicos de área de transferência |
| Compatibilidade de Bits | Funciona em VBA de 32 e 64 bits sem modificação | Requer declarações diferentes para VBA7 de 64 bits |
Agora você pode copiar texto para a área de transferência no VBA do Excel sem depender da biblioteca MSForms. O método da API do Windows é uma solução robusta para macros distribuídas. Para uma técnica relacionada, tente usar a função GetFromClipboard da API para ler o texto de volta para o Excel. Uma dica avançada é encapsular a lógica central da API em um módulo de classe separado para criar um objeto de área de transferência reutilizável para seus projetos.