Nesse vídeo demonstraremos a utilização das classes TReport, TRFunction, TRSection e TRCell, que servem para criar um relatório com opções de imprimir, gerar PDF, gerar Excel, entre outras.
Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function zExe505
Classes para montagem de um relatório com listagem de informações
@type Function
@author Atilio
@since 04/04/2023
@see https://tdn.totvs.com/display/public/framework/TReport e https://tdn.totvs.com/display/public/framework/TRSection e https://tdn.totvs.com/display/public/framework/TRFunction e https://tdn.totvs.com/display/public/framework/TRCell
@obs
**** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/
User Function zExe505()
Local aArea := FWGetArea()
Local oReport
Local aPergs := {}
Local cProdDe := Space(TamSX3('B1_COD')[1])
Local cProdAte := StrTran(cProdDe, ' ', 'Z')
Local cTipoDe := Space(TamSX3('B1_TIPO')[1])
Local cTipoAte := StrTran(cTipoDe, ' ', 'Z')
Local nOrden := 1
//Adicionando os parametros do ParamBox
aAdd(aPergs, {1, "Produto De", cProdDe, "", ".T.", "SB1", ".T.", 80, .F.}) // MV_PAR01
aAdd(aPergs, {1, "Produto Até", cProdAte, "", ".T.", "SB1", ".T.", 80, .T.}) // MV_PAR02
aAdd(aPergs, {1, "Tipo De", cTipoDe, "", ".T.", "02", ".T.", 40, .F.}) // MV_PAR03
aAdd(aPergs, {1, "Tipo Até", cTipoAte, "", ".T.", "02", ".T.", 40, .T.}) // MV_PAR04
aAdd(aPergs, {2, "Ordenar por", nOrden, {"1=Código do Produto", "2=Descrição do Produto", "3=Unidade de Medida"}, 100, ".T.", .T.}) // MV_PAR05
//Se a pergunta for confirma, cria as definicoes do relatorio
If ParamBox(aPergs, "Informe os parâmetros", , , , , , , , , .F., .F.)
MV_PAR05 := Val(cValToChar(MV_PAR05))
oReport := fReportDef()
oReport:PrintDialog()
EndIf
FWRestArea(aArea)
Return
Static Function fReportDef()
Local oReport
Local oSection := Nil
//Criacao do componente de impressao
oReport := TReport():New( "zRel02",;
"Relatório de Produto",;
,;
{|oReport| fRepPrint(oReport),};
)
oReport:SetTotalInLine(.F.)
oReport:lParamPage := .F.
oReport:oPage:SetPaperSize(9)
//Orientacao do Relatorio
oReport:SetPortrait()
//Definicoes da fonte utilizada
oReport:SetLineHeight(50)
oReport:nFontBody := 12
//Criando a secao de dados
oSection := TRSection():New( oReport,;
"Dados",;
{"QRY_REP"})
oSection:SetTotalInLine(.F.)
//Colunas do relatorio
TRCell():New(oSection, "B1_COD", "QRY_REP", "Codigo", /*cPicture*/, 15, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .T.)
TRCell():New(oSection, "B1_DESC", "QRY_REP", "Descricao", /*cPicture*/, 30, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSection, "B1_TIPO", "QRY_REP", "Tipo", /*cPicture*/, 02, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSection, "TIPODESCR", "QRY_REP", "Tp. Descr.", /*cPicture*/, 55, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSection, "B1_UM", "QRY_REP", "Unid. Med.", /*cPicture*/, 02, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSection, "UMDESCR", "QRY_REP", "UM. Descr.", /*cPicture*/, 40, /*lPixel*/, /*{|| code-block de impressao }*/, "LEFT", /*lLineBreak*/, "LEFT", /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
//Quebras do relatorio
oBreak := TRBreak():New(oSection, oSection:Cell("B1_TIPO"), {||"Total da Quebra"}, .F.)
//Totalizadores
TRFunction():New(oSection:Cell("B1_COD"), , "COUNT", , , "@E 999,999,999", , .F.)
Return oReport
Static Function fRepPrint(oReport)
Local aArea := FWGetArea()
Local cQryReport := ""
Local oSectDad := Nil
Local nAtual := 0
Local nTotal := 0
//Pegando as secoes do relatorio
oSectDad := oReport:Section(1)
//Montando consulta de dados
cQryReport += "SELECT " + CRLF
cQryReport += " B1_COD, " + CRLF
cQryReport += " B1_DESC, " + CRLF
cQryReport += " B1_TIPO, " + CRLF
cQryReport += " ISNULL(X5_DESCRI, '') AS TIPODESCR, " + CRLF
cQryReport += " B1_UM, " + CRLF
cQryReport += " ISNULL(AH_DESCPO, '') AS UMDESCR " + CRLF
cQryReport += "FROM " + CRLF
cQryReport += " " + RetSQLName("SB1") + " SB1 " + CRLF
cQryReport += " LEFT JOIN " + RetSQLName("SX5") + " SX5 ON ( " + CRLF
cQryReport += " X5_FILIAL = '" + FWxFilial("SX5") + "' " + CRLF
cQryReport += " AND X5_TABELA = '02' " + CRLF
cQryReport += " AND X5_CHAVE = B1_TIPO " + CRLF
cQryReport += " AND SX5.D_E_L_E_T_ = ' ' " + CRLF
cQryReport += " ) " + CRLF
cQryReport += " LEFT JOIN " + RetSQLName("SAH") + " SAH ON ( " + CRLF
cQryReport += " AH_FILIAL = '" + FWxFilial("SAH") + "' " + CRLF
cQryReport += " AND AH_UNIMED = B1_UM " + CRLF
cQryReport += " AND SAH.D_E_L_E_T_ = ' ' " + CRLF
cQryReport += " ) " + CRLF
cQryReport += "WHERE " + CRLF
cQryReport += " B1_FILIAL = '" + FWxFilial("SB1") + "' " + CRLF
cQryReport += " AND B1_COD >= '" + MV_PAR01 + "' " + CRLF
cQryReport += " AND B1_COD <= '" + MV_PAR02 + "' " + CRLF
cQryReport += " AND B1_TIPO >= '" + MV_PAR03 + "' " + CRLF
cQryReport += " AND B1_TIPO <= '" + MV_PAR04 + "' " + CRLF
cQryReport += " AND B1_MSBLQL != '1' " + CRLF
cQryReport += " AND SB1.D_E_L_E_T_ = ' ' " + CRLF
cQryReport += "ORDER BY " + CRLF
cQryReport += " B1_TIPO, " + CRLF
If MV_PAR05 == 1
cQryReport += " B1_COD " + CRLF
ElseIf MV_PAR05 == 2
cQryReport += " B1_DESC " + CRLF
ElseIf MV_PAR05 == 3
cQryReport += " B1_UM " + CRLF
EndIf
//Executando consulta e setando o total da regua
PlsQuery(cQryReport, "QRY_REP")
DbSelectArea("QRY_REP")
Count to nTotal
oReport:SetMeter(nTotal)
//Enquanto houver dados
oSectDad:Init()
QRY_REP->(DbGoTop())
While ! QRY_REP->(Eof())
//Incrementando a regua
nAtual++
oReport:SetMsgPrint("Imprimindo registro " + cValToChar(nAtual) + " de " + cValToChar(nTotal) + "...")
oReport:IncMeter()
//Imprimindo a linha atual
oSectDad:PrintLine()
QRY_REP->(DbSkip())
EndDo
oSectDad:Finish()
QRY_REP->(DbCloseArea())
FWRestArea(aArea)
Return
Bom pessoal, por hoje é só.
Abraços e até próxima.
eu to duvida no relatório treport e na secao2 eu coloco a mesma coisa que na seção5 mas só a 5 sai do jeito que eu quero
Tipo aqui
TRCell():New(oSection2, “C9_Pedido+C9_SEQUEN” ,””/Onde é buscado o campo */,”Numero O.F” /*Titulo/,/Picture/,20 /Tamanho/,/lPixel/,/{|| bloco-de-impressao }/, “LEFT” /Alinhamento/, .T./lLineBreak ou SetBlock/, “LEFT”, /lCellBreak/, /nColSpace/, /lAutoSize/, /nClrBack/, /nClrForce/, .T./*Negrito = T sem negrito = F */)
TRCell():New(oSection5, “C9_XENTREG” ,””/Onde é buscado o campo */,”** Data Entrega” /Titulo/,/Picture/,20 /Tamanho/,/lPixel/,/{|| bloco-de-impressao }/, “LEFT” /Alinhamento/, .T./lLineBreak ou SetBlock/, “LEFT”, /lCellBreak/, /nColSpace/, /lAutoSize/, /nClrBack/, /nClrForce/, .T./*Negrito = T sem negrito = F */)
Bom dia Matheus, tudo joia?
Eu não me lembro de ter visto nome composto em célula, por exemplo, isso aqui:
Ao invés disso, um teste que eu faria seria, colocar um nome:
E depois dentro do laço de repetição de impressão, antes do PrintLine, exemplo:
oSuaSection:Cell("PEDSEQUEN"):SetValue(SC9->C9_Pedido + SC9->C9_SEQUEN) oSuaSection:PrintLine()Tenha um ótimo e abençoado fim de semana.
Um forte abraço.
A quebra do oBreak não funciona em Excel? Aparentemente em modo Arquivo as quebras funcionam corretamente, mas em Formato de tabela, não funcionam nem as quebras nem os os dois TRFunctions
Ou estou errando em algum momento?
oSectionTotalizers := TRSection():New( oReport,;
“Totalizadores”,;
{“QRY_REP1”})
oSectionTotalizers:SetTotalInLine(.F.)
//Colunas de totalizadores
TRCell():New(oSectionTotalizers, “D3_COD”, “QRY_REP1”, “Produto”, /*cPicture*/, 15, /*lPixel*/, /*{|| code-block de impressao }*/, “LEFT”, /*lLineBreak*/, “LEFT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .T.)
TRCell():New(oSectionTotalizers, “B1_DESC”, “QRY_REP1”, “Descrição”, /*cPicture*/, 40, /*lPixel*/, /*{|| code-block de impressao }*/, “LEFT”, /*lLineBreak*/, “LEFT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSectionTotalizers, “D3_UM”, “QRY_REP1”, “Unid.”, /*cPicture*/, 05, /*lPixel*/, /*{|| code-block de impressao }*/, “LEFT”, /*lLineBreak*/, “LEFT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .F.)
TRCell():New(oSectionTotalizers, “AH_DESCPO”, “QRY_REP1”, “Descrição Unid.”, /*cPicture*/, 15, /*lPixel*/, /*{|| code-block de impressao }*/, “LEFT”, /*lLineBreak*/, “LEFT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .T.)
TRCell():New(oSectionTotalizers, “D3_QUANT”, “QRY_REP1”, “Quantidade”, /*cPicture*/, 15, /*lPixel*/, /*{|| code-block de impressao }*/, “RIGHT”, /*lLineBreak*/, “RIGHT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .T.)
TRCell():New(oSectionTotalizers, “D3_CUSTO1”, “QRY_REP1”, “Custo”, /*cPicture*/, 15, /*lPixel*/, /*{|| code-block de impressao }*/, “RIGHT”, /*lLineBreak*/, “RIGHT”, /*lCellBreak*/, /*nColSpace*/, /*lAutoSize*/, /*nClrBack*/, /*nClrFore*/, .T.)
oBreak := TRBreak():New(oSectionTotalizers, oSectionTotalizers:Cell(“D3_COD”), {||”Total”}, .F. )
TRFunction():New(oSectionTotalizers:Cell(“D3_CUSTO1″),”D3_CUSTO1″ ,”SUM”,oBreak,,PesqPict(“SD3”, “D3_CUSTO1”),,.T.,.F.) //Função de totalizador dentro do oBreak
TRFunction():New(oSectionTotalizers:Cell(“D3_QUANT”),”D3_QUANT” ,”SUM”,oBreak,,PesqPict(“SD3”, “D3_QUANT”),,.T.,.F.)
Bom dia Gabriel, tudo joia?
Até onde me lembro, no formato “Tabela” ele não funciona, pois o comportamento fica como se tivesse criando um relatório com FWMSExcel (que simplesmente exporta os dados uma linha abaixo da outra).
Não sei dizer se tem alguma parametrização, ou se você precisaria customizar algo manualmente.
Por exemplo, criar um FWPrinterXLSX e nele tratar as quebras e totalizadores.
Tenha uma ótima e abençoada sexta feira.
Um forte abraço.