Gera relatório de forma gráfica em AdvPL

Exemplo da Rotina:
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., "", .T., , @oPrintPvt, "", , , , .T.)
Exemplo 1- Gerando relatório de forma manual:
//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"
#Include "RPTDef.ch"
#Include "FWPrintSetup.ch"
//Alinhamentos
#Define PAD_LEFT 0
#Define PAD_RIGHT 1
#Define PAD_CENTER 2
//Cores
#Define COR_CINZA RGB(180, 180, 180)
#Define COR_PRETO RGB(000, 000, 000)
//Colunas
#Define COL_GRUPO 0015
#Define COL_DESCR 0095
/*/{Protheus.doc} zTstRel
Exemplos de FWMSPrinter
@author Atilio
@since 27/01/2019
@version 1.0
@type function
/*/
User Function zTstRel()
Local aArea := GetArea()
//Se a pergunta for confirmada
If MsgYesNo("Deseja gerar o relatório de grupos de produtos?", "Atenção")
Processa({|| fMontaRel()}, "Processando...")
EndIf
RestArea(aArea)
Return
/*---------------------------------------------------------------------*
| Func: fMontaRel |
| Desc: Função que monta o relatório |
*---------------------------------------------------------------------*/
Static Function fMontaRel()
Local cCaminho := ""
Local cArquivo := ""
Local cQryAux := ""
Local nAtual := 0
Local nTotal := 0
//Linhas e colunas
Private nLinAtu := 000
Private nTamLin := 010
Private nLinFin := 820
Private nColIni := 010
Private nColFin := 550
Private nColMeio := (nColFin-nColIni)/2
//Objeto de Impressão
Private oPrintPvt
//Variáveis auxiliares
Private dDataGer := Date()
Private cHoraGer := Time()
Private nPagAtu := 1
Private cNomeUsr := UsrRetName(RetCodUsr())
//Fontes
Private cNomeFont := "Arial"
Private oFontDet := TFont():New(cNomeFont, 9, -10, .T., .F., 5, .T., 5, .T., .F.)
Private oFontDetN := TFont():New(cNomeFont, 9, -10, .T., .T., 5, .T., 5, .T., .F.)
Private oFontRod := TFont():New(cNomeFont, 9, -08, .T., .F., 5, .T., 5, .T., .F.)
Private oFontTit := TFont():New(cNomeFont, 9, -13, .T., .T., 5, .T., 5, .T., .F.)
//Definindo o diretório como a temporária do S.O. e o nome do arquivo com a data e hora (sem dois pontos)
cCaminho := GetTempPath()
cArquivo := "zTstRel_" + dToS(dDataGer) + "_" + StrTran(cHoraGer, ':', '-')
//Criando o objeto do FMSPrinter
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., "", .T., , @oPrintPvt, "", , , , .T.)
//Setando os atributos necessários do relatório
oPrintPvt:SetResolution(72)
oPrintPvt:SetPortrait()
oPrintPvt:SetPaperSize(DMPAPER_A4)
oPrintPvt:SetMargin(60, 60, 60, 60)
//Imprime o cabeçalho
fImpCab()
//Montando a consulta
cQryAux := " SELECT " + CRLF
cQryAux += " BM_GRUPO, " + CRLF
cQryAux += " BM_DESC " + CRLF
cQryAux += " FROM " + CRLF
cQryAux += " " + RetSQLName('SBM') + " SBM " + CRLF
cQryAux += " WHERE " + CRLF
cQryAux += " BM_FILIAL = '" + FWxFilial('SBM') + "' " + CRLF
cQryAux += " AND SBM.D_E_L_E_T_ = ' ' " + CRLF
cQryAux += " ORDER BY " + CRLF
cQryAux += " BM_GRUPO " + CRLF
TCQuery cQryAux New Alias "QRY_SBM"
//Conta o total de registros, seta o tamanho da régua, e volta pro topo
Count To nTotal
ProcRegua(nTotal)
QRY_SBM->(DbGoTop())
nAtual := 0
//Enquanto houver registros
While ! QRY_SBM->(EoF())
nAtual++
IncProc("Imprimindo grupo " + QRY_SBM->BM_GRUPO + " (" + cValToChar(nAtual) + " de " + cValToChar(nTotal) + ")...")
//Se a linha atual mais o espaço que será utilizado forem maior que a linha final, imprime rodapé e cabeçalho
If nLinAtu + nTamLin > nLinFin
fImpRod()
fImpCab()
EndIf
//Imprimindo a linha atual
oPrintPvt:SayAlign(nLinAtu, COL_GRUPO, QRY_SBM->BM_GRUPO, oFontDet, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinAtu, COL_DESCR, QRY_SBM->BM_DESC, oFontDet, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinAtu += nTamLin
QRY_SBM->(DbSkip())
EndDo
QRY_SBM->(DbCloseArea())
//Se ainda tiver linhas sobrando na página, imprime o rodapé final
If nLinAtu <= nLinFin
fImpRod()
EndIf
//Mostrando o relatório
oPrintPvt:Preview()
Return
/*---------------------------------------------------------------------*
| Func: fImpCab |
| Desc: Função que imprime o cabeçalho |
*---------------------------------------------------------------------*/
Static Function fImpCab()
Local cTexto := ""
Local nLinCab := 030
//Iniciando Página
oPrintPvt:StartPage()
//Cabeçalho
cTexto := "Relação de Grupos de Produtos"
oPrintPvt:SayAlign(nLinCab, nColMeio - 120, cTexto, oFontTit, 240, 20, COR_CINZA, PAD_CENTER, 0)
//Linha Separatória
nLinCab += (nTamLin * 2)
oPrintPvt:Line(nLinCab, nColIni, nLinCab, nColFin, COR_CINZA)
//Cabeçalho das colunas
nLinCab += nTamLin
oPrintPvt:SayAlign(nLinCab, COL_GRUPO, "Grupo", oFontDetN, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinCab, COL_DESCR, "Descrição", oFontDetN, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinCab += nTamLin
//Atualizando a linha inicial do relatório
nLinAtu := nLinCab + 3
Return
/*---------------------------------------------------------------------*
| Func: fImpRod |
| Desc: Função que imprime o rodapé |
*---------------------------------------------------------------------*/
Static Function fImpRod()
Local nLinRod := nLinFin + nTamLin
Local cTextoEsq := ''
Local cTextoDir := ''
//Linha Separatória
oPrintPvt:Line(nLinRod, nColIni, nLinRod, nColFin, COR_CINZA)
nLinRod += 3
//Dados da Esquerda e Direita
cTextoEsq := dToC(dDataGer) + " " + cHoraGer + " " + FunName() + " " + cNomeUsr
cTextoDir := "Página " + cValToChar(nPagAtu)
//Imprimindo os textos
oPrintPvt:SayAlign(nLinRod, nColIni, cTextoEsq, oFontRod, 200, 05, COR_CINZA, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinRod, nColFin-40, cTextoDir, oFontRod, 040, 05, COR_CINZA, PAD_RIGHT, 0)
//Finalizando a página e somando mais um
oPrintPvt:EndPage()
nPagAtu++
Return
Exemplo 2- Relatório com opção de forma manual e via job:
//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"
#Include "RPTDef.ch"
#Include "FWPrintSetup.ch"
//Alinhamentos
#Define PAD_LEFT 0
#Define PAD_RIGHT 1
#Define PAD_CENTER 2
//Cores
#Define COR_CINZA RGB(180, 180, 180)
#Define COR_PRETO RGB(000, 000, 000)
//Colunas
#Define COL_GRUPO 0015
#Define COL_DESCR 0095
/*/{Protheus.doc} zTstRel
Exemplos de FWMSPrinter
@author Atilio
@since 27/01/2019
@version 1.0
@type function
/*/
User Function zTstRel()
Local aArea := GetArea()
Private lJob := .F.
//Chamado pelo Schedule
If Select("SX2") == 0
//Preparando o ambiente
lJob := .T.
RPCSetType(3)
RPCSetEnv("01", "01", "", "", "")
EndIf
//Se for execução automática, não mostra pergunta, executa direto
If lJob
Processa({|| fMontaRel()}, "Processando...")
//Senão, se a pergunta for confirmada, executa o relatório
Else
If MsgYesNo("Deseja gerar o relatório de grupos de produtos?", "Atenção")
Processa({|| fMontaRel()}, "Processando...")
EndIf
EndIf
RestArea(aArea)
Return
/*---------------------------------------------------------------------*
| Func: fMontaRel |
| Desc: Função que monta o relatório |
*---------------------------------------------------------------------*/
Static Function fMontaRel()
Local cCaminho := ""
Local cArquivo := ""
Local cQryAux := ""
Local nAtual := 0
Local nTotal := 0
//Linhas e colunas
Private nLinAtu := 000
Private nTamLin := 010
Private nLinFin := 820
Private nColIni := 010
Private nColFin := 550
Private nColMeio := (nColFin-nColIni)/2
//Objeto de Impressão
Private oPrintPvt
//Variáveis auxiliares
Private dDataGer := Date()
Private cHoraGer := Time()
Private nPagAtu := 1
Private cNomeUsr := UsrRetName(RetCodUsr())
//Fontes
Private cNomeFont := "Arial"
Private oFontDet := TFont():New(cNomeFont, 9, -10, .T., .F., 5, .T., 5, .T., .F.)
Private oFontDetN := TFont():New(cNomeFont, 9, -10, .T., .T., 5, .T., 5, .T., .F.)
Private oFontRod := TFont():New(cNomeFont, 9, -08, .T., .F., 5, .T., 5, .T., .F.)
Private oFontTit := TFont():New(cNomeFont, 9, -13, .T., .T., 5, .T., 5, .T., .F.)
//Se for via JOB, muda as parametrizações
If lJob
//Define o caminho dentro da protheus data e o nome do arquivo
cCaminho := "\x_relatorios\"
cArquivo := "zTstRel_job_" + dToS(dDataGer) + "_" + StrTran(cHoraGer, ':', '-') + ".pdf"
//Se não existir a pasta na Protheus Data, cria ela
If ! ExistDir(cCaminho)
MakeDir(cCaminho)
EndIf
//Cria o objeto FWMSPrinter
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., '', .T., .F., , , .T., .T., , .F.)
oPrintPvt:cPathPDF := cCaminho
Else
//Definindo o diretório como a temporária do S.O. e o nome do arquivo com a data e hora (sem dois pontos)
cCaminho := GetTempPath()
cArquivo := "zTstRel_" + dToS(dDataGer) + "_" + StrTran(cHoraGer, ':', '-')
//Criando o objeto do FMSPrinter
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., "", .T., , @oPrintPvt, "", , , , .T.)
EndIf
//Setando os atributos necessários do relatório
oPrintPvt:SetResolution(72)
oPrintPvt:SetPortrait()
oPrintPvt:SetPaperSize(DMPAPER_A4)
oPrintPvt:SetMargin(60, 60, 60, 60)
//Imprime o cabeçalho
fImpCab()
//Montando a consulta
cQryAux := " SELECT " + CRLF
cQryAux += " BM_GRUPO, " + CRLF
cQryAux += " BM_DESC " + CRLF
cQryAux += " FROM " + CRLF
cQryAux += " " + RetSQLName('SBM') + " SBM " + CRLF
cQryAux += " WHERE " + CRLF
cQryAux += " BM_FILIAL = '" + FWxFilial('SBM') + "' " + CRLF
cQryAux += " AND SBM.D_E_L_E_T_ = ' ' " + CRLF
cQryAux += " ORDER BY " + CRLF
cQryAux += " BM_GRUPO " + CRLF
TCQuery cQryAux New Alias "QRY_SBM"
//Conta o total de registros, seta o tamanho da régua, e volta pro topo
Count To nTotal
ProcRegua(nTotal)
QRY_SBM->(DbGoTop())
nAtual := 0
//Enquanto houver registros
While ! QRY_SBM->(EoF())
nAtual++
IncProc("Imprimindo grupo " + QRY_SBM->BM_GRUPO + " (" + cValToChar(nAtual) + " de " + cValToChar(nTotal) + ")...")
//Se a linha atual mais o espaço que será utilizado forem maior que a linha final, imprime rodapé e cabeçalho
If nLinAtu + nTamLin > nLinFin
fImpRod()
fImpCab()
EndIf
//Imprimindo a linha atual
oPrintPvt:SayAlign(nLinAtu, COL_GRUPO, QRY_SBM->BM_GRUPO, oFontDet, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinAtu, COL_DESCR, QRY_SBM->BM_DESC, oFontDet, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinAtu += nTamLin
QRY_SBM->(DbSkip())
EndDo
QRY_SBM->(DbCloseArea())
//Se ainda tiver linhas sobrando na página, imprime o rodapé final
If nLinAtu <= nLinFin
fImpRod()
EndIf
//Se for via job, imprime o arquivo para gerar corretamente o pdf
If lJob
oPrintPvt:Print()
//Se for via manual, mostra o relatório
Else
oPrintPvt:Preview()
EndIf
Return
/*---------------------------------------------------------------------*
| Func: fImpCab |
| Desc: Função que imprime o cabeçalho |
*---------------------------------------------------------------------*/
Static Function fImpCab()
Local cTexto := ""
Local nLinCab := 030
//Iniciando Página
oPrintPvt:StartPage()
//Cabeçalho
cTexto := "Relação de Grupos de Produtos"
oPrintPvt:SayAlign(nLinCab, nColMeio - 120, cTexto, oFontTit, 240, 20, COR_CINZA, PAD_CENTER, 0)
//Linha Separatória
nLinCab += (nTamLin * 2)
oPrintPvt:Line(nLinCab, nColIni, nLinCab, nColFin, COR_CINZA)
//Cabeçalho das colunas
nLinCab += nTamLin
oPrintPvt:SayAlign(nLinCab, COL_GRUPO, "Grupo", oFontDetN, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinCab, COL_DESCR, "Descrição", oFontDetN, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinCab += nTamLin
//Atualizando a linha inicial do relatório
nLinAtu := nLinCab + 3
Return
/*---------------------------------------------------------------------*
| Func: fImpRod |
| Desc: Função que imprime o rodapé |
*---------------------------------------------------------------------*/
Static Function fImpRod()
Local nLinRod := nLinFin + nTamLin
Local cTextoEsq := ''
Local cTextoDir := ''
//Linha Separatória
oPrintPvt:Line(nLinRod, nColIni, nLinRod, nColFin, COR_CINZA)
nLinRod += 3
//Dados da Esquerda e Direita
cTextoEsq := dToC(dDataGer) + " " + cHoraGer + " " + FunName() + " " + cNomeUsr
cTextoDir := "Página " + cValToChar(nPagAtu)
//Imprimindo os textos
oPrintPvt:SayAlign(nLinRod, nColIni, cTextoEsq, oFontRod, 200, 05, COR_CINZA, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinRod, nColFin-40, cTextoDir, oFontRod, 040, 05, COR_CINZA, PAD_RIGHT, 0)
//Finalizando a página e somando mais um
oPrintPvt:EndPage()
nPagAtu++
Return
Exemplo 3- Relatório com opção de forma manual e via job com disparo de e-Mail:
//Bibliotecas
#Include "Protheus.ch"
#Include "TopConn.ch"
#Include "RPTDef.ch"
#Include "FWPrintSetup.ch"
//Alinhamentos
#Define PAD_LEFT 0
#Define PAD_RIGHT 1
#Define PAD_CENTER 2
//Cores
#Define COR_CINZA RGB(180, 180, 180)
#Define COR_PRETO RGB(000, 000, 000)
//Colunas
#Define COL_GRUPO 0015
#Define COL_DESCR 0095
/*/{Protheus.doc} zTstRel
Exemplos de FWMSPrinter
@author Atilio
@since 27/01/2019
@version 1.0
@type function
/*/
User Function zTstRel()
Local aArea := GetArea()
Private lJob := .F.
//Chamado pelo Schedule
If Select("SX2") == 0
//Preparando o ambiente
lJob := .T.
RPCSetType(3)
RPCSetEnv("01", "01", "", "", "")
EndIf
//Se for execução automática, não mostra pergunta, executa direto
If lJob
Processa({|| fMontaRel()}, "Processando...")
//Senão, se a pergunta for confirmada, executa o relatório
Else
If MsgYesNo("Deseja gerar o relatório de grupos de produtos?", "Atenção")
Processa({|| fMontaRel()}, "Processando...")
EndIf
EndIf
RestArea(aArea)
Return
/*---------------------------------------------------------------------*
| Func: fMontaRel |
| Desc: Função que monta o relatório |
*---------------------------------------------------------------------*/
Static Function fMontaRel()
Local cCaminho := ""
Local cArquivo := ""
Local cQryAux := ""
Local nAtual := 0
Local nTotal := 0
//Variáveis para disparo de e-Mail
Local cPara := ""
Local cAssunto := ""
Local cCorpo := ""
Local aAnexos := {}
//Linhas e colunas
Private nLinAtu := 000
Private nTamLin := 010
Private nLinFin := 820
Private nColIni := 010
Private nColFin := 550
Private nColMeio := (nColFin-nColIni)/2
//Objeto de Impressão
Private oPrintPvt
//Variáveis auxiliares
Private dDataGer := Date()
Private cHoraGer := Time()
Private nPagAtu := 1
Private cNomeUsr := UsrRetName(RetCodUsr())
//Fontes
Private cNomeFont := "Arial"
Private oFontDet := TFont():New(cNomeFont, 9, -10, .T., .F., 5, .T., 5, .T., .F.)
Private oFontDetN := TFont():New(cNomeFont, 9, -10, .T., .T., 5, .T., 5, .T., .F.)
Private oFontRod := TFont():New(cNomeFont, 9, -08, .T., .F., 5, .T., 5, .T., .F.)
Private oFontTit := TFont():New(cNomeFont, 9, -13, .T., .T., 5, .T., 5, .T., .F.)
//Se for via JOB, muda as parametrizações
If lJob
//Define o caminho dentro da protheus data e o nome do arquivo
cCaminho := "\x_relatorios\"
cArquivo := "zTstRel_job_" + dToS(dDataGer) + "_" + StrTran(cHoraGer, ':', '-') + ".pdf"
//Se não existir a pasta na Protheus Data, cria ela
If ! ExistDir(cCaminho)
MakeDir(cCaminho)
EndIf
//Cria o objeto FWMSPrinter
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., '', .T., .F., , , .T., .T., , .F.)
oPrintPvt:cPathPDF := cCaminho
Else
//Definindo o diretório como a temporária do S.O. e o nome do arquivo com a data e hora (sem dois pontos)
cCaminho := GetTempPath()
cArquivo := "zTstRel_" + dToS(dDataGer) + "_" + StrTran(cHoraGer, ':', '-')
//Criando o objeto do FMSPrinter
oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., "", .T., , @oPrintPvt, "", , , , .T.)
EndIf
//Setando os atributos necessários do relatório
oPrintPvt:SetResolution(72)
oPrintPvt:SetPortrait()
oPrintPvt:SetPaperSize(DMPAPER_A4)
oPrintPvt:SetMargin(60, 60, 60, 60)
//Imprime o cabeçalho
fImpCab()
//Montando a consulta
cQryAux := " SELECT " + CRLF
cQryAux += " BM_GRUPO, " + CRLF
cQryAux += " BM_DESC " + CRLF
cQryAux += " FROM " + CRLF
cQryAux += " " + RetSQLName('SBM') + " SBM " + CRLF
cQryAux += " WHERE " + CRLF
cQryAux += " BM_FILIAL = '" + FWxFilial('SBM') + "' " + CRLF
cQryAux += " AND SBM.D_E_L_E_T_ = ' ' " + CRLF
cQryAux += " ORDER BY " + CRLF
cQryAux += " BM_GRUPO " + CRLF
TCQuery cQryAux New Alias "QRY_SBM"
//Conta o total de registros, seta o tamanho da régua, e volta pro topo
Count To nTotal
ProcRegua(nTotal)
QRY_SBM->(DbGoTop())
nAtual := 0
//Enquanto houver registros
While ! QRY_SBM->(EoF())
nAtual++
IncProc("Imprimindo grupo " + QRY_SBM->BM_GRUPO + " (" + cValToChar(nAtual) + " de " + cValToChar(nTotal) + ")...")
//Se a linha atual mais o espaço que será utilizado forem maior que a linha final, imprime rodapé e cabeçalho
If nLinAtu + nTamLin > nLinFin
fImpRod()
fImpCab()
EndIf
//Imprimindo a linha atual
oPrintPvt:SayAlign(nLinAtu, COL_GRUPO, QRY_SBM->BM_GRUPO, oFontDet, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinAtu, COL_DESCR, QRY_SBM->BM_DESC, oFontDet, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinAtu += nTamLin
QRY_SBM->(DbSkip())
EndDo
QRY_SBM->(DbCloseArea())
//Se ainda tiver linhas sobrando na página, imprime o rodapé final
If nLinAtu <= nLinFin
fImpRod()
EndIf
//Se for via job, imprime o arquivo para gerar corretamente o pdf
If lJob
oPrintPvt:Print()
//Atenção! - é necessário baixar a função zEnvMail() - disponível em https://terminaldeinformacao.com/2017/10/17/funcao-dispara-e-mail-varios-anexos-em-advpl/
cPara := "teste@teste.com"
cAssunto := "Assunto Teste"
cCorpo := "Corpo do e-Mail Teste"
aAdd(aAnexos, cCaminho + cArquivo)
u_zEnvMail(cPara, cAssunto, cCorpo, aAnexos)
//Se for via manual, mostra o relatório
Else
oPrintPvt:Preview()
EndIf
Return
/*---------------------------------------------------------------------*
| Func: fImpCab |
| Desc: Função que imprime o cabeçalho |
*---------------------------------------------------------------------*/
Static Function fImpCab()
Local cTexto := ""
Local nLinCab := 030
//Iniciando Página
oPrintPvt:StartPage()
//Cabeçalho
cTexto := "Relação de Grupos de Produtos"
oPrintPvt:SayAlign(nLinCab, nColMeio - 120, cTexto, oFontTit, 240, 20, COR_CINZA, PAD_CENTER, 0)
//Linha Separatória
nLinCab += (nTamLin * 2)
oPrintPvt:Line(nLinCab, nColIni, nLinCab, nColFin, COR_CINZA)
//Cabeçalho das colunas
nLinCab += nTamLin
oPrintPvt:SayAlign(nLinCab, COL_GRUPO, "Grupo", oFontDetN, 0080, nTamLin, COR_PRETO, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinCab, COL_DESCR, "Descrição", oFontDetN, 0200, nTamLin, COR_PRETO, PAD_LEFT, 0)
nLinCab += nTamLin
//Atualizando a linha inicial do relatório
nLinAtu := nLinCab + 3
Return
/*---------------------------------------------------------------------*
| Func: fImpRod |
| Desc: Função que imprime o rodapé |
*---------------------------------------------------------------------*/
Static Function fImpRod()
Local nLinRod := nLinFin + nTamLin
Local cTextoEsq := ''
Local cTextoDir := ''
//Linha Separatória
oPrintPvt:Line(nLinRod, nColIni, nLinRod, nColFin, COR_CINZA)
nLinRod += 3
//Dados da Esquerda e Direita
cTextoEsq := dToC(dDataGer) + " " + cHoraGer + " " + FunName() + " " + cNomeUsr
cTextoDir := "Página " + cValToChar(nPagAtu)
//Imprimindo os textos
oPrintPvt:SayAlign(nLinRod, nColIni, cTextoEsq, oFontRod, 200, 05, COR_CINZA, PAD_LEFT, 0)
oPrintPvt:SayAlign(nLinRod, nColFin-40, cTextoDir, oFontRod, 040, 05, COR_CINZA, PAD_RIGHT, 0)
//Finalizando a página e somando mais um
oPrintPvt:EndPage()
nPagAtu++
Return
Exemplo em Vídeo:
Clique nesse link para ver um exemplo em Vídeo da nossa Maratona de Exemplos.
Observações:
– Caso tenha dúvidas ou problemas com os exemplos, entre em contato;
– Se tiver sugestões de rotinas, pode entrar em contato;
Referências:
– TDN