Resetar senha do Administrador do Protheus

Dica de ouro para quando esquecemos a senha de admin do Protheus, mas não podemos nos dar ao luxo de descartar todo o arquivo de senhas e, consequentemente, os perfis de usuários.

Siga os passos abaixo à risca:

1) Renomeie o arquivo sigapss.spf na pasta system e guarde-o.

2) Abra o configurador para que o sistema recrie o arquivo permitindo a entrada com usuário admin e senha em branco.

3) Saia do sistema.

4) Crie e compile o fonte:

#INCLUDE "TOTVS.CH"

User Function SPFCLOSE()

    SPF_CLOSE("SIGAPSS.SPF")

Return( Nil )

5) Entre novamente no SIGACFG e acesse a o cadastro de Fórmulas.

6) Inclua uma fórmula, digite na função U_SPFCLOSE() e pressione ENTER.

7) Ainda com o Cadastro de Fórmulas aberto, vá até a system para excluir o arquivo recém criado sigapss.spf e renomeie novamente o arquivo original.

8) Ainda no SIGACFG, cancele o cadastro e saia da rotina de Fórmulas. Acesse o cadastro de usuários, altere o Administrador e defina a senha livremente.

Perguntas – Função PutSX1

Eu sei que essa todos sabem e, além disso, ouvi dizer que será continuada. Não sei se é boato. Mas por enquanto ainda funciona no Protheus 12. Então vou deixar registrado aqui esse exemplo para consulta de referência com campos Data De, Data Até, Código de Produto e uma Combobox.

// Função para validar se a pergunta existe, caso contrario o sistema irá cria-lá
*****************************************
Static Function fPergunta(cPerg)
*****************************************

//PutSx1(cGrupo,cOrdem,cPergunt         ,cPerSpa,cPerEng,cVar     ,cTipo,nTamanho,nDecimal,nPresel,cGSC,cValid    ,cF3  ,cGrpSxg    ,cPyme,cVar01    ,cDef01      ,cDefSpa1,cDefEng1,cCnt01,cDef02     ,cDefSpa2,cDefEng2,cDef03      ,cDefSpa3    ,cDefEng3    ,cDef04   ,cDefSpa4,cDefEng4,cDef05,cDefSpa5,cDefEng5,aHelpPor,aHelpEng,aHelpSpa,cHelp)
  PutSx1(cPerg ,"01"  ,"Data Inicial  ?",""     ,""     ,"mv_ch1" ,"D"  ,08      ,00      ,0      ,"G" ,""        ,""   ,""         ,""   ,"mv_par01",""          ,""      ,""      ,""    ,""         ,""      ,""      ,""          ,""          ,""          ,""       ,""      ,""      ,""    ,""      ,""      ,""      ,""      ,""      ,"")
  PutSx1(cPerg ,"02"  ,"Data Final    ?",""     ,""     ,"mv_ch2" ,"D"  ,08      ,00      ,0      ,"G" ,"NaoVazio",""   ,""         ,""   ,"mv_par02",""          ,""      ,""      ,""    ,""         ,""      ,""      ,""          ,""          ,""          ,""       ,""      ,""      ,""    ,""      ,""      ,""      ,""      ,""      ,"")
  PutSx1(cPerg ,"03"  ,"Produto	      ?",""     ,""     ,"mv_ch3" ,"D"  ,08      ,00      ,0      ,"G" ,"NaoVazio","SB1",""         ,""   ,"mv_par03",""          ,""      ,""      ,""    ,""         ,""      ,""      ,""          ,""          ,""          ,""       ,""      ,""      ,""    ,""      ,""      ,""      ,""      ,""      ,"")
  PutSx1(cPerg ,"04"  ,"Bloqueados    ?",""     ,""     ,"mv_ch4" ,"N"  ,01      ,00      ,0      ,"C" ,""        ,""   ,""         ,""   ,"mv_par04","Todos"     ,"Todos" ,"Todos" ,""    ,"Ativos"   ,"Ativos","Ativos","Bloqueados","Bloqueados","Bloqueados",""       ,""      ,""      ,""    ,""      ,""      ,""      ,""      ,""      ,"")

Return

