Olá pessoal…
Recentemente desenvolvi uma rotina, em que, ao colar uma consulta sql, basta clicar em um botão Gerar, e ele gera um código .prw completo para compilação e utilização.
A intenção é que quando temos a consulta sql pronta, possamos fazer um relatório rapidamente.
Ao executar o zReport, é mostrado a tela, tendo duas abas, a primeira são as definições do relatório (como orientação padrão, título, se irá enviar por e-Mail, etc).
A segunda aba, é a de dados, onde é possível informar a consulta SQL, agrupamento e totalizadores.
Ao gerar, será perguntado se deseja abrir o arquivo.
Ao compilar o arquivo gerado, ele será um TReport normal, com as possibilidades de gerar pdf, planilha, etc.
Abaixo um print da impressão.
Agora, caso você tenha uma consulta “SELECT * FROM …” e deseja especificar as colunas mais detalhadamente (inclusive com opções de cores), insira a consulta e marque a opção “Deseja informar as colunas manualmente?”, e informe os dados necessários.
Por último, basta imprimir. Abaixo um print de exemplo.
Caso queira fazer o download do .prw, acesse aqui.
Abaixo o código fonte completo:
//Bibliotecas #Include "Protheus.ch" #Include "TopConn.ch" //Constantes #Define STR_PULA Chr(13)+Chr(10) /*/{Protheus.doc} zReport Função que gera TOTVS Report de forma genérica @type function @author Atilio @since 17/12/2016 @version 1.0 @example u_zReport() /*/ User Function zReport() Local aArea := GetArea() //Grupos Local oGrpGer Local oGrpDef Local oGrpPar Local oGrpEma Private cAutor := "zReport" Private cData := dToC(Date()) //Dimensões da janela Private nJanLarg := 800 Private nJanAltu := 500 //Outros Objetos e variáveis Private oDlgPvt Private oBtnFec Private oBtnGer Private aTpPad := {"S=Sim", "N=Nao"} //Campos do grupo Geral Private oSayUserF, oGetUserF, cGetUserF := "xRelat" + Space(2) Private oSayDirec, oGetDirec, cGetDirec := GetTempPath() Private oSayTitul, oGetTitul, cGetTitul := "Relatorio" + Space(21) Private nLenDirec := 120 //Campos do grupo Definições Private aTpOri := {"R=Retrato", "P=Paisagem"} Private aTpFon := {"P=Padrao", "1=Padrao. Tamanho 8", "2=Padrao. Tamanho 12"} Private oSayOrien, oCmbOrien, cCmbOrien := "R" Private oSayFonte, oCmbFonte, cCmbFonte := "P" //Campos do grupo Parâmetros Private oSayUtili, oCmbUtili, cCmbUtili := "N" Private oSayPergu, oGetPergu, cGetPergu := Space(10) Private oSayMostr, oCmbMostr, cCmbMostr := "N" //Campos do grupo de e-Mail Private oSayEnvia, oCmbEnvia, cCmbEnvia := "N" Private oSayEmail, oGetEmail, cGetEmail := Space(100) //Campos da aba do SQL Private oSaySQL, oPanelSQL, oEditSQL, cEditSQL := "" Private oSayQuebr, oGetQuebr, cGetQuebr := Space(30) Private oChkEdit, lChkEdit := .F. Private oMsGetCam Private aHeaderCam := {} Private aColsCam := {} Private oChkTot, lChkTot := .F. Private oMsGetTot Private aHeaderTot := {} Private aColsTot := {} //Barras de Rolagem e abas Private oFolderPvt Private oScrollRel Private oScrollSQL //Campos para informar manualmente // Titulo Campo Picture Tamanho Dec Valid Usado Tipo F3 Contexto Combo Ini Padrão aAdd(aHeaderCam,{ "Campo", "XX_CAMPO", "", 010, 0, ".T.", ".T.", "C", "", "", "", ""} ) aAdd(aHeaderCam,{ "Titulo", "XX_TITUL", "", 020, 0, ".T.", ".T.", "C", "", "", "", ""} ) aAdd(aHeaderCam,{ "Mascara", "XX_MASCA", "", 020, 0, ".T.", ".T.", "C", "", "", "", ""} ) aAdd(aHeaderCam,{ "Tamanho", "XX_TAMCP", "@E 999", 003, 0, "Positivo()", ".T.", "N", "", "", "", ""} ) aAdd(aHeaderCam,{ "Alinhamento", "XX_ALINH", "", 001, 0, ".T.", ".T.", "C", "", "", "0=Padrao;1=Esquerda;2=Direita;3=Centralizado", "'0'"} ) aAdd(aHeaderCam,{ "Quebra a Linha?", "XX_QUEBR", "", 001, 0, ".T.", ".T.", "C", "", "", "S=Sim;N=Nao", "'N'"} ) aAdd(aHeaderCam,{ "Cor de Fundo", "XX_FUNDO", "", 001, 0, ".T.", ".T.", "C", "", "", "0=Padrao;1=Preto;2=Branco;3=Vermelho;4=Verde;5=Azul", "'0'"} ) aAdd(aHeaderCam,{ "Cor da Fonte", "XX_FONTE", "", 001, 0, ".T.", ".T.", "C", "", "", "0=Padrao;1=Preto;2=Branco;3=Vermelho;4=Verde;5=Azul", "'0'"} ) aAdd(aHeaderCam,{ "Negrito?", "XX_NEGRI", "", 001, 0, ".T.", ".T.", "C", "", "", "S=Sim;N=Nao", "'N'"} ) //Campos para totalizar // Titulo Campo Picture Tamanho Dec Valid Usado Tipo F3 Contexto Combo Ini Padrão aAdd(aHeaderTot,{ "Campo", "XX_CAMPO", "", 010, 0, ".T.", ".T.", "C", "", "", "", ""} ) aAdd(aHeaderTot,{ "Mascara", "XX_MASCA", "", 020, 0, ".T.", ".T.", "C", "", "", "", ""} ) aAdd(aHeaderTot,{ "Totalizar", "XX_TOTAL", "", 001, 0, ".T.", ".T.", "C", "", "", "0=Soma (SUM);1=Contar (COUNT);2=Maximo (MAX);3=Minimo (MIN);4=Media (AVERAGE)", "'0'"} ) //Deixando com espaços a direita cGetDirec := PadR(cGetDirec, nLenDirec) //Criando a janela DEFINE MSDIALOG oDlgPvt TITLE "zReport - Gerador de TOTVS Report" FROM 000, 000 TO nJanAltu, nJanLarg COLORS 0, 16777215 PIXEL //Folders / Pastas @ 001, 003 FOLDER oFolderPvt SIZE (nJanLarg/2)-4, (nJanAltu/2)-30 OF oDlgPvt ITEMS "Relatório",; "Dados - SQL" COLORS 0, 14215660 PIXEL //Criando barras de rolagem @ 001, 003 SCROLLBOX oScrollRel HORIZONTAL VERTICAL SIZE (nJanAltu/2)-45, (nJanLarg/2)-13 OF oFolderPvt:aDialogs[1] @ 001, 003 SCROLLBOX oScrollSQL HORIZONTAL VERTICAL SIZE (nJanAltu/2)-45, (nJanLarg/2)-13 OF oFolderPvt:aDialogs[2] //Aba do Relatório, Grupo Geral @ 001, 001 GROUP oGrpGer TO 055, (nJanLarg/2)-24 PROMPT "Geral: " OF oScrollRel COLOR RGB(255,0,0), 16777215 PIXEL @ 013, 006 SAY oSayUserF PROMPT "User Function:" SIZE 040, 007 OF oScrollRel PIXEL @ 011, 045 MSGET oGetUserF VAR cGetUserF SIZE 040, 007 OF oScrollRel COLORS 0, 16777215 PIXEL @ 028, 006 SAY oSayDirec PROMPT "Diretório:" SIZE 030, 007 OF oScrollRel PIXEL @ 026, 045 MSGET oGetDirec VAR cGetDirec SIZE 250, 007 OF oScrollRel COLORS 0, 16777215 VALID (fVldDir()) PIXEL @ 043, 006 SAY oSayTitul PROMPT "Título:" SIZE 030, 007 OF oScrollRel PIXEL @ 041, 045 MSGET oGetTitul VAR cGetTitul SIZE 130, 007 OF oScrollRel COLORS 0, 16777215 PIXEL //Aba do Relatório, Grupo Definições @ 058, 001 GROUP oGrpDef TO 097, (nJanLarg/2)-24 PROMPT "Definições: " OF oScrollRel COLOR RGB(255,0,0), 16777215 PIXEL @ 070, 006 SAY oSayOrien PROMPT "Orientação Padrão:" SIZE 060, 007 OF oScrollRel PIXEL @ 068, 055 MSCOMBOBOX oCmbOrien VAR cCmbOrien ITEMS aTpOri SIZE 040, 007 OF oScrollRel COLORS 0, 16777215 PIXEL @ 085, 006 SAY oSayFonte PROMPT "Fonte Utilizada:" SIZE 060, 007 OF oScrollRel PIXEL @ 083, 055 MSCOMBOBOX oCmbFonte VAR cCmbFonte ITEMS aTpFon SIZE 060, 007 OF oScrollRel COLORS 0, 16777215 PIXEL //Aba do Relatório, Grupo de Parâmetros @ 100, 001 GROUP oGrpPar TO 154, (nJanLarg/2)-24 PROMPT "Parâmetros: " OF oScrollRel COLOR RGB(255,0,0), 16777215 PIXEL @ 112, 006 SAY oSayUtili PROMPT "Utiliza Grupo de Perguntas?" SIZE 080, 007 OF oScrollRel PIXEL @ 110, 085 MSCOMBOBOX oCmbUtili VAR cCmbUtili ITEMS aTpPad SIZE 030, 007 OF oScrollRel COLORS 0, 16777215 VALID (fVldPer()) PIXEL @ 127, 006 SAY oSayPergu PROMPT "Código Grupo de Perguntas:" SIZE 040, 007 OF oScrollRel PIXEL @ 125, 085 MSGET oGetPergu VAR cGetPergu SIZE 060, 007 OF oScrollRel COLORS 0, 16777215 PIXEL @ 142, 006 SAY oSayMostr PROMPT "Mostra página de Parâmetros?" SIZE 080, 007 OF oScrollRel PIXEL @ 140, 085 MSCOMBOBOX oCmbMostr VAR cCmbMostr ITEMS aTpPad SIZE 030, 007 OF oScrollRel COLORS 0, 16777215 PIXEL oGetPergu:lActive := .F. oCmbMostr:lActive := .F. //Aba do Relatório, Grupo de e-Mails @ 157, 001 GROUP oGrpEma TO 196, (nJanLarg/2)-24 PROMPT "e-Mail: " OF oScrollRel COLOR RGB(255,0,0), 16777215 PIXEL @ 169, 006 SAY oSayEnvia PROMPT "Envia por e-Mail?" SIZE 080, 007 OF oScrollRel PIXEL @ 167, 075 MSCOMBOBOX oCmbEnvia VAR cCmbEnvia ITEMS aTpPad SIZE 030, 007 OF oScrollRel COLORS 0, 16777215 VALID (fVldEma()) PIXEL @ 184, 006 SAY oSayEmail PROMPT "e-Mails (separados por ';'):" SIZE 080, 007 OF oScrollRel PIXEL @ 182, 075 MSGET oGetEmail VAR cGetEmail SIZE 140, 007 OF oScrollRel COLORS 0, 16777215 PIXEL oGetEmail:lActive := .F. //Aba de dados, get referente ao SQL @ 006, 003 SAY oSaySQL PROMPT "Consulta SQL:" SIZE 040, 007 OF oScrollSQL PIXEL oPanelSQL := tPanel():New(001, 045, "", oScrollSQL, , , , RGB(000,000,000), RGB(254,254,254), 330, 060) oEditSQL := tSimpleEditor():New( 000,; //nRow 000,; //nCol oPanelSQL,; //oWnd 330,; //nWidth 060,; //nHeight cEditSQL,; //cText .F. ) //lReadOnly oEditSQL:bValid := {|| fVldSQL()} oEditSQL:TextFormat(2) @ 065, 001 SAY oSayQuebr PROMPT "Quebrar relatório por:" SIZE 060, 007 OF oScrollSQL PIXEL @ 063, 072 MSGET oGetQuebr VAR cGetQuebr SIZE 100, 007 OF oScrollSQL COLORS 0, 16777215 PIXEL //Edição de colunas @ 075, 001 CHECKBOX oChkEdit VAR lChkEdit PROMPT "Deseja informar as colunas manualmente?" SIZE 115, 007 OF oScrollSQL COLORS 0, 16777215 PIXEL oChkEdit:bChange := {|| fVldChkEdt()} oMsGetCam := MsNewGetDados():New( 085,; //nTop 003,; //nLeft 145,; //nBottom 373,; //nRight GD_INSERT+GD_DELETE+GD_UPDATE,; //nStyle "AllwaysTrue()",; //cLinhaOk ,; //cTudoOk "",; //cIniCpos ,; //aAlter ,; //nFreeze 99,; //nMax ,; //cFieldOK ,; //cSuperDel ,; //cDelOk oScrollSQL,; //oWnd aHeaderCam,; //aHeader aColsCam) //aCols oMsGetCam:lActive := .F. //Totalizadores @ 150, 001 CHECKBOX oChkTot VAR lChkTot PROMPT "Deseja totalizar colunas?" SIZE 115, 007 OF oScrollSQL COLORS 0, 16777215 PIXEL oChkTot:bChange := {|| fVldChkTot()} oMsGetTot := MsNewGetDados():New( 160,; //nTop 003,; //nLeft 200,; //nBottom 373,; //nRight GD_INSERT+GD_DELETE+GD_UPDATE,; //nStyle "AllwaysTrue()",; //cLinhaOk ,; //cTudoOk "",; //cIniCpos ,; //aAlter ,; //nFreeze 99,; //nMax ,; //cFieldOK ,; //cSuperDel ,; //cDelOk oScrollSQL,; //oWnd aHeaderTot,; //aHeader aColsTot) //aCols oMsGetTot:lActive := .F. //Ações @ (nJanAltu/2)-27, 003 GROUP oGrpAco TO (nJanAltu/2)-1, (nJanLarg/2)-1 PROMPT "Ações: " OF oDlgPvt COLOR 0, 16777215 PIXEL //Botões @ (nJanAltu/2)-21, (nJanLarg/2)-(61*1) BUTTON oBtnFec PROMPT "Fechar" SIZE 058, 017 OF oDlgPvt ACTION(oDlgPvt:End()) PIXEL @ (nJanAltu/2)-21, (nJanLarg/2)-(61*2) BUTTON oBtnFec PROMPT "Gerar" SIZE 058, 017 OF oDlgPvt ACTION(fGerar()) PIXEL //Mudando o foco para user function oGetUserF:SetFocus() ACTIVATE MSDIALOG oDlgPvt CENTERED RestArea(aArea) Return /*---------------------------------------------------------------------* | Func: fVldDir | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida o diretório digitado | *---------------------------------------------------------------------*/ Static Function fVldDir() Local lRet := .T. //Se tiver em branco, já retorna falha If Empty(cGetDirec) MsgAlert("Preencha um diretório") lRet := .F. Else //Se o diretório não existir If ! ExistDir(cGetDirec) //Se for confirmado tenta criar If MsgYesNo("O diretório informado não existe, deseja criar?", "Atenção") MakeDir(cGetDirec) //Se mesmo assim o diretório não existir, retorna falso If ! ExistDir(cGetDirec) MsgAlert("Não foi possível criar o diretório.", "Atenção") lRet := .F. EndIf Else lRet := .F. EndIf EndIf EndIf //Se for retornar exito If lRet cGetDirec := Alltrim(cGetDirec) //Tratamento para adicionar barra If SubStr(cGetDirec, Len(cGetDirec), 1) != '\' cGetDirec += '\' EndIf //Tratamento para adicionar espaços em branco cGetDirec := PadR(cGetDirec, nLenDirec) oGetDirec:Refresh() EndIf Return lRet /*---------------------------------------------------------------------* | Func: fVldPer | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida se utilizará pergunta / parâmetros | *---------------------------------------------------------------------*/ Static Function fVldPer() Local lRet := .T. //Se vai utilizar, habilita componentes If cCmbUtili == 'S' oGetPergu:lActive := .T. oCmbMostr:lActive := .T. //Senão, desabilita Else oGetPergu:lActive := .F. oCmbMostr:lActive := .F. EndIf //Atualiza os componentes oGetPergu:Refresh() oCmbMostr:Refresh() oGetPergu:SetFocus() Return lRet /*---------------------------------------------------------------------* | Func: fVldEma | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida se utilizará disparo por e-Mail | *---------------------------------------------------------------------*/ Static Function fVldEma() Local lRet := .T. //Se vai utilizar, habilita componentes If cCmbEnvia == 'S' oGetEmail:lActive := .T. //Senão, desabilita Else oGetEmail:lActive := .F. EndIf //Atualiza os componentes oGetEmail:Refresh() oGetEmail:SetFocus() Return lRet /*---------------------------------------------------------------------* | Func: fVldSQL | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida a query SQL digitada | *---------------------------------------------------------------------*/ Static Function fVldSQL() Local lRet := .T. //Atualiza o texto cEditSQL := Upper(oEditSQL:RetText()) oEditSQL:Load(cEditSQL) oEditSQL:Refresh() Return lRet /*---------------------------------------------------------------------* | Func: fVldChkEdt | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida o check de edição | *---------------------------------------------------------------------*/ Static Function fVldChkEdt() Local lRet := .T. //Se tiver checado que irá informar as colunas If lChkEdit oMsGetCam:lActive := .T. //Senão Else oMsGetCam:lActive := .F. EndIf oMsGetCam:Refresh() Return lRet /*---------------------------------------------------------------------* | Func: fVldChkTot | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que valida o check de totalizadores | *---------------------------------------------------------------------*/ Static Function fVldChkTot() Local lRet := .T. //Se tiver checado que irá informar as colunas If lChkTot oMsGetTot:lActive := .T. //Senão Else oMsGetTot:lActive := .F. EndIf oMsGetTot:Refresh() Return lRet /*---------------------------------------------------------------------* | Func: fGerar | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que que valida a geração do arquivo prw | *---------------------------------------------------------------------*/ Static Function fGerar() Local nOK := 0 Local nAtual := 0 Local aDadCel := oMsGetCam:aCols Local nPosCam := aScan(aHeaderCam, {|x| AllTrim(Upper(x[2])) == "XX_CAMPO"}) Local nPosTam := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_TAMCP"}) cEditSQL := Alltrim(Upper(oEditSQL:RetText())) //Se estiver marcado para utilizar parâmetros, porém a pergunta estiver vazia If cCmbUtili == 'S' .And. Empty(cGetPergu) MsgAlert("Preencha o código do grupo de perguntas!", "Atenção") Return EndIf //Se estiver marcado para enviar email, porém o destinatário estiver vazio If cCmbEnvia == 'S' .And. Empty(cGetEmail) MsgAlert("Preencha o(s) e-Mail(s) que receberão o relatório!", "Atenção") Return EndIf //Se não tiver consulta sql If Empty(cEditSQL) MsgAlert("Insira uma consulta SQL!", "Atenção") Return EndIf //Se for informado manualmente, verifica se tem alguma coluna em branco If lChkEdit .And. Len(aDadCel) > 0 //Percorre os dados For nAtual := 1 To Len(aDadCel) //Se a linha não estiver excluída If ! aDadCel[nAtual][Len(aHeaderCam) + 1] //Se tiver campo, incrementa If ! Empty(aDadCel[nAtual][nPosCam]) .And. aDadCel[nAtual][nPosTam] != 0 nOk++ EndIf EndIf Next If nOk == 0 MsgAlert("Não existem campos válidos para impressão (verifique campo e/ou tamanho)!", "Atenção") Return EndIf EndIf //Chama a criação do prw MsAguarde({|| fCriaPrw()}, "Aguarde...", "Criando o .prw", .T.) Return /*---------------------------------------------------------------------* | Func: fCriaPrw | | Autor: Daniel Atilio | | Data: 17/12/2016 | | Desc: Função que gera o prw com as definições do TOTVS Report | *---------------------------------------------------------------------*/ Static Function fCriaPrw() Local cArquivo := Alltrim(cGetUserF)+".prw" Local nHdl := 0 Local aStrutAux := {} Local aDadCel := oMsGetCam:aCols Local aDadTot := oMsGetTot:aCols Local nAtual := 0 Local aAreaX3 := SX3->(GetArea()) Local cTitulo := "" Local cPicture := "" Local cTamanho := "" Local cAlinham := "" Local cQuebr := "" Local cFundo := "" Local cFonte := "" Local cNegrito := "" Local cTotal := "" Local cQuebra := "" Local nPos1Cam := aScan(aHeaderCam, {|x| AllTrim(Upper(x[2])) == "XX_CAMPO"}) Local nPos1Tit := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_TITUL"}) Local nPos1Pic := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_MASCA"}) Local nPos1Tam := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_TAMCP"}) Local nPos1Ali := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_ALINH"}) Local nPos1Que := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_QUEBR"}) Local nPos1Fun := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_FUNDO"}) Local nPos1Fon := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_FONTE"}) Local nPos1Neg := aScan(aHeaderCam, {|x| Alltrim(Upper(x[2])) == "XX_NEGRI"}) Local nPos2Cam := aScan(aHeaderTot, {|x| Alltrim(Upper(x[2])) == "XX_CAMPO"}) Local nPos2Pic := aScan(aHeaderTot, {|x| Alltrim(Upper(x[2])) == "XX_MASCA"}) Local nPos2Tot := aScan(aHeaderTot, {|x| Alltrim(Upper(x[2])) == "XX_TOTAL"}) Local lFirst := .T. Local aSQL := StrTokArr(cEditSQL, CRLF) //Pegando a estrutura da query TCQuery cEditSQL New Alias "QRY_AUX" aStrutAux := QRY_AUX->(DbStruct()) QRY_AUX->(DbCloseArea()) //Se o arquivo já existir If File(Alltrim(cGetDirec)+cArquivo) //Se deseja sobrepor, exclui o arquivo If MsgYesNo("Arquivo já existe, deseja sobrepor?", "Atenção") fErase(Alltrim(cGetDirec)+cArquivo) Else Return EndIf EndIf //Cria o arquivo nHdl := fCreate(Alltrim(cGetDirec)+cArquivo) //Se houve algum erro finaliza If nHdl < 0 MsgAlert("Erro ao criar o arquivo: " + cValToChar(fError())) //Senão gera o conteúdo do arquivo Else //Cabeçalho fWrite(nHdl, '//Bibliotecas' + STR_PULA) fWrite(nHdl, '#Include "Protheus.ch"' + STR_PULA) fWrite(nHdl, '#Include "TopConn.ch"' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, '//Constantes' + STR_PULA) fWrite(nHdl, '#Define STR_PULA Chr(13)+Chr(10)' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, '/*/{Protheus.doc} ' + Alltrim(cGetUserF) + STR_PULA) fWrite(nHdl, 'Relatório - ' + cGetTitul + STR_PULA) fWrite(nHdl, '@author ' + cAutor + STR_PULA) fWrite(nHdl, '@since ' + cData + STR_PULA) fWrite(nHdl, '@version 1.0' + STR_PULA) fWrite(nHdl, ' @example' + STR_PULA) fWrite(nHdl, ' u_'+Alltrim(cGetUserF)+'()' + STR_PULA) fWrite(nHdl, ' @obs Função gerada pelo zReport()' + STR_PULA) fWrite(nHdl, '/*/' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) //Função principal fWrite(nHdl, 'User Function '+Alltrim(cGetUserF)+'()' + STR_PULA) fWrite(nHdl, ' Local aArea := GetArea()' + STR_PULA) fWrite(nHdl, ' Local oReport' + STR_PULA) fWrite(nHdl, ' Local lEmail := .F.' + STR_PULA) fWrite(nHdl, ' Local cPara := "'+Alltrim(cGetEmail)+'"' + STR_PULA) fWrite(nHdl, ' Private cPerg := ""' + STR_PULA) //Se utilizar grupo de pergunta If cCmbUtili == 'S' fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Definições da pergunta' + STR_PULA) fWrite(nHdl, ' cPerg := "'+cGetPergu+'"' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Se a pergunta não existir, zera a variável' + STR_PULA) fWrite(nHdl, ' DbSelectArea("SX1")' + STR_PULA) fWrite(nHdl, ' SX1->(DbSetOrder(1)) //X1_GRUPO + X1_ORDEM' + STR_PULA) fWrite(nHdl, ' If ! SX1->(DbSeek(cPerg))' + STR_PULA) fWrite(nHdl, ' cPerg := Nil' + STR_PULA) fWrite(nHdl, ' EndIf' + STR_PULA) EndIf //Se utiliza disparo por e-Mail If cCmbEnvia == 'S' fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Será enviado por e-Mail' + STR_PULA) fWrite(nHdl, ' lEmail := .T.' + STR_PULA) EndIf fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Cria as definições do relatório' + STR_PULA) fWrite(nHdl, ' oReport := fReportDef()' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Será enviado por e-Mail?' + STR_PULA) fWrite(nHdl, ' If lEmail' + STR_PULA) fWrite(nHdl, ' oReport:nRemoteType := NO_REMOTE' + STR_PULA) fWrite(nHdl, ' oReport:cEmail := cPara' + STR_PULA) fWrite(nHdl, ' oReport:nDevice := 3 //1-Arquivo,2-Impressora,3-email,4-Planilha e 5-Html' + STR_PULA) fWrite(nHdl, ' oReport:SetPreview(.F.)' + STR_PULA) fWrite(nHdl, ' oReport:Print(.F., "", .T.)' + STR_PULA) fWrite(nHdl, ' //Senão, mostra a tela' + STR_PULA) fWrite(nHdl, ' Else' + STR_PULA) fWrite(nHdl, ' oReport:PrintDialog()' + STR_PULA) fWrite(nHdl, ' EndIf' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' RestArea(aArea)' + STR_PULA) fWrite(nHdl, 'Return' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) //Definições do relatório fWrite(nHdl, '/*-------------------------------------------------------------------------------*' + STR_PULA) fWrite(nHdl, ' | Func: fReportDef |' + STR_PULA) fWrite(nHdl, ' | Desc: Função que monta a definição do relatório |' + STR_PULA) fWrite(nHdl, ' *-------------------------------------------------------------------------------*/' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, 'Static Function fReportDef()' + STR_PULA) fWrite(nHdl, ' Local oReport' + STR_PULA) fWrite(nHdl, ' Local oSectDad := Nil' + STR_PULA) fWrite(nHdl, ' Local oBreak := Nil' + STR_PULA) //Se tiver totalizadores If lChkTot .And. Len(aDadTot) > 0 For nAtual := 1 To Len(aDadTot) //Se tiver campo válido If !Empty(aDadTot[nAtual][nPos2Cam]) fWrite(nHdl, ' Local oFunTot'+cValToChar(nAtual)+' := Nil' + STR_PULA) EndIf Next EndIf fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Criação do componente de impressão' + STR_PULA) fWrite(nHdl, ' oReport := TReport():New( "'+Alltrim(cGetUserF)+'",; //Nome do Relatório' + STR_PULA) fWrite(nHdl, ' "'+Alltrim(cGetTitul)+'",; //Título' + STR_PULA) fWrite(nHdl, ' cPerg,; //Pergunte ... Se eu defino a pergunta aqui, será impresso uma página com os parâmetros, conforme privilégio 101' + STR_PULA) fWrite(nHdl, ' {|oReport| fRepPrint(oReport)},; //Bloco de código que será executado na confirmação da impressão' + STR_PULA) fWrite(nHdl, ' ) //Descrição' + STR_PULA) fWrite(nHdl, ' oReport:SetTotalInLine(.F.)' + STR_PULA) fWrite(nHdl, ' oReport:lParamPage := .F.' + STR_PULA) fWrite(nHdl, ' oReport:oPage:SetPaperSize(9) //Folha A4' + STR_PULA) //Se for Retrato If cCmbOrien == 'R' fWrite(nHdl, ' oReport:SetPortrait()' + STR_PULA) //Se for Paisagem ElseIf cCmbOrien == 'P' fWrite(nHdl, ' oReport:SetLandscape()' + STR_PULA) EndIf //Se a fonte for tamanho 8 If cCmbFonte == '1' fWrite(nHdl, ' oReport:SetLineHeight(50)' + STR_PULA) fWrite(nHdl, ' oReport:nFontBody := 08' + STR_PULA) //Se a fonte for tamanho 12 ElseIf cCmbFonte == '2' fWrite(nHdl, ' oReport:SetLineHeight(60)' + STR_PULA) fWrite(nHdl, ' oReport:nFontBody := 12' + STR_PULA) EndIf fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Criando a seção de dados' + STR_PULA) fWrite(nHdl, ' oSectDad := TRSection():New( oReport,; //Objeto TReport que a seção pertence' + STR_PULA) fWrite(nHdl, ' "Dados",; //Descrição da seção' + STR_PULA) fWrite(nHdl, ' {"QRY_AUX"}) //Tabelas utilizadas, a primeira será considerada como principal da seção' + STR_PULA) fWrite(nHdl, ' oSectDad:SetTotalInLine(.F.) //Define se os totalizadores serão impressos em linha ou coluna. .F.=Coluna; .T.=Linha' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Colunas do relatório' + STR_PULA) //Se foi informado as colunas manualmente If lChkEdit .And. Len(aDadCel) > 0 //Percorre os dados informados pelo usuário For nAtual := 1 To Len(aDadCel) //Se a linha não estiver excluída If ! aDadCel[nAtual][Len(aHeaderCam) + 1] //Se tiver campo, adiciona um trcell If ! Empty(aDadCel[nAtual][nPos1Cam]) //Tratamento para o título If !Empty(aDadCel[nAtual][nPos1Tit]) cTitulo := Alltrim(aDadCel[nAtual][nPos1Tit]) Else cTitulo := Capital(Alltrim(aDadCel[nAtual][nPos1Cam])) EndIf //Tratamento para a máscara If !Empty(aDadCel[nAtual][nPos1Pic]) cPicture := '"'+Alltrim(aDadCel[nAtual][nPos1Pic])+'"' Else cPicture := "/*cPicture*/" EndIf //Tratamento para o tamanho cTamanho := cValToChar(aDadCel[nAtual][nPos1Tam]) //Tratamento para alinhamento If aDadCel[nAtual][nPos1Ali] != '0' If aDadCel[nAtual][nPos1Ali] == '1' cAlinham := '"LEFT"' ElseIf aDadCel[nAtual][nPos1Ali] == '2' cAlinham := '"RIGHT"' Else cAlinham := '"CENTER"' EndIf Else cAlinham := "/*cAlign*/" EndIf //Tratamento para quebra de linha If aDadCel[nAtual][nPos1Ali] == 'S' cQuebr := ".T." Else cQuebr := "/*lLineBreak*/" EndIf //Tratamento para cor de fundo If aDadCel[nAtual][nPos1Fun] != '0' If aDadCel[nAtual][nPos1Fun] == '1' cFundo := "RGB(000,000,000)" ElseIf aDadCel[nAtual][nPos1Fun] == '2' cFundo := "RGB(254,254,254)" ElseIf aDadCel[nAtual][nPos1Fun] == '3' cFundo := "RGB(255,000,000)" ElseIf aDadCel[nAtual][nPos1Fun] == '4' cFundo := "RGB(000,255,000)" Else cFundo := "RGB(000,000,255)" EndIf Else cFundo := "/*nClrBack*/" EndIf //Tratamento para cor da fonte If aDadCel[nAtual][nPos1Fon] != '0' If aDadCel[nAtual][nPos1Fon] == '1' cFonte := "RGB(000,000,000)" ElseIf aDadCel[nAtual][nPos1Fon] == '2' cFonte := "RGB(254,254,254)" ElseIf aDadCel[nAtual][nPos1Fon] == '3' cFonte := "RGB(255,000,000)" ElseIf aDadCel[nAtual][nPos1Fon] == '4' cFonte := "RGB(000,255,000)" Else cFonte := "RGB(000,000,255)" EndIf Else cFonte := "/*nClrFore*/" EndIf //Tratamento para negrito If aDadCel[nAtual][nPos1Neg] == 'S' cNegrito := ".T." Else cNegrito := "/*lBold*/" EndIf fWrite(nHdl, ' TRCell():New(oSectDad, '+; '"'+Alltrim(aDadCel[nAtual][nPos1Cam])+'", '+; '"QRY_AUX", '+; '"'+cTitulo+'", '+; cPicture+', '+; cTamanho+', '+; '/*lPixel*/,'+; '/*{|| code-block de impressao }*/,'+; cAlinham+','+; cQuebr+','+; '/*cHeaderAlign */,'+; '/*lCellBreak*/,'+; '/*nColSpace*/,'+; '/*lAutoSize*/,'+; cFundo+','+; cFonte+','+; cNegrito+')' + STR_PULA) EndIf EndIf Next //Senão, pega todas da estrutura da query Else DbSelectArea('SX3') SX3->(DbSetOrder(2)) //X3_CAMPO //Percorre a estrutura For nAtual := 1 To Len(aStrutAux) //Se conseguir posicionar no campo If SX3->(DbSeek(aStrutAux[nAtual][1])) cTitulo := Alltrim(SX3->X3_TITULO) Else cTitulo := Capital(Alltrim(aStrutAux[nAtual][1])) EndIf fWrite(nHdl, ' TRCell():New(oSectDad, '+; '"'+Alltrim(aStrutAux[nAtual][1])+'", '+; '"QRY_AUX", '+; '"'+cTitulo+'", '+; '/*Picture*/, '+; cValToChar(aStrutAux[nAtual][3])+', '+; '/*lPixel*/,'+; '/*{|| code-block de impressao }*/,'+; '/*cAlign*/,'+; '/*lLineBreak*/,'+; '/*cHeaderAlign */,'+; '/*lCellBreak*/,'+; '/*nColSpace*/,'+; '/*lAutoSize*/,'+; '/*nClrBack*/,'+; '/*nClrFore*/,'+; '/*lBold*/)' + STR_PULA) Next EndIf //Se tiver quebra If !Empty(cGetQuebr) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Definindo a quebra' + STR_PULA) fWrite(nHdl, ' oBreak := TRBreak():New(oSectDad,{|| QRY_AUX->('+Alltrim(cGetQuebr)+') },{|| "SEPARACAO DO RELATORIO" })' + STR_PULA) fWrite(nHdl, ' oSectDad:SetHeaderBreak(.T.)' + STR_PULA) cQuebra := "oBreak" Else cQuebra := "" EndIf //Se tiver totalizadores If lChkTot .And. Len(aDadTot) > 0 fWrite(nHdl, ' ' + STR_PULA) For nAtual := 1 To Len(aDadTot) //Se tiver campo válido If !Empty(aDadTot[nAtual][nPos2Cam]) If lFirst fWrite(nHdl, ' //Totalizadores' + STR_PULA) lFirst := .F. EndIf //Tratamento para a máscara If !Empty(aDadTot[nAtual][nPos2Pic]) cPicture := '"'+Alltrim(aDadTot[nAtual][nPos2Pic])+'"' Else cPicture := "/*cPicture*/" EndIf //Tratamento para o total If aDadTot[nAtual][nPos2Tot] == '0' cTotal := '"SUM"' ElseIf aDadTot[nAtual][nPos2Tot] == '1' cTotal := '"COUNT"' ElseIf aDadTot[nAtual][nPos2Tot] == '2' cTotal := '"MAX"' ElseIf aDadTot[nAtual][nPos2Tot] == '3' cTotal := '"MIN"' Else cTotal := '"AVERAGE"' EndIf //Adiciona a função fWrite(nHdl, ' oFunTot'+cValToChar(nAtual)+' := TRFunction():New(oSectDad:Cell("'+Alltrim(aDadTot[nAtual][nPos2Cam])+'"),,'+cTotal+','+cQuebra+',,'+cPicture+')' + STR_PULA) fWrite(nHdl, ' oFunTot'+cValToChar(nAtual)+':SetEndReport(.F.)' + STR_PULA) EndIf Next EndIf fWrite(nHdl, 'Return oReport' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) //Impressão do relatório fWrite(nHdl, '/*-------------------------------------------------------------------------------*' + STR_PULA) fWrite(nHdl, ' | Func: fRepPrint |' + STR_PULA) fWrite(nHdl, ' | Desc: Função que imprime o relatório |' + STR_PULA) fWrite(nHdl, ' *-------------------------------------------------------------------------------*/' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, 'Static Function fRepPrint(oReport)' + STR_PULA) fWrite(nHdl, ' Local aArea := GetArea()' + STR_PULA) fWrite(nHdl, ' Local cQryAux := ""' + STR_PULA) fWrite(nHdl, ' Local oSectDad := Nil' + STR_PULA) fWrite(nHdl, ' Local nAtual := 0' + STR_PULA) fWrite(nHdl, ' Local nTotal := 0' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Pegando as seções do relatório' + STR_PULA) fWrite(nHdl, ' oSectDad := oReport:Section(1)' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Montando consulta de dados' + STR_PULA) //Percorrendo a consulta sql fWrite(nHdl, ' cQryAux := ""' + STR_PULA) For nAtual := 1 To Len(aSQL) fWrite(nHdl, ' cQryAux += "'+(aSQL[nAtual])+'" + STR_PULA' + STR_PULA) Next fWrite(nHdl, ' cQryAux := ChangeQuery(cQryAux)' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Executando consulta e setando o total da régua' + STR_PULA) fWrite(nHdl, ' TCQuery cQryAux New Alias "QRY_AUX"' + STR_PULA) fWrite(nHdl, ' Count to nTotal' + STR_PULA) fWrite(nHdl, ' oReport:SetMeter(nTotal)' + STR_PULA) DbSelectArea('SX3') SX3->(DbSetOrder(2)) //X3_CAMPO SX3->(DbGoTop()) //Percorre a estrutura For nAtual := 1 To Len(aStrutAux) //Se conseguir posicionar no campo If SX3->(DbSeek(aStrutAux[nAtual][1])) //Se for campo do tipo data If SX3->X3_TIPO == 'D' fWrite(nHdl, ' TCSetField("QRY_AUX", "'+Alltrim(aStrutAux[nAtual][1])+'", "D")' + STR_PULA) EndIf EndIf Next fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Enquanto houver dados' + STR_PULA) fWrite(nHdl, ' oSectDad:Init()' + STR_PULA) fWrite(nHdl, ' QRY_AUX->(DbGoTop())' + STR_PULA) fWrite(nHdl, ' While ! QRY_AUX->(Eof())' + STR_PULA) fWrite(nHdl, ' //Incrementando a régua' + STR_PULA) fWrite(nHdl, ' nAtual++' + STR_PULA) fWrite(nHdl, ' oReport:SetMsgPrint("Imprimindo registro "+cValToChar(nAtual)+" de "+cValToChar(nTotal)+"...")' + STR_PULA) fWrite(nHdl, ' oReport:IncMeter()' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' //Imprimindo a linha atual' + STR_PULA) fWrite(nHdl, ' oSectDad:PrintLine()' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' QRY_AUX->(DbSkip())' + STR_PULA) fWrite(nHdl, ' EndDo' + STR_PULA) fWrite(nHdl, ' oSectDad:Finish()' + STR_PULA) fWrite(nHdl, ' QRY_AUX->(DbCloseArea())' + STR_PULA) fWrite(nHdl, ' ' + STR_PULA) fWrite(nHdl, ' RestArea(aArea)' + STR_PULA) fWrite(nHdl, 'Return' + STR_PULA) fClose(nHdl) //Se o arquivo foi criado If File(Alltrim(cGetDirec)+cArquivo) If MsgYesNo("Arquivo gerado, deseja visualizar?", "Atenção") ShellExecute("open", cArquivo, "", Alltrim(cGetDirec), 1) EndIf EndIf EndIf RestArea(aAreaX3) Return
Esses e outros códigos, estão disponíveis gratuitamente no nosso GitHub, acesse em github.com/dan-atilio/AdvPL.
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Parabéns show de bola. São coisas assim que a totvs deveria nos entregar por padrão.
Bom dia Luiz.
Muito obrigado, realmente com ferramentas assim seria bem mais fácil.
Abraços brother.
Boa Mestree !! Fera !
Grande Newtão.
Um abraço brow.
Parabéns Daniel por compartilhar este material!
Boa tarde Artur.
Obrigado.
Abraços.
Muito bom, você está de parabéns
Boa tarde Philippe, muito obrigado.
Um grande abraço.
Parabéns Grande Mestre Atílio! Ficou show de bola!
Ahoo grande Georgito, muito obrigado jovem.
Abraços.
Boa tarde Atílio, realmente seu fonte e muito bom, podemos acrescentar muitas coisas nele para ficar muito melhor.
Ex.: a opção do próprio usuário de criar as perguntas e o sistema as cria, eu já faço isso em relatórios que eu mesmo crio.
Boa noite Roberto.
Rapaz, muito obrigado.
Realmente, eu deixo esses fontes genéricos abertos, pois sempre podemos melhorá-los né.
Como diria Philippe Kahn:
“The power of Open Source is the power of the people. The people rule.”
Um grande abraço.
Boa noite Dan,
Show de bola.
Abs
Grande Vagner.
Valeu brow.
Abraços.
Excelente! Muchas gracias!
Eu que agradeço Dario.
Abraços.
Muito bom cara, genial.
Me ajudou muito.
Muito obrigado
Eu que agradeço Alexsandro.
Um grande abraço.
Obrigado, muito bom mesmo !
Boa Tarde,
Gostaria se possível de um exemplo de relatório tendo Multi Thread, estou com problemas em performance deles.
Boa noite Mauricio, tudo bem?
Se tiver o fonte, pode entrar em contato para eu dar uma olhada.
Depois irei preparar algum conteúdo sobre multi thread.
Um grande abraço.
Que isso hem !! TOPÍSSIMO !! PARABENS !
Valeu jovem.
Um grande abraço.
Como faço para adicionar no menu do usuário?
Boa noite Ariel.
Você quer adicionar o zReport no menu?
Abraços.
Há didática e pedagogia em suas aulas, classe, objetos, métodos e a propriedade é dele mesmo. Parabéns Daniel, construindo conhecimentos da melhor maneira, simples e eficiente.
Boa noite Tavares.
Muito obrigado pelo comentário.
Um grande abraço.
Fala Dan. Antes de tudo, agradeço por compartilhar todo esse conhecimento.
Gostaria de pedir uma ajuda:
_ Eu compilei o seu fonte (na integra) no meu ambiente de testes. No próprio TDS, chamei a rotina “U_ZREPORT” para testar, mas está dando um erro ao executa-la:
THREAD ERROR ([20910], maicon.macedo, IT-00061) 08/11/2018 14:32:58
Alias does not exist SX3 on MSNEWGETDADOS:NEW(APLIB170.PRW) 03/01/2018 17:40:20 line : 270
[TOTVS build: 7.00.131227A-20180425 NG]
Called from MSNEWGETDADOS:NEW(APLIB170.PRW) 03/01/2018 17:40:20 line : 270
Called from U_ZREPORT(ZREPORT.PRW) 08/11/2018 14:21:22 line : 168
Called from STATICCALL(ZREPORT.PRW) 08/11/2018 14:21:22 line : 168
[TOTVS Ambiente: ENV]
[TOTVS Environment RPODB: top]
[TOTVS Environment Trace: Nenhum]
[TOTVS Environment IBXLog: Nenhum]
[TOTVS Environment KillStack: Nenhum]
[TOTVS Environment TraceStack: Nenhum]
[TOTVS Environment SpecialKey: 9439]
[TOTVS Environment LocalFiles: ctree]
[TOTVS Environment LogProfiler: Nenhum]
[TOTVS Environment TopMemoMega: Nenhum]
[TOTVS Environment RPOLanguage: Portuguese]
[TOTVS Environment RegionalLanguage: BRA]
[TOTVS Environment LocalDBExtension: .dtc]
[TOTVS Environment ConnectionTimeOut: Nenhum]
[TOTVS Environment General CTreeMode: server]
[TOTVS Environment General ConsoleLog: 1]
[TOTVS Environment General ConsoleFile: /outsourcing/totvs/protheus_data/logs/console_app.log]
[TOTVS Environment General MaxQuerySize: Nenhum]
[TOTVS Environment General MaxStringSize: Nenhum]
[TOTVS Remote Lib: QT-4.5.2 WIN]
[TOTVS Tipo Remoto: Microsoft Windows]
[TOTVS Build Remota: 7.00.131227A-20180507]
[TOTVS Tipo de Servidor: Console]
[TOTVS Server Build: 7.00.131227A-20180425 NG]
[TOTVS Server Unix: Sim]
[TOTVS Database: mssql]
[TOTVS Framework Versão: 20180108]
[TOTVS Framework Data: 20180103-193932]
[TOTVS Framework Comita: 764df3ca6bf8bb29a74d895a81ad23cb4bc778cc]
[TOTVS RPO Release: 12.1.017]
Publicas
Public 1: CPAISLOC(C) :BRA
Public 2: ASX8(A) :
STACK STATICCALL(ZREPORT.PRW) 08/11/2018 14:21:22
STACK U_ZREPORT(ZREPORT.PRW) 08/11/2018 14:21:22
Private 1: CAUTOR(C) :zReport
Private 2: CDATA(C) :11/08/18
Private 3: NJANLARG(N) :800
Private 4: NJANALTU(N) :500
Private 5: ODLGPVT(O) :O
Private 6: OBTNFEC(U) :NIL
Private 7: OBTNGER(U) :NIL
Private 8: ATPPAD(A) :
Private 9: OSAYUSERF(O) :O
Private 10: OGETUSERF(O) :O
Private 11: CGETUSERF(C) :xRelat
Private 12: OSAYDIREC(O) :O
Private 13: OGETDIREC(O) :O
Private 14: CGETDIREC(C) :C:\Users\MAICON~1.MAC\AppData\Local\Temp\
Private 15: OSAYTITUL(O) :O
Private 16: OGETTITUL(O) :O
Private 17: CGETTITUL(C) :Relatorio
Private 18: NLENDIREC(N) :120
Private 19: ATPORI(A) :
Private 20: ATPFON(A) :
Private 21: OSAYORIEN(O) :O
Private 22: OCMBORIEN(O) :O
Private 23: CCMBORIEN(C) :R
Private 24: OSAYFONTE(O) :O
Private 25: OCMBFONTE(O) :O
Private 26: CCMBFONTE(C) 😛
Private 27: OSAYUTILI(O) :O
Private 28: OCMBUTILI(O) :O
Private 29: CCMBUTILI(C) :N
Private 30: OSAYPERGU(O) :O
Private 31: OGETPERGU(O) :O
Private 32: CGETPERGU(C) :
Private 33: OSAYMOSTR(O) :O
Private 34: OCMBMOSTR(O) :O
Private 35: CCMBMOSTR(C) :N
Private 36: OSAYENVIA(O) :O
Private 37: OCMBENVIA(O) :O
Private 38: CCMBENVIA(C) :N
Private 39: OSAYEMAIL(O) :O
Private 40: OGETEMAIL(O) :O
Private 41: CGETEMAIL(C) :
Private 42: OSAYSQL(O) :O
Private 43: OPANELSQL(O) :O
Private 44: OEDITSQL(O) :O
Private 45: CEDITSQL(C) :
Private 46: OSAYQUEBR(O) :O
Private 47: OGETQUEBR(O) :O
Private 48: CGETQUEBR(C) :
Private 49: OCHKEDIT(O) :O
Private 50: LCHKEDIT(L) :.F.
Private 51: OMSGETCAM(U) :NIL
Private 52: AHEADERCAM(A) :
Private 53: ACOLSCAM(A) :
Private 54: OCHKTOT(U) :NIL
Private 55: LCHKTOT(L) :.F.
Private 56: OMSGETTOT(U) :NIL
Private 57: AHEADERTOT(A) :
Private 58: ACOLSTOT(A) :
Private 59: OFOLDERPVT(O) :O
Private 60: OSCROLLREL(O) :O
Private 61: OSCROLLSQL(O) :O
Local 1: AAREA(A) :
Local 2: OGRPGER(O) :O
Local 3: OGRPDEF(O) :O
Local 4: OGRPPAR(O) :O
Local 5: OGRPEMA(O) :O
STACK MSNEWGETDADOS:NEW(APLIB170.PRW) 03/01/2018 17:40:20
Param 1: NTOP(N) : 85
Param 2: NLEFT(N) : 3
Param 3: NBOTTOM(N) : 145
Param 4: NRIGHT(N) : 373
Param 5: NSTYLE(N) : 7
Param 6: ULINHAOK(C) : AllwaysTrue()
Param 7: UTUDOOK(U) : NIL
Param 8: CINICPOS(C) :
Param 9: AALTER(U) : NIL
Param 10: NFREEZE(N) : 0
Param 11: NMAX(N) : 99
Param 12: CFIELDOK(C) : AllwaysTrue()
Param 13: USUPERDEL(U) : NIL
Param 14: UDELOK(U) : NIL
Param 15: OWND(O) : O
Param 16: @APARHEADER(A) :
Param 17: @APARCOLS(A) :
Param 18: UCHANGE(U) : NIL
Param 19: CTELA(U) : NIL
Local 1: SELF(O) :O
Local 2: NTOP(N) :85
Local 3: NLEFT(N) :3
Local 4: NBOTTOM(N) :145
Local 5: NRIGHT(N) :373
Local 6: NSTYLE(N) :7
Local 7: ULINHAOK(C) :AllwaysTrue()
Local 8: UTUDOOK(U) :NIL
Local 9: CINICPOS(C) :
Local 10: AALTER(U) :NIL
Local 11: NFREEZE(N) :0
Local 12: NMAX(N) :99
Local 13: CFIELDOK(C) :AllwaysTrue()
Local 14: USUPERDEL(U) :NIL
Local 15: UDELOK(U) :NIL
Local 16: OWND(O) :O
Local 17: APARHEADER(A) :
Local 18: APARCOLS(A) :
Local 19: UCHANGE(U) :NIL
Local 20: CTELA(U) :NIL
Local 21: NI(N) :1
Local 22: NX3ORD(U) :NIL
Local 23: CTIPO(U) :NIL
Local 24: CSVALIAS(C) :
Local 25: LADDLINE(L) :.T.
Local 26: NBYTE(N) :6
Local 27: NRESTO(N) :1
Local 28: NX(N) :1
Local 29: CBINARIO(C) :00000111
Local 30: ACOMBO(U) :NIL
Local 31: NSIZE(U) :NIL
Local 32: LSX3OPENNED(L) :.F.
Local 33: LINTELA(L) :.F.
Local 34: AINTELA(U) :NIL
Local 35: NJ(U) :NIL
Local 36: LSKIP(U) :NIL
Local 37: OFONT(U) :NIL
Local 38: CATEXPRESSION(C) :Iif( Len( Self:aCOLS ) >= Self:oBrowse:nAt, Self:oBrowse:nAt, Len( Self:aCOLS ) )
Local 39: LISP12(L) :.T.
STACK { | e | ErrorDialog( e ) }(APLIB240.PRW) 03/01/2018 17:40:20
Local CodeBlock 1: E(O) :O
STACK ERRORDIALOG(APLIB240.PRW) 03/01/2018 17:40:20
Local 1: E(O) :O
Local 2: LINSIGA(L) :.F.
Local 3: CMSG(U) :NIL
Local 4: NI(U) :NIL
Local 5: CX(U) :NIL
Local 6: URETURN(U) :NIL
Local 7: CERROR(U) :NIL
Local 8: LSKIPERROR(L) :.F.
Local 9: AOBJLOG(A) :
Local 10: NX(U) :NIL
STACK ERRORDLG(APLIB240.PRW) 03/01/2018 17:40:20
Local 1: OERR(O) :O
Local 2: CMSG(U) :NIL
Local 3: ODLG(U) :NIL
Local 4: OFONT(U) :NIL
Local 5: OBMP(U) :NIL
Local 6: OPANEL(U) :NIL
Local 7: OPANELBMP(U) :NIL
Local 8: ODETAIL(U) :NIL
Local 9: OSEND(U) :NIL
Local 10: OCLOSE(U) :NIL
Local 11: OSAVE(U) :NIL
Local 12: OERROR(U) :NIL
Local 13: CERROR(U) :NIL
STACK CLEARPASS(APLIB240.PRW) 03/01/2018 17:40:20
Local 1: CENV(U) :NIL
Files
Boa noite Maicon, tudo bem?
Opa, primeiramente muito obrigado pelo carinho.
Esse erro é por que o Protheus não foi “preparado” com o famoso RPCSetEnv ou Prepare Environment. Portanto, o ideal é executar a rotina, direto pelo Menu dentro do sistema, ou no Fórmulas.
Ou seja, executar o SIGAMDI / SIGAADV, e depois sim abrir o zReport.
Espero ter ajudado. Qualquer dúvida, fico à disposição.
Um grande abraço.
Dan, boa tarde.
Antes de tudo, obrigado por compartilhar todo esse conhecimento.
Eu compilei o seu fonte (na integra) no meu ambiente de teste (minha plataforma é cloud). Ao testa-lo, no próprio TDS, ocorre um erro:
THREAD ERROR ([20910], maicon.macedo, IT-00061) 08/11/2018 14:32:58
Alias does not exist SX3 on MSNEWGETDADOS:NEW(APLIB170.PRW) 03/01/2018 17:40:20 line : 270
Pode me dar uma ajuda?
Obrigado novamente.
Boa noite Maicon, tudo bem?
Opa, primeiramente muito obrigado pelo carinho.
Esse erro é por que o Protheus não foi “preparado” com o famoso RPCSetEnv ou Prepare Environment. Portanto, o ideal é executar a rotina, direto pelo Menu dentro do sistema, ou no Fórmulas.
Ou seja, executar o SIGAMDI / SIGAADV, e depois sim abrir o zReport.
Espero ter ajudado. Qualquer dúvida, fico à disposição.
Um grande abraço.