E ae pessoal, tudo bom? Antes de mais nada gostaria de agradecer pois tenho aprendido bastante aqui no fórum. Tenho encontrado dificuldade para resolver uma questão de lógica em um programa que estou criando e gera relatório de Notas Fiscais. De forma resumida o programa recebe as entradas do usuário tais como data, numero da nota, ou então local que emitiu, e com esses dados ele efetua a busca e retorna os dados da(s) nota(s) fiscal(is) em questão. Foi-me pedido para acrescentar a este relatório o sub-total de peças por NOTA, o sub-total de valor por NOTA, o total de peças no RELATÓRIO e o total de volar no RELATÓRIO. A parte do total ficou fácil, foi só dar o display fora do FOR EACH. A questão que está travando pra mim, seriam os sub-totais, tanto de valor quanto de peças por NOTA. A pessoa que me passou está tarefa quer que eu de o display não linha a linha da nota, mas por nota, então o programa me traz algo mais ou menos assim: 0000017196 1 Catalisador x 200 RS1.000,00 0000017196 2 Catalisador y 100 R$1.000,00 0000017196 3 Catalisador z 100 R$500,00 Na lógica que eu havia criado o display vinha assim: sub-qtdade sub-valor 0000017196 1 Catalisador x 200 RS1.000,00 200 R$1.000,00 0000017196 2 Catalisador y 100 R$1.000,00 300 R$2.000,00 0000017196 3 Catalisador z 100 R$500,00 400 R$2.500,00 Mas a idéia de display precisa ser assim: 0000017196 1 Catalisador x 200 RS1.000,00 0000017196 2 Catalisador y 100 R$1.000,00 0000017196 3 Catalisador z 100 R$500,00 sub-qtdade: 400 sub-valor:R$2.500,00 Eu pensei que se eu tivesse uma função next dentro do progress eu conseguiria resolver isso de maneira fácil, pois eu compararia a nota atual do for each com a próxima nota e caso fossem diferentes eu daria o display dessa nf atual já com os sub totais, e caso contrario daria o display sem os sub-totais. Segue o código já criado, se tiverem alguma idéia de como em ajudar, pois como não conheço todas as funções e suas utilidades, acabo ficando limitado. Código: /* Sistema..: Teste Programa.: relatorionf.p Autor....: Rodrigo Araujo Data.....: xx/xx/xxxx Descricao: Relatório de NF´s */ {mfdtitle.i 2.0} DEF VAR v-typ-doc AS CHAR FORMAT "X(2)" LABEL "Tipo Doc" no-undo. DEF VAR site like si_site no-undo. DEF VAR site1 like si_site no-undo. DEF VAR nf AS CHAR FORMAT "X(15)" LABEL "NF" no-undo. DEF VAR nf1 AS CHAR FORMAT "X(15)" LABEL "->" no-undo. DEF VAR date-em AS DATE FORMAT "99/99/9999" LABEL "Data inicial" no-undo. DEF VAR date-em1 AS DATE FORMAT "99/99/9999" LABEL "->" no-undo. DEF VAR total_qty like znd_qty_item no-undo. DEF VAR total_pri like znd_ext_price no-undo. DEF VAR sub_qty like znd_qty_item no-undo. DEF VAR sub_pri like znd_ext_price no-undo. DEF VAR teste like zn_nbr no-undo. ASSIGN v-typ-doc = "NF". form v-typ-doc colon 13 site colon 13 site1 colon 40 nf colon 13 nf1 colon 40 date-em colon 13 date-em1 colon 40 with width 80 side-labels frame a. setFrameLabels(frame a:handle). form zn_addr colon 1 zn_inv_date colon 13 znd_part colon 23 zn_nbr colon 43 znd_line colon 57 znd_desc colon 62 znd_um colon 112 znd_qty_item colon 116 znd_ext_price colon 133 skip sub_qty colon 1 label "Itens por nota" sub_pri colon 17 label "Valor nota" total_qty colon 35 label "Qtdade total" total_pri colon 52 label "Valor total" with width 250 frame b. setFrameLabels(frame b:handle). REPEAT: assign teste = "". assign sub_qty = 0. assign sub_pri = 0. assign total_qty = 0. assign total_pri = 0. display v-typ-doc site site1 nf nf1 date-em date-em1 with frame a. if site1 = hi_char then assign site1 = "". if nf1 = hi_char then assign nf1 = "". if date-em = low_date then assign date-em = ?. if date-em1 = today then assign date-em1 = ?. update site help "Entre com o local emitente." validate ( can-find( first si_mstr where si_domain = global_domain and si_site = input site ), "ERRO: Entre com um local válido para a busca. Com dois digitos.") site1 help "Entre com o local emitente." validate ( can-find( first si_mstr where si_domain = global_domain and si_site = input site1 ), "ERRO: Entre com um local válido para a busca. Com dois digitos.") nf help "Entre com a nota fiscal." validate ( can-find( first zn_mstr where zn_domain = global_domain and zn_nbr = input nf ), "ERRO: Entre com uma nf válida para a busca.") nf1 help "Entre com a nota fiscal." validate ( can-find( first zn_mstr where zn_domain = global_domain and zn_nbr = input nf1 ), "ERRO: Entre com uma nf válida para a busca.") date-em help "Entre com a data para busca." date-em1 help "Entre com a data para busca." validate ( input date-em1 >= input date-em , "ERRO: Entra com uma hora válida.") with frame a. {gpselout.i &printType = "printer" &printWidth = 80 &pagedFlag = " " &stream = " " &appendToFile = " " &streamedOutputToTerminal = " " &withBatchOption = "yes" &displayStatementType = 1 &withCancelMessage = "yes" &pageBottomMargin = 6 &withEmail = "yes" &withWinprint = "yes" &defineVariables = "yes"} {mfphead.i} if site1 = "" then assign site1 = hi_char. if nf1 = "" then assign nf1 = hi_char. if date-em = ? then assign date-em = low_date. if date-em1 = ? then assign date-em1 = today. for each zn_mstr no-lock where zn_domain = global_domain and (zn_addr >= site and zn_addr <= site1) and zn_doc_type = v-typ-doc and (zn_nbr >= nf and zn_nbr <= nf1) and (zn_inv_date >= date-em and zn_inv_date <= date-em1) , each znd_det where znd_domain = zn_domain and znd_addr = zn_addr and znd_doc_type = zn_doc_type and znd_nbr = zn_nbr and znd_ret_nbr = zn_ret_nbr and znd_line = znd_line no-lock: /* Obtendo sub-totais por nota, qtdade e valor */ if teste <> zn_nbr then do: assign sub_qty = 0. assign sub_pri = 0. if znd_qty_item < 0 then sub_qty = sub_qty - znd_qty_item. else sub_qty = sub_qty + znd_qty_item. if znd_ext_price < 0 then sub_pri = sub_pri - znd_ext_price. else sub_pri = sub_pri + znd_ext_price. assign teste = zn_nbr. end. /* if */ else do: if znd_qty_item < 0 then sub_qty = sub_qty - znd_qty_item. else sub_qty = sub_qty + znd_qty_item. if znd_ext_price < 0 then sub_pri = sub_pri - znd_ext_price. else sub_pri = sub_pri + znd_ext_price. end. /* else */ /* Obtendo total geral por qtdade e valor */ if znd_qty_item < 0 then total_qty = total_qty - znd_qty_item. else total_qty = total_qty + znd_qty_item. if znd_ext_price < 0 then total_pri = total_pri - znd_ext_price. else total_pri = total_pri + znd_ext_price. if teste <> next (zn_mstr.zn_nbr)then display zn_addr zn_inv_date znd_part zn_nbr znd_line znd_desc znd_um znd_qty_item znd_ext_price sub_qty sub_pri with frame b. else display zn_addr zn_inv_date znd_part zn_nbr znd_line znd_desc znd_um znd_qty_item znd_ext_price with frame b. end. /* for each */ display total_qty total_pri with frame b. if not available zn_mstr then display "Sem registros encontrados". {mfrtrail.i} end. /* repeat */ Obrigado.
Meu caro, boa tarde! Você precisa pesquisar algo sobre ACCUM. Então deixa eu tentar te ajudar. Dentro do FOR EACH vc pode acumular valores de acordo com a ordem do For each. por exemplo. Código: FOR EACH ttNota BREAK BY ttNota.NUm_Doc. /* Aqui acumulando os subtotais.. devido ter declarado a ordem la no BREAK BY*/ ACCUM ttNota.Total (TOTAL BY ttNota.NUm_Doc). /* ACumulo do Total Geral */ ACCUM ttNota.Total (TOTAL). IF LAST-OF(ttNota.Num_Doc) THEN DO. /* MOstrando o SubTotal por Num_Doc definido no Break by */ DISPLAY ACCUM TOTAL BY ttNota.NUm_Doc ttNota.Total. END. IF LAST(ttNota.Num_Doc) THEN DO. /* Mostrando o Total Geral */ DISPLAY ACCUM TOTAL ttNota.Total. END. END. /*For Each*/ Entao o ACCUM pra vc usar, tem que ser na Ordem do BREAK BY, e entao vc usa o Subtotal no LAst-OF(tabela.campo) e mostra o ACCUM TOTAL BY tabela.campo tabela.campodototal .(ACCUM TOTAL BY ttNota.Num_Doc ttNota.Total) por ex. Veja se lhe ajuda.. qq coisa add ai eriutoncharles no skype ou msn que estes coisinhas mais simples eu posso te ajudar