TDS, AutoComplete e Perfomance

Pessoal,

Não sei vocês, mas o AutoComplete do TDS está me deixando louco. Toda hora o TDS fica lento e/ou trava e finalmente descobri que o vilão era realmente o AutoComplete que fica olhando no RPO todas as funções compiladas.

Olha, é um recurso muito legal, mas pra mim não tá dando não rsrs

Então segue dica rápida pra desabilitar, caso você também esteja tendo problemas.

No TDS acesse Janela / Preferências depois em Developer Studio na barra lateral e enfim AutoComplete. Pronto, desabilite e perceba se vai melhorar pra você também.

TDS-autocomplete

Forte abraço e até a próxima dica 😉

Pictures (máscaras) de campos

As máscaras começam sempre com @

Use @R para gravar apenas números (excluir caracteres ex. ponto, vírgula, barras) no banco.

Exemplo para um campo de CPF:

@R 999.999.999-99 // Onde 9 significa qualquer caractere numérico.

Segue a tabela com todos os parâmetros possíveis (retirada do TDN):

Caractere Descrição

A

Permite somente caracteres  alfa.

N

Permite somente caracteres  alfa e número.

X

Permite qualquer caractere

9

Permite dígitos de qualquer tipo incluído sinal

#

Permite dígitos, sinais e espaços para qualquer tipo de dado

L

Permite apenas Y,N, T e F

Y

Permite apenas Y,N

!

Converte caracteres alfa em maiúscula

$

Exibe o sinal de dólar

.

Exibe um ponto decimal

,

Exibe uma virgula

R

Insere caracteres  mais não salva no campo de dado.

Para campos numéricos que contenham decimal, é obrigatório o uso do @E seguido da máscara com pontos e vírgulas invertidos (padrão americano), exemplo:

@E 99,999,999.99 // os pontos e as vírgulas serão invertidos na visualização

Os separadores de milhar são opcionais. E lembre-se de casar o número de caracteres numéricos da máscara com o tamanho real do campo quando estiver criando ou alterando no configurador.

 

Informações retiradas do TDN: https://goo.gl/EPs2Ro

Chamar Static Function no aRotina

Segue exemplo de como chamar uma Static Function no vetor aRotina:

Private bVisuali := {|| fCad(2) }
Private bIncluir := {|| fCad(3) }
Private bAlterar := {|| fCad(4) }
Private bExcluir := {|| fCad(5) } 
Private bFirmar :=  {|| fFirmar() } 
Private bImprime := {|| fImprime() }
 
Private aRotina := {{"Pesquisar"  , "AxPesqui"       , 0 , 1 },;
                    {"Visualizar" , "Eval(bVisuali)" , 0 , 2 },;
                    {"Incluir"    , "Eval(bIncluir)" , 0 , 3 },;
                    {"Alterar"    , "Eval(bAlterar)" , 0 , 4 },;
                    {"Excluir"    , "Eval(bExcluir)" , 0 , 5 },;
                    {"Firmar"     , "Eval(bFirmar)"  , 0 , 6 },;
                    {"Imprimir"   , "Eval(bImprime)" , 0 , 7 }}

Neste exemplo as funções fCad, fFirmar e fImprime são estáticas.

Exportar planilha do Excel usando FWMsExcel

exportexcelOlá meus amigos. A seguir, informações para exportarmos planilha do Excel de uma maneira mais profissional.

O objeto FWMsExcel fornece métodos para criação de arquivo XML compatível com as versões do MS Excel 2003, superiores e alternativos. Com ele é possível criar abas, tabelas, e colunas. Manipular cores e fontes inclusive.

Segue um exemplo muito simples de exportação para planilha do Excel utilizando o objeto FWMsExcel:

Local cArquivo  := "RELAT_FINANC.XLS"
Local oExcelApp := Nil
Local cPath     := "C:\WINDOWS\TEMP\"
Local nTotal    := 0
Local oExcel
Local oExcelApp

aColunas := {}
aLocais := {} 
oBrush1 := TBrush():New(, RGB(193,205,205))
 
// Verifica se o Excel está instalado na máquina
 
If !ApOleClient("MSExcel")

    MsgAlert("Microsoft Excel não instalado!")
    Return

