VBA - Artigo 017 - Gerando arquivo de log

Progredindo em VBA no Microsoft Excel

Gerando arquivo de log

Em sistemas computacionais, é comum a geração de arquivos com o registro do funcionamento do sistema, para que possam ser identificadas eventuais anomalias. É possível criarmos arquivos de log em planilhas do Excel, onde podemos gravar informações sobre erros no funcionamento do código (a fim de identificar as causas), data e hora de abertura e fechamento da planilha, quem abriu etc.

Conforme vimos no artigo anterior sobre arquivos sequenciais, podemos abrir arquivos para acrescentar linhas a um arquivo existente, com o parâmetro Append no comando Open. Assim podemos manter todos os registros pelo tempo que for necessário. Caso usássemos o comando Open com o parâmetro Output, seria gerado um arquivo novo a cada uso, o que não é o desejado.

Antes de mais nada, vamos ver alguns detalhes para ajudar na criação de uma sub-rotina que pode ser usada em qualquer planilha. Sabemos que o Excel identifica arquivos externos com um número. Se usarmos um número fixo no código, não poderemos reutilizar o código em planilhas que trabalham com arquivos externos, com o risco de misturar os registros gravados. Felizmente, o VBA tem a função FreeFile, que retorna o próximo número disponível. Se não houver arquivos abertos, ela retornará 1, se houver um aberto, retornará 2 e assim por diante.

Outra ideia é manter o arquivo de log junto ao próprio arquivo da planilha do Excel. Há o método ActiveWorkbook.Path que retorna o caminho do arquivo da planilha ativa. Podemos usar até o próprio nome da planilha como nome do arquivo de log, para ficar mais fácil de identificar.

Com estes detalhes, podemos montar um esboço da sub-rotina:

Sub Teste()

    Dim Diretorio As String
    Dim NomeArquivo As String
    Dim NumeroArquivo As Integer

    Diretorio = ActiveWorkbook.Path
    NomeArquivo = Diretorio & "\" & ActiveWorkbook.Name & ".log"
    NumeroArquivo = FreeFile

    Debug.Print "Diretório = " & Diretorio
    Debug.Print "Nome do arquivo = " & NomeArquivo
    Debug.Print "Número do arquivo = " & NumeroArquivo

End Sub

Com esse esboço você pode testar o funcionamento. Os métodos Debug.Print irão exibir os valores das variáveis após o término da sub-rotina. Não esqueça de testar com uma planilha já salva, porque vai precisar do diretório e nome de arquivo. Não se preocupe com o fato do arquivo terminar com duas extensões " .xlsm.log", pois o Windows só considera como extensão após o último ponto, neste caso ".log". Você pode até remover a extensão ".xlsm", mas para isso precisará de usar as funções de tratamento de strings, o que não vamos ver aqui para não alongar e nem desviar o foco do artigo.

Uma coisa que sempre é bom colocar no início do log é a data e hora do momento em que está sendo gravado. O VBA fornece a função Now, que fornece a data e hora do momento em que é chamada, ou seja, é perfeita para o que precisamos. Como função, podemos enviar o seu retorno para uma variável a fim de armazenar para o momento oportuno. Acrescente as linhas ao esboço e veja o resultado:

    Dim DataHora As String
    DataHora = Now
    Debug.Print "Data e hora = " & DataHora

É possível obter somente a data com DateValue(Now) e somente a hora com TimeValue(Now), mas no log é sempre bom termos os dois dados. Caso queira criar um log mais sofisticado, como por exemplo um arquivo de log diário, use essas funções.

Por fim, precisamos decidir a forma de como será enviado o conteúdo para ser gravado no log. A maneira mais simples é a sub-rotina receber uma variável do tipo string com o texto que será gravado. Vejamos como fica o código:

Sub GravarLog(Mensagem As String)

    Dim Diretorio As String
    Dim NomeArquivo As String
    Dim NumeroArquivo As Integer
    Dim DataHora As String

    Diretorio = ActiveWorkbook.Path
    NomeArquivo = Diretorio & "\" & ActiveWorkbook.Name & ".log"
    NumeroArquivo = FreeFile
    DataHora = Now

    Open NomeArquivo For Append As #NumeroArquivo
   
    Print #NumeroArquivo, DataHora & " - " & Mensagem
   
    Close #NumeroArquivo

End Sub

Primeiramente, observe que a variável NumeroArquivo vem acompanhada do símbolo # nos comandos Open, Print e Close. Se não estiver com o # aparece uma mensagem de erro.

Essa sub-rotina GravarLog irá gravar um registro com a data e hora acompanhada do conteúdo da variável Mensagem recebida. Teste o funcionamento com o código abaixo:

Sub Teste()

    GravarLog "Testando a gravação do log"

End Sub

Execute o teste quantas vezes achar necessário e depois abra o arquivo gerado para ver o conteúdo. Para cada vez que foi executado o teste haverá uma linha com a mensagem informada, cada uma com seu respectivo horário.

Com essa rotina GravarLog simples já dá para fazer coisas bacanas, como gravar o horário que a planilha foi aberta e fechada, além do nome do usuário. Para isso é preciso editar os eventos Open e BeforeClose da pasta de trabalho:

Private Sub Workbook_Open()

    GravarLog "Planilha aberta por " & Environ("USERNAME")

End Sub

Private Sub Workbook_BeforeClose(Cancel As Boolean)

    GravarLog "Planilha fechada por " & Environ("USERNAME")

End Sub

Perceba que este código deverá ser gravado na pasta de trabalho, não em um módulo ou planilha. Caso contrário não irá funcionar da maneira esperada. Salve sua planilha e feche. O arquivo de log já deverá ter uma linha referente ao fechamento da planilha. Abra a planilha novamente e confira que gerou uma linha referente à abertura dela.

Essa sub-rotina GravarLog é bem simples, basta mandar um texto que ela vai registrar no arquivo. Porém, há ocasiões em que é necessário gravar várias linhas, como por exemplo para registrar um erro que aconteceu. Ainda é possível chamar a rotina várias vezes e registrar as linhas necessárias. Entretanto, o arquivo será aberto e fechado várias vezes durante o processo, causando uma perda de desempenho e sobrecarregando o disco com sucessivas aberturas e fechamentos. Neste caso, podemos alterar a rotina de três maneiras distintas:

- Usando parâmetros opcionais: neste caso será preciso criar estruturas de verificação para checar se os parâmetros adicionais foram enviados para criar as linhas adicionais;

- Usando um objeto do tipo type como parâmetro: neste caso as estruturas de verificação devem checar quais informações foram preenchidas e então gerar as linhas de acordo com  o que for recebido;

- Criar uma classe para a geração de log: este é o método mais sofisticado e que demandará mais habilidade do desenvolvedor, mas uma classe bem feita pode ser exportada e utilizada por virtualmente qualquer planilha.

Você pode exercitar suas habilidades em VBA criando versões diferentes para quaisquer uma das três possibilidades acima. Veja qual atende melhor as suas necessidades para o momento. Use em conjunto com On Error para registrar os erros não tratados no código para facilitar a averiguação de erros e assim poder solucioná-los de forma mais rápida.

Espero que este artigo seja de grande utilidade e que você comece a gerar arquivos de log pelo menos para registrar erros ainda não tratados. O registro dos erros é a melhor forma de descobrir o que deu errado e é o ponto de partida para identificar a causa e buscar a solução.

Quaisquer dúvidas, comentários ou sugestões, use a seção de comentários abaixo. Até o próximo artigo.


Pedro Martins

Formado em Tecnologia em Eletrônica Digital, já trabalhou como artefinalista, eletrotécnico, programador de CLP (para máquinas industriais) e analista de sistemas em sistema bancário, programando em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.






Postagem Anterior Próxima Postagem