Às vezes precisamos criar um log para saber as tabelas que estavam abertas e em quais registros estavam, hoje iremos demonstrar em como fazer isso.
Existem alguns processos no sistema, que acabam rodando e para rastrearmos algo, fica um pouco oneroso, como por exemplo, o da contabilização.
Então pensando nisso, como poderíamos gravar um log genérico, para saber em quais tabelas o sistema esta posicionado? A lógica seria:
- Na CT5, no campo desejado, colocar uma fórmula, por exemplo, u_zSuaFuncao()
- Dentro dessa função, acionar a chamada de uma rotina que irá gerar o log, por exemplo, MemoWrite(cPastaNoServidor, u_zLogAlias(1))
- Na função zLogAlias, pegue o conteúdo da variável pública cFOpened
- Faça um For, percorrendo até 511 alias (conforme documentação do TDN: https://tdn.totvs.com/display/tec/Alias)
- Através do comando Select() verifique se o alias está aberto
- Se sim, grave o conteúdo no log com o nome do alias e o recno posicionado (também com o índice usado e o conteúdo do índice)
Abaixo a função zLogAlias desenvolvida conforme a lógica acima (ela também foi adaptada para retornar um array, caso precisem):
//Bibliotecas #Include "TOTVS.ch" /*/{Protheus.doc} User Function zLogAlias Função que percorre todos os alias em memória para gravar em log @type Function @author Atilio @since 02/06/2022 @param nTipo, Numérico, Se for 1 irá retornar um texto de log e se não for irá retornar um array @obs Posições do array: [1] = Tabela (ex.: SB1) [2] = RecNo (ex.: 1342) [3] = Índice usado (ex.: 1) [4] = Campos que compõem o índice (ex.: B1_FILIAL + B1_COD) [5] = Chave do registro posicionado (ex.: ' 000001') /*/ User Function zLogAlias(nTipo) Local aArea := FWGetArea() Local cAbertos := cFOpened Local nAtual := 0 Local xLog := Nil Local cAliasAtu := "" Local nAliasRec := 0 Local nIndUsado := 0 Local cIndCampos := "" Local cIndChave := "" Local nMaximo := 511 Default nTipo := 1 If nTipo == 1 xLog := "Alias abertos (cFOpened): " + cAbertos + CRLF + CRLF xLog += "Alias encontrados na WorkArea: " + CRLF Else xLog := {} EndIf //Percorre 511 alias (conforme documentação em https://tdn.totvs.com/display/tec/Alias) For nAtual := 0 To nMaximo //Pega o alias da area atual cAliasAtu := Upper(Alias(nAtual)) //Somente se houver alias e Garantia para prevenir se realmente ta aberto, para não confiar apenas na variável pública If ! Empty(cAliasAtu) .And. Select(cAliasAtu) > 0 nIndUsado := (cAliasAtu)->(IndexOrd()) cIndCampos := StrTran((cAliasAtu)->(IndexKey(nIndUsado)), "+", " + ") cIndChave := (cAliasAtu)->( &(cIndCampos) ) nAliasRec := (cAliasAtu)->(RecNo()) //Pula o registro caso seja tabelas internas If Left(cAliasAtu, 3) == "MP_" .Or. ; Left(cAliasAtu, 6) == "MPUSR_" .Or. ; Left(cAliasAtu, 7) == "MPMENU_" .Or. ; Left(cAliasAtu, 6) == "MPGRP_" .Or. ; Left(cAliasAtu, 1) == "X" .Or. ; Left(cAliasAtu, 4) == "TPH_" .Or. ; Left(cAliasAtu, 9) == "PROFALIAS" Loop EndIf If nTipo == 1 xLog += "Tabela: " + cAliasAtu + ; "; Recno: " + cValToChar(nAliasRec) + ; "; Ordem: " + cValToChar(nIndUsado) +; "; Índice: " + cIndCampos +; "; Chave: '" + cIndChave + "'" +; CRLF Else aAdd(xLog, {; cAliasAtu,; nAliasRec,; nIndUsado,; cIndCampos,; cIndChave; }) EndIf EndIf Next FWRestArea(aArea) Return xLog
Abaixo um print de como é o resultado, por exemplo, acionando na tela de cadastro de produtos.
Uma dica interessante, seria aproveitar a ideia do Canivete de Atalhos, e adicionar essa função em um atalho para já exibir em tela as tabelas abertas, conforme exemplo abaixo:
SetKey(K_SH_F12, { || ShowLog(u_zLogAlias()) })
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Bom dia Daniel, só uma observação, como ainda não executei seu exemplo, não sei se há relevância, mas no TDN sobre o comando Alias(), ele vai de 0 (zero) até 511, mas no seu fonte, você inicia de 1, então a posição 0 (zero) nunca será pesquisada. Também não entendi onde deve ser colocada a função. Seria no campo X2_ROTINA da CT5 ou em algum ponto de entrada?
Bom dia Klaus, tudo joia?
Opa, obrigado pelo aviso, já atualizei o exemplo para começar com 0 ao invés de 1.
Quanto ao exemplo, vamos supor que dentro de um registro seu da CT5, no campo CT5_DEBITO tem a função u_zDebito(). Ai dentro dessa função, você adicionaria o comando para ver as tabelas que estão na memória, por exemplo:
Mas você pode acionar também em pontos de entrada ou em outras rotinas, pois ela funciona de forma genérica.
Grande abraço.