EndIf

oExcel  := FWMSExcel():New()
cAba    := "Contas a Receber"
cTabela := "Titulos"

// Criação de nova aba 
oExcel:AddworkSheet(cAba)

// Criação de tabela
oExcel:AddTable (cAba,cTabela)

// Criação de colunas 
oExcel:AddColumn(cAba,cTabela,"Dt.Emissao" ,1,4,.F.) 
oExcel:AddColumn(cAba,cTabela,"Prefixo"    ,2,1,.F.) 
oExcel:AddColumn(cAba,cTabela,"Titulo"     ,2,1,.F.) 
oExcel:AddColumn(cAba,cTabela,"Parcela"    ,2,1,.F.) 
oExcel:AddColumn(cAba,cTabela,"Valor"      ,3,2,.T.) 

While !SE1->(Eof())
 
    // Criação de Linhas 
    oExcel:AddRow(cAba,cTabela, { DtoC(SE1->E1_EMISSAO) ,;
                                  SE1->PREFIXO ,; 
                                  SE1->TITULO ,; 
                                  SE1->PARCELA ,; 
                                  SE1->E1_VALOR })

    SE1->(dbSkip())

End

If !Empty(oExcel:aWorkSheet)

    oExcel:Activate()
    oExcel:GetXMLFile(cArquivo)
 
    CpyS2T("\SYSTEM\"+cArquivo, cPath)

    oExcelApp := MsExcel():New()
    oExcelApp:WorkBooks:Open(cPath+cArquivo) // Abre a planilha
    oExcelApp:SetVisible(.T.)

EndIf

Veja mais sobre o objeto FWMsExcel no TDN:
http://tdn.totvs.com/display/public/mp/FWMsExcel

Usando TCLink para conectar a outra base de dados

php-db-connection

Olá meus amigos! Andei um pouco sumido, mas vou me esforçar em continuar postando conteúdo por aqui. Vamos falar de conexão com outros bancos de dados de dentro do Protheus.

Com as funções AdvConnection(), TCLink() e TcSetConn() podemos nos conectar a outras bases de dados através do DBAccess (TopConnect). Lembrando que primeiramente temos que seguir a configuração padrão que é criar a conexão ODBC no servidor onde está instalado o DBAccess e depois configurar no próprio DBMonitor como já fazemos com a base Protheus.

No nosso fonte, bastará alternar entre os bancos de dados para realizar consultas e comandos SQLs. Veja abaixo um exemplo simples para se conectar a um banco que chamamos de GRUPOBI onde o DBAccess se encontra no mesmo servidor da aplicação escutando na porta 7890.

Local cConexao    := SuperGetMV("MV_XXCON01", .F., "MSSQL/GRUPOBI")
Local cServerAddr := SuperGetMV("MV_XXCON02", .F., "localhost")
Local nPort       := Val(SuperGetMV("MV_XXCON03", .F., "7890"))

If Type("_nTopProtheus") == "U"

    Public _nTopProtheus

    _nTopProtheus := AdvConnection() // obtém o ID da conexão atual

EndIf

If Type("_nTopGrupoBI") == "U"

    Public _nTopGrupoBI

    MsgRun("Conectando a Grupo BI...","Conexão",;
        {|| _nTopGrupoBI := TcLink(cConexao,cServerAddr,nPort) })

    If _nTopGrupoBI < 0

        MsgAlert("Não foi possível se conectar com Grupo BI. "+;
                 "Essa falha pode ocorrer devido ao número de licenças excedidas. "+;
                 "Tente mais tarde ou contate o administrador do sistema.")

        Return .F.

    EndIf

EndIf

TcSetConn(_nTopGrupoBI) // Utilize essa função para alternar entre as conexões

Você precisará de permissão para criação de tabelas no banco, pois o Protheus criará automaticamente nesta base as seguintes tabelas de controle do DBAccess: TOP_PARAM, TOP_SP, TOP_VIRTUALIDX, TOP_FIELD e TOP_IDXSTATS.

Vejam mais informações no TDN: http://tdn.totvs.com/display/tec/TCSetConn

Controle de Semáforo no Protheus

O controle de semáforo no Protheus é feito utiizando-se duas funções:

LockByName (para criar um semáforo)
http://tdn.totvs.com/pages/releaseview.action?pageId=6814894

UnlockByName (para liberar o semáforo criado)
http://tdn.totvs.com/pages/releaseview.action?pageId=6814897

O conceito é o seguinte. Quando for iniciar a rotina verifique se pode criar um semáforo dessa forma:

If !LockByName("NOME_DA_SUA_ROTINA",.F.,.F.,.T.)
    MsgAlert("Rotina está sendo executada por outro usuário.")
    Return
EndIf

Ao final da rotina desative o semáforo. Senão não vai conseguir rodar mais a rotina. Dessa forma:

UnLockByName("NOME_DA_SUA_ROTINA",.F.,.F.,.T.)

Em caso de queda de conexão e travamento dos semáforos, existe a pasta semaforo no Protheus_Data. Será necessário parar o serviço, apagar os arquivos e iniciar novamente o serviço. Isso resolve qualquer problema de semáforos padrões do sistema inclusive.

Essa dica foi enviada pelo amigo, consultor e programador Bruno Sobral, que pediu para não colocar os créditos, mas eu sou teimoso. Abraços 😉

Tabela de Cores

Para nossa referência futura:

CLR_YELLOW    16   Amarelo
CLR_BLUE       2   Azul
CLR_HBLUE     11   Azul Claro
CLR_WHITE     17   Branco
CLR_CYAN       4   Ciano
CLR_HCYAN     13   Ciano Claro
CLR_GRAY      10   Cinza
CLR_HGRAY      8   Cinza Claro
CLR_MAGENTA    6   Magenta
CLR_HMAGENTA  15   Magenta Claro
CLR_BROWN      7   Marrom
CLR_BLACK      1   Preto
CLR_GREEN      3   Verde
CLR_HGREEN    12   Verde Claro
CLR_RED        5   Vermellho
CLR_HRED      14   Vermelho Claro

Tela básica com TCBrowse

O intuito deste post é oferecer um exemplo básico de tela em ADVPL contendo um Say, um Get, uma Enchoice e um TCBrowse (com cores) da maneira mais simples possível, sem definir fontes, tamanhos e posicionamentos relativos, etc. A idéia é servir para uma referência rápida. Segue:


Local oVerde    := LoadBitmap(GetResources(),'BR_VERDE')    
Local oAmarelo  := LoadBitmap(GetResources(),'BR_AMARELO') 
Local oVermelho := LoadBitmap(GetResources(),'BR_VERMELHO') 
Local oPreto    := LoadBitmap(GetResources(),'BR_PRETO') 
Local oAzul     := LoadBitmap(GetResources(),'BR_AZUL') 

Private _cIDCons := "ABC123"

oDlg := MSDialog():New(0,0,350,552,"Consulta",,,.F.,,,,,,.T.,,,.T. )
oDlg:bInit := {||EnchoiceBar(oDlg,{||oDlg:End()},{|| oDlg:End()},,)}

oSay := TSay():New(10,05,{||'Código da consulta:'},oDlg,,/*oFont*/,,,,.T.,/*CLR_BLACK*/,/*CLR_WHITE*/,50,10)
oGet := TGet():New(08,55,{||_cIDCons},oDlg,040,009,"@!",,0,,,.F.,,.T.,,.F.,,.F.,.F.,,.T.,.F.,,_cIDCons,,,, )

aBrowse := {{oAzul,"Nome","Antônio Gustavo"},;
            {oVerde,"Endereço","Rua A, 123 casa 4"},;
            {oVermelho,"Telefone","(21) 99583-1283"}}

oBrowse := TCBrowse():New( 25 , 5, 270, 135,,;
                          {'','Consulta','Resultado'},{20,150,50},;

oDlg,,,,,{||},,,,,,,.F.,,.T.,,.F.,,, )

oBrowse:SetArray(aBrowse)

oBrowse:bLine := {||{ aBrowse[oBrowse:nAt,01],;
                      aBrowse[oBrowse:nAt,02],;
                      aBrowse[oBrowse:nAt,03] } }

oDlg:Activate(,,,.T.)