No artigo de hoje, vou mostrar como fazer aquele efeito zebrado em relatórios que usam a classe FWMSPrinter.
Basicamente pessoal, a lógica do zebrado, seria pintar o fundo de uma linha de maneira alternada.
Para fazermos isso em AdvPL, a lógica seria basicamente assim:
- Primeiro, é necessário criar um pincel com alguma cor, nesse exemplo que iremos mostrar será na cor Azul, e nosso pincel iremos chamar de oBrushAzul
- Depois precisamos de uma massa de dados, no nosso caso, será uma query de produtos, com o nome de alias QRY_AUX
- Em seguida precisamos de uma variável numérica, que irá sempre ser incrementada a cada produto que irei imprimir, no nosso exemplo será nAtuAux
- Agora, antes de imprimir as informações, eu verifico se a nAtuAux é par ou ímpar (se o resto da divisão der zero, é par). Caso seja par, via AdvPL eu informo que é para pintar o fundo com o método FillRect
Após a explicação da lógica, abaixo um print do relatório gerado pelo Protheus:
E abaixo o código fonte usado para desenvolvimento do relatório:
//Bibliotecas #Include "TOTVS.ch" #Include "TopConn.ch" #Include "RPTDef.ch" #Include "FWPrintSetup.ch" //Alinhamentos #Define PAD_LEFT 0 #Define PAD_RIGHT 1 #Define PAD_CENTER 2 Static nCorCinza := RGB(110, 110, 110) Static nCorAzul := RGB(193, 231, 253) /*/{Protheus.doc} zZebra Listagem de produtos, com cor de fundo alterada (zebrada) @author Atilio @since 03/06/2021 @version 1.0 @type function /*/ User Function zZebra() Local aPergs := {} Private cProdDe := Space(TamSX3("B1_COD")[1]) Private cProdAt := StrTran(cProdDe, " ", "Z") //Monta os parâmetros da tela aAdd(aPergs, {1, "Produto De", cProdDe, "@!", ".T.", "SB1", ".T.", 90, .F.}) aAdd(aPergs, {1, "Produto Até", cProdAt, "@!", ".T.", "SB1", ".T.", 90, .T.}) //Se a pergunta for confirmada If ParamBox(aPergs, "Informe os parâmetros", , , , , , , , , .F., .F.) cProdDe := MV_PAR01 cProdAt := MV_PAR02 Processa({|| fImprime()}) EndIf Return /*/{Protheus.doc} fImprime Funcao que gera o PDF Automaticamente @author Atilio @since 03/06/2021 @version 1.0 /*/ Static Function fImprime() Local aArea := GetArea() Local nTotAux := 0 Local nAtuAux := 0 Local cQryAux Local cArquivo := "zZebra_"+RetCodUsr()+"_" + dToS(Date()) + "_" + StrTran(Time(), ':', '-') + ".pdf" Private oPrintPvt Private oBrushAzul := TBRUSH():New(,nCorAzul) Private cHoraEx := Time() Private nPagAtu := 1 //Linhas e colunas Private nLinAtu := 0 Private nLinFin := 580 Private nColIni := 010 Private nColFin := 815 Private nEspCol := (nColFin-(nColIni+150))/13 Private nColMeio := (nColFin-nColIni)/2 //Colunas dos relatorio Private nColProd := nColIni Private nColDesc := nColIni + 050 Private nColUnid := nColFin - 425 Private nColTipo := nColFin - 340 Private nColBarr := nColFin - 200 //Declarando as fontes Private cNomeFont := "Arial" Private oFontDet := TFont():New(cNomeFont, 9, -11, .T., .F., 5, .T., 5, .T., .F.) Private oFontDetN := TFont():New(cNomeFont, 9, -13, .T., .T., 5, .T., 5, .T., .F.) Private oFontRod := TFont():New(cNomeFont, 9, -8, .T., .F., 5, .T., 5, .T., .F.) Private oFontMin := TFont():New(cNomeFont, 9, -7, .T., .F., 5, .T., 5, .T., .F.) Private oFontMinN := TFont():New(cNomeFont, 9, -7, .T., .T., 5, .T., 5, .T., .F.) Private oFontTit := TFont():New(cNomeFont, 9, -15, .T., .T., 5, .T., 5, .T., .F.) //Monta a consulta de dados cQryAux := "" cQryAux += " SELECT " + CRLF cQryAux += " B1_COD, " + CRLF cQryAux += " B1_DESC, " + CRLF cQryAux += " B1_UM, " + CRLF cQryAux += " B1_TIPO, " + CRLF cQryAux += " B1_CODBAR " + CRLF cQryAux += " FROM " + CRLF cQryAux += " " + RetSQLName("SB1") + " SB1 " + CRLF cQryAux += " WHERE " + CRLF cQryAux += " B1_FILIAL = '" + FWxFilial("SB1") + "' " + CRLF cQryAux += " AND B1_MSBLQL != '1' " + CRLF cQryAux += " AND B1_COD >= '" + cProdDe + "' " + CRLF cQryAux += " AND B1_COD <= '" + cProdAt + "' " + CRLF cQryAux += " AND SB1.D_E_L_E_T_ = ' ' " + CRLF cQryAux += " ORDER BY " + CRLF cQryAux += " B1_COD " + CRLF TCQuery cQryAux New Alias "QRY_AUX" //Define o tamanho da régua Count to nTotAux ProcRegua(nTotAux) QRY_AUX->(DbGoTop()) //Somente se tiver dados If ! QRY_AUX->(EoF()) //Criando o objeto de impressao oPrintPvt := FWMSPrinter():New(cArquivo, IMP_PDF, .F., , .T., , @oPrintPvt, , , , ,.T.) oPrintPvt:cPathPDF := GetTempPath() oPrintPvt:SetResolution(72) oPrintPvt:SetLandscape() oPrintPvt:SetPaperSize(DMPAPER_A4) oPrintPvt:SetMargin(0, 0, 0, 0) //Imprime os dados fImpCab() While ! QRY_AUX->(EoF()) nAtuAux++ IncProc("Imprimindo produto " + cValToChar(nAtuAux) + " de " + cValToChar(nTotAux) + "...") //Se atingiu o limite, quebra de pagina fQuebra() //Faz o zebrado ao fundo If nAtuAux % 2 == 0 oPrintPvt:FillRect({nLinAtu - 2, nColIni, nLinAtu + 12, nColFin}, oBrushAzul) EndIf //Imprime a linha atual oPrintPvt:SayAlign(nLinAtu, nColProd, QRY_AUX->B1_COD, oFontDet, (nColDesc - nColProd), 10, , PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu, nColDesc, QRY_AUX->B1_DESC, oFontDet, (nColUnid - nColDesc), 10, , PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu, nColUnid, QRY_AUX->B1_UM, oFontDet, (nColTipo - nColUnid), 10, , PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu, nColTipo, QRY_AUX->B1_TIPO, oFontDet, (nColBarr - nColTipo), 10, , PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu, nColBarr, QRY_AUX->B1_CODBAR, oFontDet, (nColFin - nColBarr), 10, , PAD_LEFT, ) nLinAtu += 15 oPrintPvt:Line(nLinAtu-3, nColIni, nLinAtu-3, nColFin, nCorCinza) //Se atingiu o limite, quebra de pagina fQuebra() QRY_AUX->(DbSkip()) EndDo fImpRod() oPrintPvt:Preview() Else MsgStop("Não foi encontrado informações com os parâmetros informados!", "Atenção") EndIf QRY_AUX->(DbCloseArea()) RestArea(aArea) Return /*---------------------------------------------------------------------* | Func: fImpCab | | Desc: Funcao que imprime o cabecalho | *---------------------------------------------------------------------*/ Static Function fImpCab() Local cTexto := "" Local nLinCab := 015 //Iniciando Pagina oPrintPvt:StartPage() //Cabecalho cTexto := "Listagem de Produtos" oPrintPvt:SayAlign(nLinCab, nColMeio-200, cTexto, oFontTit, 400, 20, , PAD_CENTER, ) oPrintPvt:SayAlign(nLinCab - 03, nColFin-300, "De: " + cProdDe, oFontDetN, 300, 20, , PAD_RIGHT, ) oPrintPvt:SayAlign(nLinCab + 07, nColFin-300, "Até: " + cProdAt, oFontDetN, 300, 20, , PAD_RIGHT, ) //Linha Separatoria nLinCab += 020 oPrintPvt:Line(nLinCab, nColIni, nLinCab, nColFin) //Atualizando a linha inicial do relatorio nLinAtu := nLinCab + 5 oPrintPvt:SayAlign(nLinAtu+00, nColProd, "Código", oFontMin, (nColDesc - nColProd), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+10, nColProd, "Produto", oFontMin, (nColDesc - nColProd), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+05, nColDesc, "Descrição", oFontMin, (nColUnid - nColDesc), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+00, nColUnid, "Unidade de", oFontMin, (nColTipo - nColUnid), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+10, nColUnid, "Medida", oFontMin, (nColTipo - nColUnid), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+05, nColTipo, "Tipo", oFontMin, (nColBarr - nColTipo), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+00, nColBarr, "Código de", oFontMin, (nColFin - nColBarr), 10, nCorCinza, PAD_LEFT, ) oPrintPvt:SayAlign(nLinAtu+10, nColBarr, "Barras", oFontMin, (nColFin - nColBarr), 10, nCorCinza, PAD_LEFT, ) nLinAtu += 25 Return /*---------------------------------------------------------------------* | Func: fImpRod | | Desc: Funcao que imprime o rodape | *---------------------------------------------------------------------*/ Static Function fImpRod() Local nLinRod:= nLinFin Local cTexto := '' //Linha Separatoria oPrintPvt:Line(nLinRod, nColIni, nLinRod, nColFin) nLinRod += 3 //Dados da Esquerda cTexto := dToC(dDataBase) + " " + cHoraEx + " " + FunName() + " (zZebra) " + UsrRetName(RetCodUsr()) oPrintPvt:SayAlign(nLinRod, nColIni, cTexto, oFontRod, 500, 10, , PAD_LEFT, ) //Direita cTexto := "Pagina "+cValToChar(nPagAtu) oPrintPvt:SayAlign(nLinRod, nColFin-40, cTexto, oFontRod, 040, 10, , PAD_RIGHT, ) //Finalizando a pagina e somando mais um oPrintPvt:EndPage() nPagAtu++ Return Static Function fQuebra() If nLinAtu >= nLinFin-10 fImpRod() fImpCab() EndIf Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.