Twittando com o VBA
Estive recentemente trabalhando num projeto baseado em VBA que incorpora a possibilidade de postar atualizações de status para Twitter.
Antes de colocá-lo juntos consultei vários exemplos de códigos, especificações, documentação API, mensagens em blog, fórum, etc ... Estou compartilhando meus esforços aqui na esperança de salvar qualquer outra pessoa trabalhando em um projeto semelhante um pouco de tempo e / ou frustração . Eu também acrescentou um par de características que eu não tinha visto em outros lugares (por exemplo, usando v1.1. Da API do Twitter, incluindo imagens com tweets, integrando ligação encurtamento, etc ...), então (espero!) Eu sou acrescentando algo de novo para o corpo Tweet-via-VBA da literatura.
Alguns aspectos preliminares:
- Claro, todos têm sua própria maneira de nomear variáveis / funções / subs, tabs, comentários, etc ... Se algo que estiver implementado aqui não combinar com o seu modo, faça as alterações que achar necessário.
- Desejei evitar Dlls de terceiros ou add-ins. Assim, estamos usando scripts de controle Microsoft (msscript.ocx), e um par de bibliotecas .Net (o que significa que precisará ter o .NET Framework 1.1 ou posterior instalado). Uma desvantagem para isso é que o Microsoft Script só pode ser usado em versões do MS Office de 32 bits (2007, 2010 e 2013 devem ser todos OK). Nas versões 32 bits ou 64 bits do Windows o código com está sendo executado no Office 64 bits. Se precisar modificar este código para rodar em 64 bits no Office, precisará implementar algumas alterações.
- Certifique-se de ter adicionado as referências ao Microsoft WinHTTP Services, XML Microsoft e Microsoft Script ao seu projeto (Ferramentas -> Adicione referências no editor VBA)
- Você encontrará alguns casos óbvios de repetição de código (por exemplo, as funções get_basestring , get_status_basestring e get_media_basestring são bastante idênticos). Como estava originalmente trabalhando desta maneira, foi mais fácil concentrar a tarefa dessa forma (ou seja, Tweets de texto, Tweets com mídia, obtendo o serviço do Twitter e a informação do estado). Pode-se facilmente refazer as funções anteriores em uma única função, existem oportunidades adicionais para tornar o código mais eficiente / elegante e consistente.
- Este desenvolvimento foi criado por Greg Williams e está licenciado sob atribuição Creative Commons.
- O código é fornecido como está. Todo o uso é por sua conta e risco.
Funções da API do Windows e declarações de tipo
Primeiro, vamos definir um par de funções da API do Windows usando o Declare palavra-chave. Também vamos criar alguns tipos de dados definidos pelo usuário usando o Tipo comunicado.
#If VBA7 ThenPublic Declare PtrSafe Sub GetSystemTime Lib "Kernel32" (lpSystemTime As SYSTEMTIME)Public Declare PtrSafe Function SystemTimeToFileTime Lib "Kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As LongPtrPublic Declare PtrSafe Function LocalFileTimeToFileTime Lib "Kernel32" (lpLocalFileTime As FILETIME, lpFileTime As FILETIME) As LongPtrPublic Declare PtrSafe Function FileTimeToSystemTime Lib "Kernel32" (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As LongPtr#ElsePublic Declare Sub GetSystemTime Lib "Kernel32" (lpSystemTime As SYSTEMTIME)Public Declare Function SystemTimeToFileTime Lib "Kernel32" (lpSystemTime As SYSTEMTIME, lpFileTime As FILETIME) As LongPublic Declare Function LocalFileTimeToFileTime Lib "Kernel32" (lpLocalFileTime As FILETIME, lpFileTime As FILETIME) As LongPublic Declare Function FileTimeToSystemTime Lib "Kernel32" (lpFileTime As FILETIME, lpSystemTime As SYSTEMTIME) As Long#End IfPublic Type FILETIMEdwLowDateTime As LongdwHighDateTime As LongEnd TypePublic Type SYSTEMTIMEwYear As IntegerwMonth As IntegerwDayOfWeek As IntegerwDay As IntegerwHour As IntegerwMinute As IntegerwSecond As IntegerwMilliseconds As IntegerEnd Type
A sintaxe #If VBA7 Então ... # Else ... # End If, PtrSafe palavra-chave, e LongPtr tipo de dados são usados para permitir que o código seja executado na versão 64 bits do Office (ver este artigo MSDN para mais informações).
Novamente, conforme mencionado acima, o código como está (usando o Microsoft Script Control), não será executado no Office 64 bits. Mas, se decidir escrever alternativas / uso que não precisam Microsoft Script Control (ou no caso aparentemente improvável que a Microsoft lança uma versão de 64 bits do msscript.ocx), vai ser útil para ter suas declarações de função API 64-bit de pronto.
CONSTANTES
A seguir, vamos definir algumas constantes. Para obtermos as chaves de API do Twitter necessárias e os tokens, precisaremos nos inscrever no Twitter como um desenvolvedor, em seguida, registrar o aplicativo.
Neste exemplo, também usaremos encurtador de links do Google para encurtar os links incluídos nos tweets. Se quiser fazer o mesmo, precisará se inscrever como um desenvolvedor do Google e obter uma chave de API.
Const cnsAPIMethodP As String = "POST"
Const cnsAPIMethodG As String = "GET"
Const cnsOauthConsumerKey As String = "yourtwitterconsumerkey"
Const cnsOauthConsumerSecret As String = "yourtwitterconsumersecret"
Const cnsOauthToken As String = "yourtwitteraccesstoken"
Const cnsOauthTokenSecret As String = "yourtwitteraccesstokensecret"
Const cnsURLPost As String = "https://api.twitter.com/1.1/statuses/update.json"
Const cnsURLMedia As String = "https://api.twitter.com/1.1/statuses/update_with_media.json"
Const cnsURLStatus As String = "https://api.twitter.com/1.1/help/configuration.json"
Const cnsMethod As String = "HMAC-SHA1"
Const cnsOauthVersion As String = "1.0"
'Following only necessary if using Google's goo.gl link shortener API
Const cnsGoogleShortenerURL As String = "https://www.googleapis.com/urlshortener/v1/url"
Const cnsGoogleShortenerKey As String = "yourgoogleshortenerkeyhere"
Funções auxiliares
Em seguida, olharemos para algumas funções auxiliares para criar / enviar nossos tweets.
O LocalTimeToUTC função converte um valor de data em formato UTC. Graças ao código do Allen Wyatt.
Public Function LocalTimeToUTC(dteTime As Date) As DateDim dteLocalFileTime As FILETIMEDim dteFileTime As FILETIMEDim dteLocalSystemTime As SYSTEMTIMEDim dteSystemTime As SYSTEMTIMEdteLocalSystemTime.wYear = CInt(Year(dteTime))dteLocalSystemTime.wMonth = CInt(Month(dteTime))dteLocalSystemTime.wDay = CInt(Day(dteTime))dteLocalSystemTime.wHour = CInt(Hour(dteTime))dteLocalSystemTime.wMinute = CInt(Minute(dteTime))dteLocalSystemTime.wSecond = CInt(Second(dteTime))Call SystemTimeToFileTime(dteLocalSystemTime, _dteLocalFileTime)Call LocalFileTimeToFileTime(dteLocalFileTime, _dteFileTime)Call FileTimeToSystemTime(dteFileTime, dteSystemTime)LocalTimeToUTC = CDate(dteSystemTime.wMonth & "/" & _dteSystemTime.wDay & "/" & _dteSystemTime.wYear & " " & _dteSystemTime.wHour & ":" & _dteSystemTime.wMinute & ":" & _dteSystemTime.wSecond)End Function
O Twitter usa o OAuth Autorization para validar todas as solicitações. Um dos parâmetros necessários do OAuth é um timestamp (ou seja, o número de segundos decorridos desde 1 de janeiro de 1970 00:00:00 GMT). A função get_timestamp fornece uma seqüência timestamp no formato exigido.
Public Function get_timestamp() As Stringget_timestamp = DateDiff("s", #1/1/1970#, LocalTimeToUTC(Now))End Function
A função EncodeBase64 recebe um array de bytes e converte para uma string codificada em base64. É usado para converter dados binários em uma cadeia de caracteres ASCII. Pensava que esta era uma técnica escorregadia; criar um documento XML (usando o objeto MSXML2.DOMDocument), crie um nó e e atribuia os dados binários para ele. Em seguida, basta ler a propriedade de texto do mesmo nó (MSMXL2.DOMDocument irá lidar com a conversão automaticamente). Graças a Tim Hastings para o código.
Public Function EncodeBase64(ByRef arrData() As Byte) As StringDim objXML As MSXML2.DOMDocumentDim objNode As MSXML2.IXMLDOMElementSet objXML = New MSXML2.DOMDocument' byte array to base64Set objNode = objXML.createElement("b64")objNode.DataType = "bin.base64"objNode.nodeTypedValue = arrDataEncodeBase64 = objNode.TextSet objNode = NothingSet objXML = NothingEnd Function
O Base64_HMACSHA1 é uma função que utiliza um par de classes do namespace .Net Sistema de hash uma string em um SHA-1 digere e calcula um código de autenticação HMAC usando uma chave secreta. (você pode usar o método VBA CreateObject para utilizar quaisquer classes .Net que são 'explicitamente expostas como componentes COM') Graças ao código da HK1.
Public Function Base64_HMACSHA1(ByVal sTextToHash As String, ByVal sSharedSecretKey As String) As StringDim asc As ObjectDim enc As ObjectDim TextToHash() As ByteDim SharedSecretKey() As ByteSet asc = CreateObject("System.Text.UTF8Encoding")Set enc = CreateObject("System.Security.Cryptography.HMACSHA1")TextToHash = asc.Getbytes_4(sTextToHash)SharedSecretKey = asc.Getbytes_4(sSharedSecretKey)enc.key = SharedSecretKeyDim bytes() As Bytebytes = enc.ComputeHash_2((TextToHash))Base64_HMACSHA1 = EncodeBase64(bytes)Set asc = NothingSet enc = NothingEnd Function
A função binary_file_to_string recebe um arquivo binário (como um arquivo de imagem) e a converte para uma string. Vamos eventualmente usar esta função quando quisermos incluir imagens em nossos tweets. Nada muito complicado aqui; apenas ler um arquivo binário em um array de bytes, em seguida, usaremos a função VBA built-in StrConv para converter a matriz de bytes para uma cadeia Unicode.
Public Function binary_file_to_string(strFileName) As String
Dim bytArr() As Byte
Dim strConvData As String
Dim intFile As Integer
intFile = FreeFile
Open strFileName For Binary Access Read As intFile
If LOF(intFile) > 0 Then
ReDim bytArr(0 To LOF(intFile) - 1) As Byte
Get intFile, , bytArr
strConvData = StrConv(bytArr, vbUnicode)
End If
Close intFile
binary_file_to_string = strConvData
End Function
A função strToByteArray recebe uma string e a converte para um array de bytes utilizando a função StrConv do VBA. Ao incluir uma imagem no tweet, vamos usar esta função para preparar o corpo da solicitação HTTP.Public Function get_GUID() As Stringget_GUID = Replace(Mid$(CreateObject("Scriptlet.TypeLib").Guid, 2, 36), "-", "")End Function
Private Function strToByteArray(sText As String) As Byte()strToByteArray = StrConv(sText, vbFromUnicode)End Function
Public Function UrlEncode(str As String)Dim objEnc As MSScriptControl.ScriptControlSet objEnc = New MSScriptControl.ScriptControlobjEnc.Language = "JScript"objEnc.AddCode "function encode(str) {return encodeURIComponent(str);}"Dim encoded As Stringencoded = objEnc.Run("encode", str)UrlEncode = encodedEnd Function
Funções do Twitter
Com o nosso exército de funções auxiliares prontos para lançar dentro, é hora de twittar!
A fim de postar uma atualização de status (ou seja, tweet), vamos (amplamente) precisa:
- Calcular uma assinatura de autenticação especial
- Enviar um pedido http adequadamente construído
Parece bastante simples, mas o cálculo da assinatura envolve algumas etapas distintas. Vamos expandir nossa lista de tarefas:
- Calcular uma assinatura de autenticação especial
- Criar uma cadeia de texto aleatório que é susceptível de ser exclusivo
- Calcular um timestamp época
- Criar uma cadeia de base com a qual para calcular a nossa assinatura de autenticação
- Criar uma chave especial com o qual calcular a nossa assinatura de autenticação
- Criar assinatura de autenticação
- Enviar um pedido http construída adequadamente
Nós tomaremos cada seção em ordem.
Aguarde os próximos artigos...
Deixe seus comentários, compartilhe este artigo!
brazilsalesforceeffectiveness@gmail.com